diff options
author | Kajur, Harish (vk250x) <vk250x@att.com> | 2020-02-21 14:34:10 -0500 |
---|---|---|
committer | Harish Venkata Kajur <vk250x@att.com> | 2020-02-25 23:59:33 -0500 |
commit | 98749c47bbb5f5ddcc1c4f0690b79c7288f6bdd6 (patch) | |
tree | a472ce2edabd497b643917f44785b775fa16e15e /aai-core | |
parent | e654645a50a0d028d8e67ea997f84efe8d28a6a0 (diff) |
Enhancements for the aai-common library
Issue-ID: AAI-2806
Change-Id: I2dbb46b897b35136ac1bb802978d3f974af1b307
Signed-off-by: Kajur, Harish (vk250x) <vk250x@att.com>
Diffstat (limited to 'aai-core')
246 files changed, 14132 insertions, 9457 deletions
diff --git a/aai-core/pom.xml b/aai-core/pom.xml index ec4e7e38..cb0281a6 100644 --- a/aai-core/pom.xml +++ b/aai-core/pom.xml @@ -39,7 +39,7 @@ limitations under the License. <jacoco.line.coverage.limit>0.50</jacoco.line.coverage.limit> <gremlin.version>3.2.2</gremlin.version> - <groovy.version>2.4.15</groovy.version> + <groovy.version>2.4.15</groovy.version> <!-- Start of Default ONAP Schema Properties --> <aai.wiki.link>https://wiki.onap.org/</aai.wiki.link> <gendoc.version>v15</gendoc.version> @@ -98,7 +98,7 @@ limitations under the License. <version>2.8</version> </plugin> <plugin> - <!-- explicitly define maven-deploy-plugin after other to force exec + <!-- explicitly define maven-deploy-plugin after other to force exec order --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> @@ -117,6 +117,10 @@ limitations under the License. </dependency> <dependency> <groupId>org.onap.aai.aai-common</groupId> + <artifactId>aai-aaf-auth</artifactId> + </dependency> + <dependency> + <groupId>org.onap.aai.aai-common</groupId> <artifactId>aai-annotations</artifactId> </dependency> <dependency> @@ -132,11 +136,11 @@ limitations under the License. <groupId>com.att.eelf</groupId> <artifactId>eelf-core</artifactId> <exclusions><!-- excluding transitive dependency coming from this artifact, as we would need powermock-api-mockito2--> - <exclusion> - <groupId>org.powermock</groupId> - <artifactId>powermock-api-mockito</artifactId> - </exclusion> - </exclusions> + <exclusion> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> @@ -167,20 +171,10 @@ limitations under the License. <scope>test</scope> </dependency> <dependency> - <groupId>org.powermock</groupId> - <artifactId>powermock-module-junit4</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.powermock</groupId> - <artifactId>powermock-api-mockito2</artifactId> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> - <dependency> - <groupId>org.powermock</groupId> - <artifactId>powermock-core</artifactId> - <scope>test</scope> - </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> @@ -224,6 +218,11 @@ limitations under the License. <artifactId>json-path</artifactId> </dependency> <dependency> + <groupId>com.jayway.jsonpath</groupId> + <artifactId>json-path-assert</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util</artifactId> </dependency> @@ -244,10 +243,6 @@ limitations under the License. <artifactId>jersey-json</artifactId> </dependency> <dependency> - <groupId>javax.ws.rs</groupId> - <artifactId>javax.ws.rs-api</artifactId> - </dependency> - <dependency> <groupId>org.apache.tinkerpop</groupId> <artifactId>gremlin-core</artifactId> </dependency> @@ -286,10 +281,6 @@ limitations under the License. </dependency> <dependency> - <groupId>javax.servlet</groupId> - <artifactId>javax.servlet-api</artifactId> - </dependency> - <dependency> <groupId>com.bazaarvoice.jolt</groupId> <artifactId>jolt-complete</artifactId> </dependency> diff --git a/aai-core/src/main/java/org/onap/aai/audit/ListEndpoints.java b/aai-core/src/main/java/org/onap/aai/audit/ListEndpoints.java index dcfd58a5..fe2e1ff7 100644 --- a/aai-core/src/main/java/org/onap/aai/audit/ListEndpoints.java +++ b/aai-core/src/main/java/org/onap/aai/audit/ListEndpoints.java @@ -22,8 +22,8 @@ package org.onap.aai.audit; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.CaseFormat; import java.util.ArrayList; @@ -53,7 +53,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext */ public class ListEndpoints { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ListEndpoints.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ListEndpoints.class); private static final String START = "inventory"; private static final String[] blacklist = {"search", "aai-internal"}; diff --git a/aai-core/src/main/java/org/onap/aai/auth/AAIAuthCore.java b/aai-core/src/main/java/org/onap/aai/auth/AAIAuthCore.java deleted file mode 100644 index cde2faa3..00000000 --- a/aai-core/src/main/java/org/onap/aai/auth/AAIAuthCore.java +++ /dev/null @@ -1,372 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.auth; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.UnsupportedEncodingException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import org.eclipse.jetty.util.security.Password; -import org.eclipse.persistence.internal.oxm.conversion.Base64; -import org.onap.aai.auth.exceptions.AAIUnrecognizedFunctionException; -import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.logging.LoggingContext; -import org.onap.aai.logging.LoggingContext.StatusCode; -import org.onap.aai.util.AAIConfig; -import org.onap.aai.util.AAIConstants; -import org.onap.aai.util.FileWatcher; - -/** - * The Class AAIAuthCore. - */ -public final class AAIAuthCore { - - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIAuthCore.class); - - private static final String ERROR_CODE_AAI_4001 = "AAI_4001"; - - private String globalAuthFileName = AAIConstants.AAI_AUTH_CONFIG_FILENAME; - - private final Pattern AUTH_POLICY_PATTERN; - private final Set<String> validFunctions = new HashSet<>(); - private Map<String, AAIUser> users; - private boolean timerSet = false; - private Timer timer = null; - - private String basePath; - - /** - * Instantiates a new AAI auth core. - */ - public AAIAuthCore(String basePath) { - this.basePath = basePath; - AUTH_POLICY_PATTERN = Pattern.compile("^" + this.basePath + "/v\\d+/([\\w\\-]*)"); - init(); - } - - /** - * Inits the. - */ - private synchronized void init() { - - LOGGER.debug("Initializing Auth Policy Config"); - - reloadUsers(); - - /* - * this timer code is setting up a recurring task that checks if the - * auth config file has been updated and reloads the users if so to get - * the most up to date info (that update check logic is within - * FileWatcher) - * - * the timing this method uses is coarser than the frequency of requests - * AI&I gets so we're looking at better ways of doing this (TODO) - */ - TimerTask task = new FileWatcher(new File(globalAuthFileName)) { - @Override - protected void onChange(File file) { - reloadUsers(); - } - }; - - if (!timerSet) { - timerSet = true; - timer = new Timer(); - - // repeat the check every second - timer.schedule(task, new Date(), 10000); - } - LOGGER.debug("Static Initializiation complete"); - } - - /** - * Cleanup. - */ - // just ends the auth config file update checking timer - public void cleanup() { - timer.cancel(); - } - - /** - * Reload users. - */ - /* - * this essentially takes the data file, which is organized role-first with - * users under each role and converts it to data organized user-first with - * each user containing their role with its associated allowed functions - * this data stored in the class field users - */ - private synchronized void reloadUsers() { - - Map<String, AAIUser> tempUsers = new HashMap<>(); - - try { - LOGGER.debug("Reading from " + globalAuthFileName); - String authFile = new String(Files.readAllBytes(Paths.get(globalAuthFileName))); - - JsonParser parser = new JsonParser(); - JsonObject authObject = parser.parse(authFile).getAsJsonObject(); - if (authObject.has("roles")) { - JsonArray roles = authObject.getAsJsonArray("roles"); - for (JsonElement role : roles) { - if (role.isJsonObject()) { - JsonObject roleObject = role.getAsJsonObject(); - String roleName = roleObject.get("name").getAsString(); - Map<String, Boolean> usrs = this.getUsernamesFromRole(roleObject); - List<String> aaiFunctions = this.getAAIFunctions(roleObject); - - usrs.forEach((key, value) -> { - final AAIUser au = tempUsers.getOrDefault(key, new AAIUser(key, value)); - au.addRole(roleName); - aaiFunctions.forEach(f -> { - List<String> httpMethods = this.getRoleHttpMethods(f, roleObject); - httpMethods.forEach(hm -> au.setUserAccess(f, hm)); - this.validFunctions.add(f); - }); - - tempUsers.put(key, au); - - }); - } - } - if (!tempUsers.isEmpty()) { - users = tempUsers; - } - } - } catch (FileNotFoundException e) { - ErrorLogHelper.logError(ERROR_CODE_AAI_4001, globalAuthFileName + ". Exception: " + e); - } catch (JsonProcessingException e) { - ErrorLogHelper.logError(ERROR_CODE_AAI_4001, globalAuthFileName + ". Not valid JSON: " + e); - } catch (Exception e) { - ErrorLogHelper.logError(ERROR_CODE_AAI_4001, globalAuthFileName + ". Exception caught: " + e); - } - } - - private List<String> getRoleHttpMethods(String aaiFunctionName, JsonObject roleObject) { - List<String> httpMethods = new ArrayList<>(); - - JsonArray ja = roleObject.getAsJsonArray("functions"); - for (JsonElement je : ja) { - if (je.isJsonObject() && je.getAsJsonObject().has("name") - && je.getAsJsonObject().get("name").getAsString().equals(aaiFunctionName)) { - JsonArray jaMeth = je.getAsJsonObject().getAsJsonArray("methods"); - for (JsonElement jeMeth : jaMeth) { - if (jeMeth.isJsonObject() && jeMeth.getAsJsonObject().has("name")) { - httpMethods.add(jeMeth.getAsJsonObject().get("name").getAsString()); - } - } - } - } - - return httpMethods; - } - - private List<String> getAAIFunctions(JsonObject roleObject) { - List<String> aaiFunctions = new ArrayList<>(); - - JsonArray ja = roleObject.getAsJsonArray("functions"); - for (JsonElement je : ja) { - if (je.isJsonObject() && je.getAsJsonObject().has("name")) { - aaiFunctions.add(je.getAsJsonObject().get("name").getAsString()); - } - } - - return aaiFunctions; - } - - private Map<String, Boolean> getUsernamesFromRole(JsonObject roleObject) throws UnsupportedEncodingException { - Map<String, Boolean> usernames = new HashMap<>(); - - JsonArray uja = roleObject.getAsJsonArray("users"); - for (JsonElement je : uja) { - if (je.isJsonObject()) { - if (je.getAsJsonObject().has("username")) { - if (je.getAsJsonObject().has("is-wildcard-id")) { - usernames.put(je.getAsJsonObject().get("username").getAsString().toLowerCase(), - je.getAsJsonObject().get("is-wildcard-id").getAsBoolean()); - } else { - usernames.put(je.getAsJsonObject().get("username").getAsString().toLowerCase(), false); - } - } else if (je.getAsJsonObject().has("user")) { - String auth = je.getAsJsonObject().get("user").getAsString() + ":" - + Password.deobfuscate(je.getAsJsonObject().get("pass").getAsString()); - String authorizationCode = new String(Base64.base64Encode(auth.getBytes("utf-8"))); - usernames.put(authorizationCode, false); - } - } - } - - return usernames; - } - - public String getAuthPolicyFunctName(String uri) { - String authPolicyFunctionName = ""; - if (uri.startsWith(basePath + "/search")) { - authPolicyFunctionName = "search"; - } else if (uri.startsWith(basePath + "/recents")) { - authPolicyFunctionName = "recents"; - } else if (uri.startsWith(basePath + "/cq2gremlin")) { - authPolicyFunctionName = "cq2gremlin"; - } else if (uri.startsWith(basePath + "/cq2gremlintest")) { - authPolicyFunctionName = "cq2gremlintest"; - } else if (uri.startsWith(basePath + "/util/echo")) { - authPolicyFunctionName = "util"; - } else if (uri.startsWith(basePath + "/tools")) { - authPolicyFunctionName = "tools"; - } else { - Matcher match = AUTH_POLICY_PATTERN.matcher(uri); - if (match.find()) { - authPolicyFunctionName = match.group(1); - } - } - return authPolicyFunctionName; - } - - /** - * for backwards compatibility - * - * @param username - * @param uri - * @param httpMethod - * @param haProxyUser - * @return - * @throws AAIUnrecognizedFunctionException - */ - public boolean authorize(String username, String uri, String httpMethod, String haProxyUser) - throws AAIUnrecognizedFunctionException { - return authorize(username, uri, httpMethod, haProxyUser, null); - } - - /** - * - * @param username - * @param uri - * @param httpMethod - * @param haProxyUser - * @param issuer issuer of the cert - * @return - * @throws AAIUnrecognizedFunctionException - */ - public boolean authorize(String username, String uri, String httpMethod, String haProxyUser, String issuer) - throws AAIUnrecognizedFunctionException { - String aaiMethod = this.getAuthPolicyFunctName(uri); - if (!this.validFunctions.contains(aaiMethod)) { - throw new AAIUnrecognizedFunctionException(aaiMethod); - } - boolean wildcardCheck = isWildcardIssuer(issuer); - boolean authorized; - LOGGER.debug( - "Authorizing the user for the request cert {}, haproxy header {}, aai method {}, httpMethod {}, cert issuer {}", - username, haProxyUser, aaiMethod, httpMethod, issuer); - Optional<AAIUser> oau = this.getUser(username, wildcardCheck); - if (oau.isPresent()) { - AAIUser au = oau.get(); - if (au.hasRole("HAProxy")) { - LOGGER.debug("User has HAProxy role"); - if ("GET".equalsIgnoreCase(httpMethod) && "util".equalsIgnoreCase(aaiMethod) && haProxyUser.isEmpty()) { - LOGGER.debug("Authorized user has HAProxy role with echo request"); - authorized = this.authorize(au, aaiMethod, httpMethod); - } else { - authorized = this.authorize(haProxyUser, uri, httpMethod, "", issuer); - } - } else { - LOGGER.debug("User doesn't have HAProxy role so assuming its a regular client"); - authorized = this.authorize(au, aaiMethod, httpMethod); - } - } else { - LOGGER.debug("User not found: " + username + " on function " + aaiMethod + " request type " + httpMethod); - authorized = false; - } - - return authorized; - } - - private boolean isWildcardIssuer(String issuer) { - if (issuer != null && !issuer.isEmpty()) { - List<String> validIssuers = Arrays - .asList(AAIConfig.get("aaf.valid.issuer.wildcard", UUID.randomUUID().toString()).split("\\|")); - for (String validIssuer : validIssuers) { - if (issuer.contains(validIssuer)) { - return true; - } - } - } - return false; - } - - /** - * returns aai user either matching the username or containing the wildcard. - * - * @param username - * @return - */ - public Optional<AAIUser> getUser(String username, boolean wildcardCheck) { - if (users.containsKey(username)) { - return Optional.of(users.get(username)); - } else if (wildcardCheck) { - List<AAIUser> laus = - users.entrySet().stream().filter(e -> e.getValue().isWildcard() && username.contains(e.getKey())) - .map(Map.Entry::getValue).collect(Collectors.toList()); - if (!laus.isEmpty()) { - return Optional.of(laus.get(0)); - } - } - return Optional.empty(); - } - - /** - * - * @param aaiUser - * aai user with the username - * @param aaiMethod - * aai function the authorization is required on - * @param httpMethod - * http action user is attempting - * @return true, if successful - */ - private boolean authorize(AAIUser aaiUser, String aaiMethod, String httpMethod) { - if (aaiUser.hasAccess(aaiMethod, httpMethod)) { - LoggingContext.statusCode(StatusCode.COMPLETE); - LOGGER.debug("AUTH ACCEPTED: " + aaiUser.getUsername() + " on function " + aaiMethod + " request type " - + httpMethod); - return true; - } else { - LoggingContext.statusCode(StatusCode.ERROR); - LOGGER.debug("AUTH FAILED: " + aaiUser.getUsername() + " on function " + aaiMethod + " request type " - + httpMethod); - return false; - } - } -} diff --git a/aai-core/src/main/java/org/onap/aai/auth/AAIUser.java b/aai-core/src/main/java/org/onap/aai/auth/AAIUser.java deleted file mode 100644 index f1e1b084..00000000 --- a/aai-core/src/main/java/org/onap/aai/auth/AAIUser.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Modifications Copyright © 2018 IBM. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.auth; - -import java.util.*; - -public class AAIUser { - - private String username; - - private boolean isWildcard = false; - private Set<String> roles; - private Map<String, Set<String>> aaiFunctionToHttpMethod; - - public AAIUser(String username) { - this(username, false); - } - - public AAIUser(String username, boolean isWildcard) { - this.username = username; - this.roles = new HashSet<>(); - this.aaiFunctionToHttpMethod = new HashMap<>(); - this.isWildcard = isWildcard; - } - - public boolean isWildcard() { - return isWildcard; - } - - public String getUsername() { - return username; - } - - public void addRole(String role) { - this.roles.add(role); - } - - public boolean hasRole(String role) { - return this.roles.contains(role); - } - - public void setUserAccess(String aaiMethod, String... httpMethods) { - for (String httpMethod : httpMethods) { - this.addUserAccess(aaiMethod, httpMethod); - } - } - - private void addUserAccess(String aaiMethod, String httpMethod) { - Set<String> httpMethods = new HashSet<>(); - if (this.aaiFunctionToHttpMethod.containsKey(aaiMethod)) { - httpMethods = this.aaiFunctionToHttpMethod.get(aaiMethod); - } - httpMethods.add(httpMethod); - this.aaiFunctionToHttpMethod.put(aaiMethod, httpMethods); - } - - public boolean hasAccess(String aaiMethod, String httpMethod) { - return this.aaiFunctionToHttpMethod.getOrDefault(aaiMethod, Collections.emptySet()).contains(httpMethod); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/auth/exceptions/AAIUnrecognizedFunctionException.java b/aai-core/src/main/java/org/onap/aai/auth/exceptions/AAIUnrecognizedFunctionException.java deleted file mode 100644 index 1410b445..00000000 --- a/aai-core/src/main/java/org/onap/aai/auth/exceptions/AAIUnrecognizedFunctionException.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Modifications Copyright © 2018 IBM. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.auth.exceptions; - -import org.onap.aai.exceptions.AAIException; - -public class AAIUnrecognizedFunctionException extends AAIException { - - private static final String AAI_3012 = "AAI_3012"; - private static final long serialVersionUID = 3297064867724071290L; - - public AAIUnrecognizedFunctionException() { - } - - public AAIUnrecognizedFunctionException(String message) { - super(AAI_3012, message); - } - - public AAIUnrecognizedFunctionException(Throwable cause) { - super(AAI_3012, cause); - } - - public AAIUnrecognizedFunctionException(String message, Throwable cause) { - super(AAI_3012, cause, message); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/concurrent/AaiCallable.java b/aai-core/src/main/java/org/onap/aai/concurrent/AaiCallable.java index 6ea67b90..69560ec1 100644 --- a/aai-core/src/main/java/org/onap/aai/concurrent/AaiCallable.java +++ b/aai-core/src/main/java/org/onap/aai/concurrent/AaiCallable.java @@ -44,7 +44,9 @@ public abstract class AaiCallable<T> implements Callable<T> { * The call method */ public T call() throws Exception { - MDC.setContextMap(mdcCopy); + if ( mdcCopy != null ) { + MDC.setContextMap(mdcCopy); + } return process(); } diff --git a/aai-core/src/main/java/org/onap/aai/config/AuthorizationConfiguration.java b/aai-core/src/main/java/org/onap/aai/config/AuthorizationConfiguration.java index 9f8bbc45..24e7ec5a 100644 --- a/aai-core/src/main/java/org/onap/aai/config/AuthorizationConfiguration.java +++ b/aai-core/src/main/java/org/onap/aai/config/AuthorizationConfiguration.java @@ -20,7 +20,7 @@ package org.onap.aai.config; -import org.onap.aai.auth.AAIAuthCore; +import org.onap.aai.aaf.auth.AAIAuthCore; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/aai-core/src/main/java/org/onap/aai/logging/CustomLogPatternLayoutEncoder.java b/aai-core/src/main/java/org/onap/aai/config/XmlFormatTransformerConfiguration.java index 010d828b..0c83c2b3 100644 --- a/aai-core/src/main/java/org/onap/aai/logging/CustomLogPatternLayoutEncoder.java +++ b/aai-core/src/main/java/org/onap/aai/config/XmlFormatTransformerConfiguration.java @@ -17,24 +17,17 @@ * limitations under the License. * ============LICENSE_END========================================================= */ +package org.onap.aai.config; -package org.onap.aai.logging; +import org.onap.aai.transforms.XmlFormatTransformer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; -import ch.qos.logback.access.PatternLayout; +@Configuration +public class XmlFormatTransformerConfiguration { -public class CustomLogPatternLayoutEncoder extends ch.qos.logback.access.PatternLayoutEncoder { - - /** - * @{inheritDoc} - */ - @Override - public void start() { - PatternLayout patternLayout = new CustomLogPatternLayout(); - patternLayout.setContext(context); - patternLayout.setPattern(getPattern()); - patternLayout.start(); - this.layout = patternLayout; - super.start(); + @Bean + public XmlFormatTransformer xmlFormatTransformer(){ + return new XmlFormatTransformer(); } - } diff --git a/aai-core/src/main/java/org/onap/aai/db/props/AAIProperties.java b/aai-core/src/main/java/org/onap/aai/db/props/AAIProperties.java index a0f6d77e..7dbc3a1d 100644 --- a/aai-core/src/main/java/org/onap/aai/db/props/AAIProperties.java +++ b/aai-core/src/main/java/org/onap/aai/db/props/AAIProperties.java @@ -32,9 +32,15 @@ public class AAIProperties { public static final String RESOURCE_VERSION = "resource-version"; public static final String AAI_URI = "aai-uri"; public static final Integer MAXIMUM_DEPTH = 10000; + public static final Integer MINIMUM_DEPTH = 0; public static final String LINKED = "linked"; public static final String DB_ALIAS_SUFFIX = "-local"; public static final String AAI_UUID = "aai-uuid"; + public static final String START_TS = "start-ts"; + public static final String END_TS = "end-ts"; + public static final String END_SOT = "end-source-of-truth"; + public static final String START_TX_ID = "start-tx-id"; + public static final String END_TX_ID = "end-tx-id"; private AAIProperties() { diff --git a/aai-core/src/main/java/org/onap/aai/dbgen/GraphSONPartialReader.java b/aai-core/src/main/java/org/onap/aai/dbgen/GraphSONPartialReader.java index fdc8e814..d3dfd150 100644 --- a/aai-core/src/main/java/org/onap/aai/dbgen/GraphSONPartialReader.java +++ b/aai-core/src/main/java/org/onap/aai/dbgen/GraphSONPartialReader.java @@ -20,8 +20,8 @@ package org.onap.aai.dbgen; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.ByteArrayInputStream; @@ -77,7 +77,7 @@ public final class GraphSONPartialReader implements GraphReader { private boolean unwrapAdjacencyList = false; private final GraphSONReader reader; - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(InMemoryGraph.class); + private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryGraph.class); final TypeReference<Map<String, Object>> mapTypeReference = new TypeReference<Map<String, Object>>() {}; diff --git a/aai-core/src/main/java/org/onap/aai/dbgen/SchemaGenerator.java b/aai-core/src/main/java/org/onap/aai/dbgen/SchemaGenerator.java index bfd1f55b..d253f876 100644 --- a/aai-core/src/main/java/org/onap/aai/dbgen/SchemaGenerator.java +++ b/aai-core/src/main/java/org/onap/aai/dbgen/SchemaGenerator.java @@ -20,8 +20,8 @@ package org.onap.aai.dbgen; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.collect.Multimap; import java.util.HashMap; @@ -49,7 +49,7 @@ import org.onap.aai.util.AAIConfig; public class SchemaGenerator { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(SchemaGenerator.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SchemaGenerator.class); /** * Load schema into JanusGraph. diff --git a/aai-core/src/main/java/org/onap/aai/dbgen/SchemaGenerator4Hist.java b/aai-core/src/main/java/org/onap/aai/dbgen/SchemaGenerator4Hist.java new file mode 100644 index 00000000..0f88de24 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/dbgen/SchemaGenerator4Hist.java @@ -0,0 +1,238 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.dbgen; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.common.collect.Multimap; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.Cardinality; +import org.janusgraph.core.JanusGraph; +import org.janusgraph.core.Multiplicity; +import org.janusgraph.core.PropertyKey; +import org.janusgraph.core.schema.JanusGraphManagement; +import org.onap.aai.config.SpringContextAware; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.edges.EdgeRule; +import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.LoaderUtil; +import org.onap.aai.logging.LogFormatTools; +import org.onap.aai.schema.enums.PropertyMetadata; +import org.onap.aai.util.AAIConfig; + +import java.util.*; + +import static org.onap.aai.db.props.AAIProperties.*; + +public class SchemaGenerator4Hist { + + private static final Logger LOGGER = LoggerFactory.getLogger(SchemaGenerator4Hist.class); + + /** + * Load schema into JanusGraph. + * + * @param graph + * the graph + * @param graphMgmt + * the graph mgmt + */ + public static void loadSchemaIntoJanusGraph(final JanusGraph graph, final JanusGraphManagement graphMgmt, + String backend) { + + try { + AAIConfig.init(); + } catch (Exception ex) { + LOGGER.error(" ERROR - Could not run AAIConfig.init(). " + LogFormatTools.getStackTop(ex)); + // System.out.println(" ERROR - Could not run AAIConfig.init(). "); + System.exit(1); + } + + // NOTE - JanusGraph 0.5.3 doesn't keep a list of legal node Labels. + // They are only used when a vertex is actually being created. + // JanusGraph 1.1 will keep track (we think). + + // Use EdgeRules to make sure edgeLabels are defined in the db. NOTE: + // the multiplicty used here is + // always "MULTI". This is not the same as our internal "Many2Many", + // "One2One", "One2Many" or "Many2One" + // We use the same edge-label for edges between many different types of + // nodes and our internal + // multiplicty definitions depends on which two types of nodes are being + // connected. + + Multimap<String, EdgeRule> edges = null; + Set<String> labels = new HashSet<>(); + + EdgeIngestor edgeIngestor = SpringContextAware.getBean(EdgeIngestor.class); + + try { + edges = edgeIngestor.getAllCurrentRules(); + } catch (EdgeRuleNotFoundException e) { + LOGGER.error("Unable to find all rules {}", LogFormatTools.getStackTop(e)); + } + + for (EdgeRule rule : edges.values()) { + labels.add(rule.getLabel()); + } + + for (String label : labels) { + if (graphMgmt.containsRelationType(label)) { + String dmsg = " EdgeLabel [" + label + "] already existed. "; + LOGGER.debug(dmsg); + } else { + String dmsg = "Making EdgeLabel: [" + label + "]"; + LOGGER.debug(dmsg); + graphMgmt.makeEdgeLabel(label).multiplicity(Multiplicity.valueOf("MULTI")).make(); + } + } + + Loader loader = LoaderUtil.getLatestVersion(); + + Map<String, Introspector> objs = loader.getAllObjects(); + Map<String, PropertyKey> seenProps = new HashMap<>(); + + for (Introspector obj : objs.values()) { + for (String propName : obj.getProperties()) { + String dbPropName = propName; + Optional<String> alias = obj.getPropertyMetadata(propName, PropertyMetadata.DB_ALIAS); + if (alias.isPresent()) { + dbPropName = alias.get(); + } + if (graphMgmt.containsRelationType(dbPropName)) { + String dmsg = " PropertyKey [" + dbPropName + "] already existed in the DB. "; + LOGGER.debug(dmsg); + } else { + Class<?> type = obj.getClass(propName); + Cardinality cardinality = Cardinality.LIST; + boolean process = false; + if (obj.isListType(propName) && obj.isSimpleGenericType(propName)) { + // NOTE - For history - All properties have cardinality = LIST + // It is assumed that there is special processing in the Resources MS + // for History to turn what used to be SET (referred to as isListType + // above) will be stored in our db as a single String. And that + // single string will have Cardinality = LIST so we can track its + // history. + //cardinality = Cardinality.SET; + type = obj.getGenericTypeClass(propName); + process = true; + } else if (obj.isSimpleType(propName)) { + process = true; + } + + if (process) { + + String imsg = " Creating PropertyKey: [" + dbPropName + "], [" + type.getSimpleName() + "], [" + + cardinality + "]"; + LOGGER.info(imsg); + PropertyKey propK; + if (!seenProps.containsKey(dbPropName)) { + propK = graphMgmt.makePropertyKey(dbPropName).dataType(type).cardinality(cardinality) + .make(); + seenProps.put(dbPropName, propK); + } else { + propK = seenProps.get(dbPropName); + } + if (graphMgmt.containsGraphIndex(dbPropName)) { + String dmsg = " Index [" + dbPropName + "] already existed in the DB. "; + LOGGER.debug(dmsg); + } else { + if (obj.getIndexedProperties().contains(propName)) { + // NOTE - for History we never add a unique index - just a regular index + imsg = "Add index for PropertyKey: [" + dbPropName + "]"; + LOGGER.info(imsg); + graphMgmt.buildIndex(dbPropName, Vertex.class).addKey(propK).buildCompositeIndex(); + } else { + imsg = "No index needed/added for PropertyKey: [" + dbPropName + "]"; + LOGGER.info(imsg); + } + } + } + } + } + }// Done processing all properties defined in the OXM + + // Add the 3 new History properties are in the DB + // They are all Cardinality=Single since instance of a Node, Edge or Property can + // only have one of them. That is, a Property can show up many times in a + // node, but each instance of that property will only have a single start-ts, + // end-ts, end-source-of-truth. Same goes for a node or edge itself. + if (graphMgmt.containsRelationType(END_SOT)) { + String dmsg = "PropertyKey [" + END_SOT + "] already existed in the DB. "; + LOGGER.debug(dmsg); + } else if (!seenProps.containsKey(END_SOT) ) { + String imsg = " Creating PropertyKey: [" + END_SOT + "], [String], [SINGLE]"; + LOGGER.info(imsg); + graphMgmt.makePropertyKey(END_SOT).dataType(String.class) + .cardinality(Cardinality.SINGLE).make(); + } + + if (graphMgmt.containsRelationType(START_TS)) { + String dmsg = " PropertyKey [" + START_TS + "] already existed in the DB. "; + LOGGER.debug(dmsg); + } else if (!seenProps.containsKey(START_TS) ) { + String imsg = " Creating PropertyKey: [" + START_TS + "], [Long], [SINGLE]"; + LOGGER.info(imsg); + graphMgmt.makePropertyKey(START_TS).dataType(Long.class) + .cardinality(Cardinality.SINGLE).make(); + } + + if (graphMgmt.containsRelationType(END_TS)) { + String dmsg = "PropertyKey [" + END_TS + "] already existed in the DB. "; + LOGGER.debug(dmsg); + } else if (!seenProps.containsKey(END_TS) ) { + String imsg = " Creating PropertyKey: [" + END_TS + "], [Long], [SINGLE]"; + LOGGER.info(imsg); + graphMgmt.makePropertyKey(END_TS).dataType(Long.class) + .cardinality(Cardinality.SINGLE).make(); + } + + if (graphMgmt.containsRelationType(START_TX_ID)) { + String dmsg = "PropertyKey [" + START_TX_ID + "] already existed in the DB. "; + LOGGER.debug(dmsg); + } else if (!seenProps.containsKey(START_TX_ID) ) { + String imsg = " Creating PropertyKey: [" + START_TX_ID + "], [String], [SINGLE]"; + LOGGER.info(imsg); + graphMgmt.makePropertyKey(START_TX_ID).dataType(String.class) + .cardinality(Cardinality.SINGLE).make(); + } + + if (graphMgmt.containsRelationType(END_TX_ID)) { + String dmsg = "PropertyKey [" + END_TX_ID + "] already existed in the DB. "; + LOGGER.debug(dmsg); + } else if (!seenProps.containsKey(END_TX_ID) ) { + String imsg = " Creating PropertyKey: [" + END_TX_ID + "], [String], [SINGLE]"; + LOGGER.info(imsg); + graphMgmt.makePropertyKey(END_TX_ID).dataType(String.class) + .cardinality(Cardinality.SINGLE).make(); + } + + String imsg = "-- About to call graphMgmt commit"; + LOGGER.info(imsg); + graphMgmt.commit(); + if (backend != null) { + LOGGER.info("Successfully loaded the schema to " + backend); + } + + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/dbmap/AAIGraph.java b/aai-core/src/main/java/org/onap/aai/dbmap/AAIGraph.java index ca4e02f0..5bb4b656 100644 --- a/aai-core/src/main/java/org/onap/aai/dbmap/AAIGraph.java +++ b/aai-core/src/main/java/org/onap/aai/dbmap/AAIGraph.java @@ -22,13 +22,8 @@ package org.onap.aai.dbmap; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; -import java.io.FileNotFoundException; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import org.apache.commons.configuration.ConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.tinkerpop.gremlin.structure.Graph; @@ -36,10 +31,15 @@ import org.apache.tinkerpop.gremlin.structure.io.IoCore; import org.janusgraph.core.JanusGraph; import org.janusgraph.core.JanusGraphFactory; import org.janusgraph.core.schema.JanusGraphManagement; +import org.onap.aai.config.SpringContextAware; import org.onap.aai.dbgen.SchemaGenerator; +import org.onap.aai.dbgen.SchemaGenerator4Hist; import org.onap.aai.exceptions.AAIException; import org.onap.aai.util.AAIConstants; +import java.io.FileNotFoundException; +import java.util.Properties; + /** * Database Mapping class which acts as the middle man between the REST * interface objects and JanusGraph DB objects. This class provides methods to commit @@ -48,16 +48,13 @@ import org.onap.aai.util.AAIConstants; * object to load, commit/rollback and shutdown for each request. The data model * rules such as keys/required properties are handled by calling DBMeth methods * which are driven by a specification file in json. - * - * + * + * */ public class AAIGraph { - private static final EELFLogger logger = EELFManager.getInstance().getLogger(AAIGraph.class); - protected static final String COMPONENT = "aaidbmap"; - protected Map<String, JanusGraph> graphs = new HashMap<>(); - private static final String REALTIME_DB = "realtime"; - private static final String CACHED_DB = "cached"; + private static final Logger logger = LoggerFactory.getLogger(AAIGraph.class); + protected JanusGraph graph; private static boolean isInit = false; /** @@ -67,15 +64,10 @@ public class AAIGraph { try { String serviceName = System.getProperty("aai.service.name", "NA"); String rtConfig = System.getProperty("realtime.db.config"); - String cachedConfig = System.getProperty("cached.db.config"); if (rtConfig == null) { rtConfig = AAIConstants.REALTIME_DB_CONFIG; } - if (cachedConfig == null) { - cachedConfig = AAIConstants.CACHED_DB_CONFIG; - } - this.loadGraph(REALTIME_DB, rtConfig, serviceName); - this.loadGraph(CACHED_DB, cachedConfig, serviceName); + this.loadGraph(rtConfig, serviceName); } catch (Exception e) { throw new RuntimeException("Failed to instantiate graphs", e); } @@ -103,18 +95,17 @@ public class AAIGraph { return isInit; } - private void loadGraph(final String name, final String configPath, final String serviceName) - throws AAIException, ConfigurationException { + private void loadGraph(String configPath, String serviceName) throws Exception { // Graph being opened by JanusGraphFactory is being placed in hashmap to be used later // These graphs shouldn't be closed until the application shutdown try { - final PropertiesConfiguration propertiesConfiguration = - new AAIGraphConfig.Builder(configPath).forService(serviceName).withGraphType(name).buildConfiguration(); - final JanusGraph graph = JanusGraphFactory.open(propertiesConfiguration); + PropertiesConfiguration propertiesConfiguration = new AAIGraphConfig.Builder(configPath) + .forService(serviceName).withGraphType("realtime").buildConfiguration(); + graph = JanusGraphFactory.open(propertiesConfiguration); - final Properties graphProps = new Properties(); + Properties graphProps = new Properties(); propertiesConfiguration.getKeys() - .forEachRemaining(k -> graphProps.setProperty(k, propertiesConfiguration.getString(k))); + .forEachRemaining(k -> graphProps.setProperty(k, propertiesConfiguration.getString(k))); if ("inmemory".equals(graphProps.get("storage.backend"))) { // Load the propertyKeys, indexes and edge-Labels into the DB @@ -126,13 +117,12 @@ public class AAIGraph { throw new AAIException("AAI_5102"); } - graphs.put(name, graph); - } catch (final FileNotFoundException fnfe) { - throw new AAIException("AAI_4001"); + } catch (FileNotFoundException e) { + throw new AAIException("AAI_4001", e); } } - private void loadSnapShotToInMemoryGraph(final JanusGraph graph, final Properties graphProps) { + private void loadSnapShotToInMemoryGraph(JanusGraph graph, Properties graphProps) { if (logger.isDebugEnabled()) { logger.debug("Load Snapshot to InMemory Graph"); } @@ -141,12 +131,12 @@ public class AAIGraph { if ("true".equals(value)) { try (Graph transaction = graph.newTransaction()) { String location = System.getProperty("snapshot.location"); - logAndPrint(logger, "Loading snapshot to inmemory graph."); + logAndPrint("Loading snapshot to inmemory graph."); transaction.io(IoCore.graphson()).readGraph(location); transaction.tx().commit(); - logAndPrint(logger, "Snapshot loaded to inmemory graph."); + logAndPrint("Snapshot loaded to inmemory graph."); } catch (Exception e) { - logAndPrint(logger, "ERROR: Could not load datasnapshot to in memory graph. \n" + logAndPrint("ERROR: Could not load datasnapshot to in memory graph. \n" + ExceptionUtils.getFullStackTrace(e)); throw new RuntimeException(e); } @@ -154,19 +144,25 @@ public class AAIGraph { } } - private void loadSchema(final JanusGraph graph) { + private void loadSchema(JanusGraph graph) { // Load the propertyKeys, indexes and edge-Labels into the DB JanusGraphManagement graphMgt = graph.openManagement(); System.out.println("-- loading schema into JanusGraph"); - SchemaGenerator.loadSchemaIntoJanusGraph(graph, graphMgt, "inmemory"); + if ("true".equals(SpringContextAware.getApplicationContext().getEnvironment().getProperty("history.enabled", "false"))) { + SchemaGenerator4Hist.loadSchemaIntoJanusGraph(graph, graphMgt, "inmemory"); + } else { + SchemaGenerator.loadSchemaIntoJanusGraph(graph, graphMgt, "inmemory"); + } } /** * Close all of the graph connections made in the instance. */ public void graphShutdown() { - graphs.values().stream().filter(JanusGraph::isOpen).forEach(JanusGraph::close); + if (graph != null && graph.isOpen()) { + graph.close(); + } } /** @@ -175,30 +171,10 @@ public class AAIGraph { * @return the graph */ public JanusGraph getGraph() { - return graphs.get(REALTIME_DB); - } - - public void graphShutdown(final DBConnectionType connectionType) { - - graphs.get(this.getGraphName(connectionType)).close(); - } - - public JanusGraph getGraph(final DBConnectionType connectionType) { - return graphs.get(this.getGraphName(connectionType)); - } - - private String getGraphName(final DBConnectionType connectionType) { - String graphName = ""; - if (DBConnectionType.CACHED.equals(connectionType)) { - graphName = this.CACHED_DB; - } else if (DBConnectionType.REALTIME.equals(connectionType)) { - graphName = this.REALTIME_DB; - } - - return graphName; + return graph; } - private void logAndPrint(final EELFLogger logger, final String msg) { + private void logAndPrint(String msg) { System.out.println(msg); logger.info(msg); } diff --git a/aai-core/src/main/java/org/onap/aai/dbmap/AAIGraphConfig.java b/aai-core/src/main/java/org/onap/aai/dbmap/AAIGraphConfig.java index d2f81610..ea939b32 100644 --- a/aai-core/src/main/java/org/onap/aai/dbmap/AAIGraphConfig.java +++ b/aai-core/src/main/java/org/onap/aai/dbmap/AAIGraphConfig.java @@ -22,8 +22,8 @@ package org.onap.aai.dbmap; import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.*; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.collect.Iterators; @@ -46,7 +46,7 @@ import org.janusgraph.diskstorage.configuration.backend.CommonsConfiguration; */ public class AAIGraphConfig { - private static final EELFLogger logger = EELFManager.getInstance().getLogger(AAIGraphConfig.class); + private static final Logger logger = LoggerFactory.getLogger(AAIGraphConfig.class); private AAIGraphConfig() { }; diff --git a/aai-core/src/main/java/org/onap/aai/dbmap/InMemoryGraph.java b/aai-core/src/main/java/org/onap/aai/dbmap/InMemoryGraph.java index 54986f37..d017b7e9 100644 --- a/aai-core/src/main/java/org/onap/aai/dbmap/InMemoryGraph.java +++ b/aai-core/src/main/java/org/onap/aai/dbmap/InMemoryGraph.java @@ -20,12 +20,15 @@ package org.onap.aai.dbmap; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; + +import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.tinkerpop.gremlin.structure.io.IoCore; import org.janusgraph.core.JanusGraph; import org.janusgraph.core.JanusGraphFactory; @@ -33,52 +36,56 @@ import org.janusgraph.core.JanusGraphTransaction; import org.janusgraph.core.schema.JanusGraphManagement; import org.onap.aai.dbgen.GraphSONPartialIO; import org.onap.aai.dbgen.SchemaGenerator; +import org.onap.aai.logging.LogFormatTools; public class InMemoryGraph { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(InMemoryGraph.class); + private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryGraph.class); private JanusGraph graph = null; - public InMemoryGraph(final Builder builder) throws IOException { + public InMemoryGraph(Builder builder) throws IOException { /* * Create a In-memory graph */ - try (final InputStream is = new FileInputStream(builder.propertyFile);) { + InputStream is = new FileInputStream(builder.propertyFile); + try { graph = JanusGraphFactory.open(builder.propertyFile); - final Properties graphProps = new Properties(); + Properties graphProps = new Properties(); graphProps.load(is); - final JanusGraphManagement graphMgt = graph.openManagement(); + JanusGraphManagement graphMgt = graph.openManagement(); if (builder.isSchemaEnabled) { LOGGER.info("Schema Enabled"); SchemaGenerator.loadSchemaIntoJanusGraph(graph, graphMgt, graphProps.getProperty("storage.backend")); } - try (final JanusGraphTransaction transaction = graph.newTransaction();) { - LOGGER.info("Loading snapshot"); - if (builder.isPartialGraph) { - if ((builder.graphsonLocation != null) && (builder.graphsonLocation.length() > 0)) { - transaction.io(GraphSONPartialIO.build()).readGraph(builder.graphsonLocation); - } else { - transaction.io(GraphSONPartialIO.build()).reader().create().readGraph(builder.seqInputStream, + JanusGraphTransaction transaction = graph.newTransaction(); + LOGGER.info("Loading snapshot"); + if (builder.isPartialGraph) { + if ((builder.graphsonLocation != null) && (builder.graphsonLocation.length() > 0)) { + transaction.io(GraphSONPartialIO.build()).readGraph(builder.graphsonLocation); + } else { + transaction.io(GraphSONPartialIO.build()).reader().create().readGraph(builder.seqInputStream, graph); - } + } + } else { + if ((builder.graphsonLocation != null) && (builder.graphsonLocation.length() > 0)) { + transaction.io(IoCore.graphson()).readGraph(builder.graphsonLocation); } else { - if ((builder.graphsonLocation != null) && (builder.graphsonLocation.length() > 0)) { - transaction.io(IoCore.graphson()).readGraph(builder.graphsonLocation); - } else { - transaction.io(IoCore.graphson()).reader().create().readGraph(builder.seqInputStream, graph); - } + transaction.io(IoCore.graphson()).reader().create().readGraph(builder.seqInputStream, graph); } - transaction.commit(); - } catch (final IOException e) { - LOGGER.error("ERROR: Could not load datasnapshot to in memory graph. \n", e); - throw new IllegalStateException("Could not load datasnapshot to in memory graph"); } + transaction.commit(); - } catch (final IOException e) { - LOGGER.error("ERROR: Could not load datasnapshot to in memory graph. \n", e); + } catch (Exception e) { + // TODO : Changesysout to logger + e.printStackTrace(); + LOGGER.error("ERROR: Could not load datasnapshot to in memory graph. \n" + LogFormatTools.getStackTop(e)); throw new IllegalStateException("Could not load datasnapshot to in memory graph"); + + } finally { + is.close(); } + } public static class Builder { diff --git a/aai-core/src/main/java/org/onap/aai/dmaap/AAIDmaapEventJMSConsumer.java b/aai-core/src/main/java/org/onap/aai/dmaap/AAIDmaapEventJMSConsumer.java index 44ff599f..b3a8773e 100644 --- a/aai-core/src/main/java/org/onap/aai/dmaap/AAIDmaapEventJMSConsumer.java +++ b/aai-core/src/main/java/org/onap/aai/dmaap/AAIDmaapEventJMSConsumer.java @@ -22,43 +22,45 @@ package org.onap.aai.dmaap; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -import java.util.Objects; -import java.util.UUID; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.TextMessage; - -import org.apache.log4j.MDC; import org.json.JSONException; import org.json.JSONObject; -import org.onap.aai.logging.LogFormatTools; -import org.onap.aai.logging.LoggingContext; -import org.onap.aai.logging.LoggingContext.LoggingField; -import org.onap.aai.logging.LoggingContext.StatusCode; +import org.onap.aai.aailog.logs.AaiDmaapMetricLog; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.AaiElsErrorCode; +import org.onap.aai.logging.ErrorLogHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import org.springframework.core.env.Environment; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.web.client.RestTemplate; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.TextMessage; +import java.util.Map; +import java.util.Objects; + public class AAIDmaapEventJMSConsumer implements MessageListener { private static final String EVENT_TOPIC = "event-topic"; - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIDmaapEventJMSConsumer.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AAIDmaapEventJMSConsumer.class); private RestTemplate restTemplate; private HttpHeaders httpHeaders; private Environment environment; + private Map<String, String> mdcCopy; + public AAIDmaapEventJMSConsumer(Environment environment, RestTemplate restTemplate, HttpHeaders httpHeaders) { + super(); + mdcCopy = MDC.getCopyOfContextMap(); Objects.nonNull(environment); Objects.nonNull(restTemplate); Objects.nonNull(httpHeaders); @@ -76,41 +78,47 @@ public class AAIDmaapEventJMSConsumer implements MessageListener { String jsmMessageTxt = ""; String aaiEvent = ""; + JSONObject aaiEventHeader; + JSONObject joPayload; + String transactionId = ""; + String serviceName = ""; String eventName = ""; - LoggingContext.save(); - LoggingContext.init(); + String aaiElsErrorCode = AaiElsErrorCode.SUCCESS; + String errorDescription = ""; + + if ( mdcCopy != null ) { + MDC.setContextMap(mdcCopy); + } + if (message instanceof TextMessage) { + AaiDmaapMetricLog metricLog = new AaiDmaapMetricLog(); try { jsmMessageTxt = ((TextMessage) message).getText(); JSONObject jo = new JSONObject(jsmMessageTxt); - if (jo.has("aaiEventPayload")) { - aaiEvent = jo.getJSONObject("aaiEventPayload").toString(); + joPayload = jo.getJSONObject("aaiEventPayload"); + aaiEvent = joPayload.toString(); } else { return; } - if (jo.getString("transId") != null) { - LoggingContext.requestId(jo.getString("transId")); - } else { - final UUID generatedRequestUuid = UUID.randomUUID(); - LoggingContext.requestId(generatedRequestUuid.toString()); - } - if (jo.getString("fromAppId") != null) { - LoggingContext.partnerName(jo.getString("fromAppId")); - } - if (jo.getString(EVENT_TOPIC) != null) { - eventName = jo.getString(EVENT_TOPIC); + if (jo.getString("event-topic") != null) { + eventName = jo.getString("event-topic"); } - - LoggingContext.targetEntity("DMAAP"); - if (jo.getString(EVENT_TOPIC) != null) { - eventName = jo.getString(EVENT_TOPIC); - LoggingContext.targetServiceName(eventName); + if (joPayload.has("event-header")) { + try { + aaiEventHeader = joPayload.getJSONObject("event-header"); + if (aaiEventHeader.has("id")) { + transactionId = aaiEventHeader.get("id").toString(); + } + if (aaiEventHeader.has("entity-link")) { + serviceName = aaiEventHeader.get("entity-link").toString(); + } + } + catch (JSONException jexc) { + // ignore, this is just used for logging + } } - LoggingContext.serviceName("AAI"); - LoggingContext.statusCode(StatusCode.COMPLETE); - LoggingContext.responseCode(LoggingContext.SUCCESS); - LOGGER.info(eventName + "|" + aaiEvent); + metricLog.pre(eventName, aaiEvent, transactionId, serviceName); HttpEntity httpEntity = new HttpEntity(aaiEvent, httpHeaders); @@ -121,21 +129,20 @@ public class AAIDmaapEventJMSConsumer implements MessageListener { if ("AAI-EVENT".equals(eventName)) { restTemplate.exchange(baseUrl + endpoint, HttpMethod.POST, httpEntity, String.class); } else { - LoggingContext.statusCode(StatusCode.ERROR); LOGGER.error(eventName + "|Event Topic invalid."); } } catch (JMSException | JSONException e) { - LoggingContext.statusCode(StatusCode.ERROR); - LoggingContext.responseCode(LoggingContext.DATA_ERROR); - LOGGER.error("AAI_7350 Error parsing aaievent jsm message for sending to dmaap. {} {}", jsmMessageTxt, - LogFormatTools.getStackTop(e)); + aaiElsErrorCode = AaiElsErrorCode.DATA_ERROR; + errorDescription = e.getMessage(); + ErrorLogHelper.logException(new AAIException("AAI_7350")); } catch (Exception e) { - LoggingContext.statusCode(StatusCode.ERROR); - LoggingContext.responseCode(LoggingContext.AVAILABILITY_TIMEOUT_ERROR); - LOGGER.error("AAI_7350 Error sending message to dmaap. {} {}", jsmMessageTxt, - LogFormatTools.getStackTop(e)); + aaiElsErrorCode = AaiElsErrorCode.AVAILABILITY_TIMEOUT_ERROR; + errorDescription = e.getMessage(); + ErrorLogHelper.logException(new AAIException("AAI_7304", jsmMessageTxt)); + } + finally { + metricLog.post(aaiElsErrorCode, errorDescription); } } - } } diff --git a/aai-core/src/main/java/org/onap/aai/dmaap/AAIDmaapEventJMSProducer.java b/aai-core/src/main/java/org/onap/aai/dmaap/AAIDmaapEventJMSProducer.java index 4036b907..eb0d1658 100644 --- a/aai-core/src/main/java/org/onap/aai/dmaap/AAIDmaapEventJMSProducer.java +++ b/aai-core/src/main/java/org/onap/aai/dmaap/AAIDmaapEventJMSProducer.java @@ -50,4 +50,12 @@ public class AAIDmaapEventJMSProducer implements MessageProducer { ccf.destroy(); } } + + public void sendMessageToDefaultDestination(String msg) { + if (jmsTemplate != null) { + jmsTemplate.convertAndSend(msg); + CachingConnectionFactory ccf = (CachingConnectionFactory) this.jmsTemplate.getConnectionFactory(); + ccf.destroy(); + } + } } diff --git a/aai-core/src/main/java/org/onap/aai/dmaap/MessageProducer.java b/aai-core/src/main/java/org/onap/aai/dmaap/MessageProducer.java index 9b17d881..1df64b69 100644 --- a/aai-core/src/main/java/org/onap/aai/dmaap/MessageProducer.java +++ b/aai-core/src/main/java/org/onap/aai/dmaap/MessageProducer.java @@ -25,4 +25,5 @@ import org.json.JSONObject; public interface MessageProducer { void sendMessageToDefaultDestination(JSONObject finalJson); + void sendMessageToDefaultDestination(String msg); } diff --git a/aai-core/src/main/java/org/onap/aai/domain/model/AAIResources.java b/aai-core/src/main/java/org/onap/aai/domain/model/AAIResources.java index 4e5f0392..413faf62 100644 --- a/aai-core/src/main/java/org/onap/aai/domain/model/AAIResources.java +++ b/aai-core/src/main/java/org/onap/aai/domain/model/AAIResources.java @@ -20,10 +20,10 @@ package org.onap.aai.domain.model; -import java.util.HashMap; - import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import java.util.HashMap; + public class AAIResources { private DynamicJAXBContext jaxbContext; diff --git a/aai-core/src/main/java/org/onap/aai/domain/notificationEvent/NotificationEvent.java b/aai-core/src/main/java/org/onap/aai/domain/notificationEvent/NotificationEvent.java index d8b9b997..1e6307cc 100644 --- a/aai-core/src/main/java/org/onap/aai/domain/notificationEvent/NotificationEvent.java +++ b/aai-core/src/main/java/org/onap/aai/domain/notificationEvent/NotificationEvent.java @@ -18,30 +18,25 @@ * ============LICENSE_END========================================================= */ // -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2016.01.06 at 05:38:00 PM EST +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 +// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2016.01.06 at 05:38:00 PM EST // package org.onap.aai.domain.notificationEvent; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAnyElement; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - import org.w3c.dom.Element; +import javax.xml.bind.annotation.*; + /** * <p> * Java class for anonymous complex type. - * + * * <p> * The following schema fragment specifies the expected content contained within this class. - * + * * <pre> * <complexType> * <complexContent> @@ -77,8 +72,8 @@ import org.w3c.dom.Element; * </complexContent> * </complexType> * </pre> - * - * + * + * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = {"cambriaPartition", "eventHeader", "entity"}) @@ -94,11 +89,11 @@ public class NotificationEvent { /** * Gets the value of the eventHeader property. - * + * * @return * possible object is * {@link EventHeader } - * + * */ public EventHeader getEventHeader() { return eventHeader; @@ -106,11 +101,11 @@ public class NotificationEvent { /** * Sets the value of the eventHeader property. - * + * * @param value * allowed object is * {@link EventHeader } - * + * */ public void setEventHeader(EventHeader value) { this.eventHeader = value; @@ -118,12 +113,12 @@ public class NotificationEvent { /** * Gets the value of the any property. - * + * * @return * possible object is * {@link Object } * {@link Element } - * + * */ public Object getEntity() { return entity; @@ -131,12 +126,12 @@ public class NotificationEvent { /** * Sets the value of the any property. - * + * * @param value * allowed object is * {@link Object } * {@link Element } - * + * */ public void setEntity(Object value) { this.entity = value; @@ -144,11 +139,11 @@ public class NotificationEvent { /** * Gets the value of the cambriaPartition property. - * + * * @return * possible object is * {@link String } - * + * */ public String getCambriaPartition() { return cambriaPartition; @@ -156,11 +151,11 @@ public class NotificationEvent { /** * Sets the value of the cambriaPartition property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setCambriaPartition(String value) { this.cambriaPartition = value; @@ -169,10 +164,10 @@ public class NotificationEvent { /** * <p> * Java class for anonymous complex type. - * + * * <p> * The following schema fragment specifies the expected content contained within this class. - * + * * <pre> * <complexType> * <complexContent> @@ -196,8 +191,8 @@ public class NotificationEvent { * </complexContent> * </complexType> * </pre> - * - * + * + * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType( @@ -235,11 +230,11 @@ public class NotificationEvent { /** * Gets the value of the id property. - * + * * @return * possible object is * {@link String } - * + * */ public String getId() { return id; @@ -247,11 +242,11 @@ public class NotificationEvent { /** * Sets the value of the id property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setId(String value) { this.id = value; @@ -259,11 +254,11 @@ public class NotificationEvent { /** * Gets the value of the timestamp property. - * + * * @return * possible object is * {@link String } - * + * */ public String getTimestamp() { return timestamp; @@ -271,11 +266,11 @@ public class NotificationEvent { /** * Sets the value of the timestamp property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setTimestamp(String value) { this.timestamp = value; @@ -283,11 +278,11 @@ public class NotificationEvent { /** * Gets the value of the sourceName property. - * + * * @return * possible object is * {@link String } - * + * */ public String getSourceName() { return sourceName; @@ -295,11 +290,11 @@ public class NotificationEvent { /** * Sets the value of the sourceName property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setSourceName(String value) { this.sourceName = value; @@ -307,11 +302,11 @@ public class NotificationEvent { /** * Gets the value of the domain property. - * + * * @return * possible object is * {@link String } - * + * */ public String getDomain() { return domain; @@ -319,11 +314,11 @@ public class NotificationEvent { /** * Sets the value of the domain property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setDomain(String value) { this.domain = value; @@ -331,11 +326,11 @@ public class NotificationEvent { /** * Gets the value of the sequenceNumber property. - * + * * @return * possible object is * {@link String } - * + * */ public String getSequenceNumber() { return sequenceNumber; @@ -343,11 +338,11 @@ public class NotificationEvent { /** * Sets the value of the sequenceNumber property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setSequenceNumber(String value) { this.sequenceNumber = value; @@ -355,11 +350,11 @@ public class NotificationEvent { /** * Gets the value of the severity property. - * + * * @return * possible object is * {@link String } - * + * */ public String getSeverity() { return severity; @@ -367,11 +362,11 @@ public class NotificationEvent { /** * Sets the value of the severity property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setSeverity(String value) { this.severity = value; @@ -379,11 +374,11 @@ public class NotificationEvent { /** * Gets the value of the eventType property. - * + * * @return * possible object is * {@link String } - * + * */ public String getEventType() { return eventType; @@ -391,11 +386,11 @@ public class NotificationEvent { /** * Sets the value of the eventType property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setEventType(String value) { this.eventType = value; @@ -403,11 +398,11 @@ public class NotificationEvent { /** * Gets the value of the version property. - * + * * @return * possible object is * {@link String } - * + * */ public String getVersion() { return version; @@ -415,11 +410,11 @@ public class NotificationEvent { /** * Sets the value of the version property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setVersion(String value) { this.version = value; @@ -427,11 +422,11 @@ public class NotificationEvent { /** * Gets the value of the action property. - * + * * @return * possible object is * {@link String } - * + * */ public String getAction() { return action; @@ -439,11 +434,11 @@ public class NotificationEvent { /** * Sets the value of the action property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setAction(String value) { this.action = value; @@ -451,11 +446,11 @@ public class NotificationEvent { /** * Gets the value of the entityType property. - * + * * @return * possible object is * {@link String } - * + * */ public String getEntityType() { return entityType; @@ -463,11 +458,11 @@ public class NotificationEvent { /** * Sets the value of the entityType property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setEntityType(String value) { this.entityType = value; @@ -475,11 +470,11 @@ public class NotificationEvent { /** * Gets the value of the topEntityType property. - * + * * @return * possible object is * {@link String } - * + * */ public String getTopEntityType() { return topEntityType; @@ -487,11 +482,11 @@ public class NotificationEvent { /** * Sets the value of the topEntityType property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setTopEntityType(String value) { this.topEntityType = value; @@ -499,11 +494,11 @@ public class NotificationEvent { /** * Gets the value of the entityLink property. - * + * * @return * possible object is * {@link String } - * + * */ public String getEntityLink() { return entityLink; @@ -511,11 +506,11 @@ public class NotificationEvent { /** * Sets the value of the entityLink property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setEntityLink(String value) { this.entityLink = value; @@ -523,11 +518,11 @@ public class NotificationEvent { /** * Gets the value of the status property. - * + * * @return * possible object is * {@link String } - * + * */ public String getStatus() { return status; @@ -535,11 +530,11 @@ public class NotificationEvent { /** * Sets the value of the status property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setStatus(String value) { this.status = value; diff --git a/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessage.java b/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessage.java index 6cd82eef..53311990 100644 --- a/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessage.java +++ b/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessage.java @@ -20,11 +20,7 @@ package org.onap.aai.domain.responseMessage; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) @XmlType( diff --git a/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessageData.java b/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessageData.java index 76b73642..c48f1ed8 100644 --- a/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessageData.java +++ b/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessageData.java @@ -23,22 +23,16 @@ package org.onap.aai.domain.responseMessage; // -//This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -//See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -//Any modifications to this file will be lost upon recompilation of the source schema. -//Generated on: 2015.09.11 at 11:53:27 AM EDT +//This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 +//See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> +//Any modifications to this file will be lost upon recompilation of the source schema. +//Generated on: 2015.09.11 at 11:53:27 AM EDT // +import javax.xml.bind.annotation.*; import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAnyElement; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = {"aaiResponseMessageDatum", "any"}) @XmlRootElement(name = "aai-response-message-data", namespace = "http://org.onap.aai.inventory") diff --git a/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessageDatum.java b/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessageDatum.java index 90c6e280..a8adffde 100644 --- a/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessageDatum.java +++ b/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessageDatum.java @@ -20,11 +20,7 @@ package org.onap.aai.domain.responseMessage; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = {"aaiResponseMessageDatumKey", "aaiResponseMessageDatumValue", diff --git a/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessages.java b/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessages.java index 09bf30e3..8263e58d 100644 --- a/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessages.java +++ b/aai-core/src/main/java/org/onap/aai/domain/responseMessage/AAIResponseMessages.java @@ -21,29 +21,23 @@ package org.onap.aai.domain.responseMessage; // -//This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -//See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -//Any modifications to this file will be lost upon recompilation of the source schema. -//Generated on: 2015.09.11 at 11:53:27 AM EDT +//This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 +//See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> +//Any modifications to this file will be lost upon recompilation of the source schema. +//Generated on: 2015.09.11 at 11:53:27 AM EDT // +import javax.xml.bind.annotation.*; import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAnyElement; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - /** * <p> * Java class for anonymous complex type. - * + * * <p> * The following schema fragment specifies the expected content contained within this class. - * + * * <pre> * <complexType> * <complexContent> @@ -77,8 +71,8 @@ import javax.xml.bind.annotation.XmlType; * </complexContent> * </complexType> * </pre> - * - * + * + * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = {"aaiResponseMessage", "any"}) diff --git a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/Fault.java b/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/Fault.java deleted file mode 100644 index 55e45b64..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/Fault.java +++ /dev/null @@ -1,376 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2015.02.11 at 04:54:39 PM EST -// - -package org.onap.aai.domain.restPolicyException; - -import java.util.ArrayList; -import java.util.List; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -/** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="requestError"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="policyException"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="variables"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "", propOrder = {"requestError"}) -@XmlRootElement(name = "Fault") -public class Fault { - - @XmlElement(required = true) - protected RequestError requestError; - - /** - * Gets the value of the requestError property. - * - * @return - * possible object is - * {@link RequestError } - * - */ - public RequestError getRequestError() { - return requestError; - } - - /** - * Sets the value of the requestError property. - * - * @param value - * allowed object is - * {@link RequestError } - * - */ - public void setRequestError(RequestError value) { - this.requestError = value; - } - - /** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="policyException"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="variables"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = {"policyException"}) - public static class RequestError { - - @XmlElement(required = true) - protected PolicyException policyException; - - /** - * Gets the value of the policyException property. - * - * @return - * possible object is - * {@link PolicyException } - * - */ - public PolicyException getPolicyException() { - return policyException; - } - - /** - * Sets the value of the policyException property. - * - * @param value - * allowed object is - * {@link PolicyException } - * - */ - public void setPolicyException(PolicyException value) { - this.policyException = value; - } - - /** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="variables"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = {"messageId", "text", "variables"}) - public static class PolicyException { - - @XmlElement(required = true) - protected String messageId; - @XmlElement(required = true) - protected String text; - @XmlElement(required = true) - protected Variables variables; - - /** - * Gets the value of the messageId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessageId() { - return messageId; - } - - /** - * Sets the value of the messageId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessageId(String value) { - this.messageId = value; - } - - /** - * Gets the value of the text property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getText() { - return text; - } - - /** - * Sets the value of the text property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setText(String value) { - this.text = value; - } - - /** - * Gets the value of the variables property. - * - * @return - * possible object is - * {@link Variables } - * - */ - public Variables getVariables() { - return variables; - } - - /** - * Sets the value of the variables property. - * - * @param value - * allowed object is - * {@link Variables } - * - */ - public void setVariables(Variables value) { - this.variables = value; - } - - /** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = {"variable"}) - public static class Variables { - - protected List<String> variable; - - /** - * Gets the value of the variable property. - * - * <p> - * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a <CODE>set</CODE> method for the variable property. - * - * <p> - * For example, to add a new item, do as follows: - * - * <pre> - * getVariable().add(newItem); - * </pre> - * - * - * <p> - * Objects of the following type(s) are allowed in the list - * {@link String } - * - * @return the variable - */ - public List<String> getVariable() { - if (variable == null) { - variable = new ArrayList<String>(); - } - return this.variable; - } - - } - - } - - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/ObjectFactory.java b/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/ObjectFactory.java deleted file mode 100644 index f85fe748..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/ObjectFactory.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2015.02.11 at 04:54:39 PM EST -// - -package org.onap.aai.domain.restPolicyException; - -import javax.xml.bind.annotation.XmlRegistry; - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the org.onap.aai.domain.restPolicyException package. - * <p> - * An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: - * org.onap.aai.domain.restPolicyException - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Fault }. - * - * @return the fault - */ - public Fault createFault() { - return new Fault(); - } - - /** - * Create an instance of {@link Fault.RequestError } - * - * @return the request error - */ - public Fault.RequestError createFaultRequestError() { - return new Fault.RequestError(); - } - - /** - * Create an instance of {@link Fault.RequestError.PolicyException } - * - * @return the policy exception - */ - public Fault.RequestError.PolicyException createFaultRequestErrorPolicyException() { - return new Fault.RequestError.PolicyException(); - } - - /** - * Create an instance of {@link Fault.RequestError.PolicyException.Variables } - * - * @return the variables - */ - public Fault.RequestError.PolicyException.Variables createFaultRequestErrorPolicyExceptionVariables() { - return new Fault.RequestError.PolicyException.Variables(); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/PolicyException.java b/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/PolicyException.java deleted file mode 100644 index 1aa2673a..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/PolicyException.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.domain.restPolicyException; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.annotation.Generated; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Generated("org.jsonschema2pojo") -@JsonPropertyOrder({"messageId", "text", "variables"}) -public class PolicyException { - - @JsonProperty("messageId") - private String messageId; - @JsonProperty("text") - private String text; - @JsonProperty("variables") - private List<String> variables = new ArrayList<String>(); - @JsonIgnore - private Map<String, Object> additionalProperties = new HashMap<String, Object>(); - - /** - * Gets the message id. - * - * @return The messageId - */ - @JsonProperty("messageId") - public String getMessageId() { - return messageId; - } - - /** - * Sets the message id. - * - * @param messageId The messageId - */ - @JsonProperty("messageId") - public void setMessageId(String messageId) { - this.messageId = messageId; - } - - /** - * Gets the text. - * - * @return The text - */ - @JsonProperty("text") - public String getText() { - return text; - } - - /** - * Sets the text. - * - * @param text The text - */ - @JsonProperty("text") - public void setText(String text) { - this.text = text; - } - - /** - * Gets the variables. - * - * @return The variables - */ - @JsonProperty("variables") - public List<String> getVariables() { - return variables; - } - - /** - * Sets the variables. - * - * @param variables The variables - */ - @JsonProperty("variables") - public void setVariables(List<String> variables) { - this.variables = variables; - } - - /** - * Gets the additional properties. - * - * @return the additional properties - */ - @JsonAnyGetter - public Map<String, Object> getAdditionalProperties() { - return this.additionalProperties; - } - - /** - * Sets the additional property. - * - * @param name the name - * @param value the value - */ - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/RESTResponse.java b/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/RESTResponse.java deleted file mode 100644 index 262ca855..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/RESTResponse.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.domain.restPolicyException; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Generated; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Generated("org.jsonschema2pojo") -@JsonPropertyOrder({"requestError"}) -public class RESTResponse { - - @JsonProperty("requestError") - private RequestError requestError; - @JsonIgnore - private Map<String, Object> additionalProperties = new HashMap<String, Object>(); - - /** - * Gets the request error. - * - * @return The requestError - */ - @JsonProperty("requestError") - public RequestError getRequestError() { - return requestError; - } - - /** - * Sets the request error. - * - * @param requestError The requestError - */ - @JsonProperty("requestError") - public void setRequestError(RequestError requestError) { - this.requestError = requestError; - } - - /** - * Gets the additional properties. - * - * @return the additional properties - */ - @JsonAnyGetter - public Map<String, Object> getAdditionalProperties() { - return this.additionalProperties; - } - - /** - * Sets the additional property. - * - * @param name the name - * @param value the value - */ - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/RequestError.java b/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/RequestError.java deleted file mode 100644 index 54580de7..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restPolicyException/RequestError.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.domain.restPolicyException; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Generated; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Generated("org.jsonschema2pojo") -@JsonPropertyOrder({"policyException"}) -public class RequestError { - - @JsonProperty("policyException") - private PolicyException policyException; - @JsonIgnore - private Map<String, Object> additionalProperties = new HashMap<String, Object>(); - - /** - * Gets the policy exception. - * - * @return The policyException - */ - @JsonProperty("policyException") - public PolicyException getPolicyException() { - return policyException; - } - - /** - * Sets the policy exception. - * - * @param policyException The policyException - */ - @JsonProperty("policyException") - public void setPolicyException(PolicyException policyException) { - this.policyException = policyException; - } - - /** - * Gets the additional properties. - * - * @return the additional properties - */ - @JsonAnyGetter - public Map<String, Object> getAdditionalProperties() { - return this.additionalProperties; - } - - /** - * Sets the additional property. - * - * @param name the name - * @param value the value - */ - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restResponseInfo/Info.java b/aai-core/src/main/java/org/onap/aai/domain/restResponseInfo/Info.java deleted file mode 100644 index 789fe926..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restResponseInfo/Info.java +++ /dev/null @@ -1,380 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2015.10.28 at 05:53:17 PM EDT -// - -package org.onap.aai.domain.restResponseInfo; - -import java.util.ArrayList; -import java.util.List; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -/** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="responseMessages" minOccurs="0"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="responseMessage" maxOccurs="unbounded" minOccurs="0"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="variables"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "", propOrder = {"responseMessages"}) -@XmlRootElement(name = "Info") -public class Info { - - protected ResponseMessages responseMessages; - - /** - * Gets the value of the responseMessages property. - * - * @return - * possible object is - * {@link ResponseMessages } - * - */ - public ResponseMessages getResponseMessages() { - return responseMessages; - } - - /** - * Sets the value of the responseMessages property. - * - * @param value - * allowed object is - * {@link ResponseMessages } - * - */ - public void setResponseMessages(ResponseMessages value) { - this.responseMessages = value; - } - - /** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="responseMessage" maxOccurs="unbounded" minOccurs="0"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="variables"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = {"responseMessage"}) - public static class ResponseMessages { - - protected List<ResponseMessage> responseMessage; - - /** - * Gets the value of the responseMessage property. - * - * <p> - * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a <CODE>set</CODE> method for the responseMessage property. - * - * <p> - * For example, to add a new item, do as follows: - * - * <pre> - * getResponseMessage().add(newItem); - * </pre> - * - * - * <p> - * Objects of the following type(s) are allowed in the list - * {@link ResponseMessage } - * - * @return the response message - */ - public List<ResponseMessage> getResponseMessage() { - if (responseMessage == null) { - responseMessage = new ArrayList<ResponseMessage>(); - } - return this.responseMessage; - } - - /** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="variables"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = {"messageId", "text", "variables"}) - public static class ResponseMessage { - - @XmlElement(required = true) - protected String messageId; - @XmlElement(required = true) - protected String text; - @XmlElement(required = true) - protected Variables variables; - - /** - * Gets the value of the messageId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessageId() { - return messageId; - } - - /** - * Sets the value of the messageId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessageId(String value) { - this.messageId = value; - } - - /** - * Gets the value of the text property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getText() { - return text; - } - - /** - * Sets the value of the text property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setText(String value) { - this.text = value; - } - - /** - * Gets the value of the variables property. - * - * @return - * possible object is - * {@link Variables } - * - */ - public Variables getVariables() { - return variables; - } - - /** - * Sets the value of the variables property. - * - * @param value - * allowed object is - * {@link Variables } - * - */ - public void setVariables(Variables value) { - this.variables = value; - } - - /** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = {"variable"}) - public static class Variables { - - protected List<String> variable; - - /** - * Gets the value of the variable property. - * - * <p> - * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a <CODE>set</CODE> method for the variable property. - * - * <p> - * For example, to add a new item, do as follows: - * - * <pre> - * getVariable().add(newItem); - * </pre> - * - * - * <p> - * Objects of the following type(s) are allowed in the list - * {@link String } - * - * @return the variable - */ - public List<String> getVariable() { - if (variable == null) { - variable = new ArrayList<String>(); - } - return this.variable; - } - - } - - } - - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restResponseInfo/ObjectFactory.java b/aai-core/src/main/java/org/onap/aai/domain/restResponseInfo/ObjectFactory.java deleted file mode 100644 index 4efafb23..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restResponseInfo/ObjectFactory.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2015.10.28 at 05:53:17 PM EDT -// - -package org.onap.aai.domain.restResponseInfo; - -import javax.xml.bind.annotation.XmlRegistry; - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the org.onap.aai.domain.restResponseInfo package. - * <p> - * An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: - * org.onap.aai.domain.restResponseInfo - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Info }. - * - * @return the info - */ - public Info createInfo() { - return new Info(); - } - - /** - * Create an instance of {@link Info.ResponseMessages } - * - * @return the response messages - */ - public Info.ResponseMessages createInfoResponseMessages() { - return new Info.ResponseMessages(); - } - - /** - * Create an instance of {@link Info.ResponseMessages.ResponseMessage } - * - * @return the response message - */ - public Info.ResponseMessages.ResponseMessage createInfoResponseMessagesResponseMessage() { - return new Info.ResponseMessages.ResponseMessage(); - } - - /** - * Create an instance of {@link Info.ResponseMessages.ResponseMessage.Variables } - * - * @return the variables - */ - public Info.ResponseMessages.ResponseMessage.Variables createInfoResponseMessagesResponseMessageVariables() { - return new Info.ResponseMessages.ResponseMessage.Variables(); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/Fault.java b/aai-core/src/main/java/org/onap/aai/domain/restServiceException/Fault.java deleted file mode 100644 index 3efa13c3..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/Fault.java +++ /dev/null @@ -1,376 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2015.02.11 at 04:54:29 PM EST -// - -package org.onap.aai.domain.restServiceException; - -import java.util.ArrayList; -import java.util.List; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -/** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="requestError"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="serviceException"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="variables"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "", propOrder = {"requestError"}) -@XmlRootElement(name = "Fault") -public class Fault { - - @XmlElement(required = true) - protected RequestError requestError; - - /** - * Gets the value of the requestError property. - * - * @return - * possible object is - * {@link RequestError } - * - */ - public RequestError getRequestError() { - return requestError; - } - - /** - * Sets the value of the requestError property. - * - * @param value - * allowed object is - * {@link RequestError } - * - */ - public void setRequestError(RequestError value) { - this.requestError = value; - } - - /** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="serviceException"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="variables"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = {"serviceException"}) - public static class RequestError { - - @XmlElement(required = true) - protected ServiceException serviceException; - - /** - * Gets the value of the serviceException property. - * - * @return - * possible object is - * {@link ServiceException } - * - */ - public ServiceException getServiceException() { - return serviceException; - } - - /** - * Sets the value of the serviceException property. - * - * @param value - * allowed object is - * {@link ServiceException } - * - */ - public void setServiceException(ServiceException value) { - this.serviceException = value; - } - - /** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/> - * <element name="variables"> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </element> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = {"messageId", "text", "variables"}) - public static class ServiceException { - - @XmlElement(required = true) - protected String messageId; - @XmlElement(required = true) - protected String text; - @XmlElement(required = true) - protected Variables variables; - - /** - * Gets the value of the messageId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessageId() { - return messageId; - } - - /** - * Sets the value of the messageId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessageId(String value) { - this.messageId = value; - } - - /** - * Gets the value of the text property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getText() { - return text; - } - - /** - * Sets the value of the text property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setText(String value) { - this.text = value; - } - - /** - * Gets the value of the variables property. - * - * @return - * possible object is - * {@link Variables } - * - */ - public Variables getVariables() { - return variables; - } - - /** - * Sets the value of the variables property. - * - * @param value - * allowed object is - * {@link Variables } - * - */ - public void setVariables(Variables value) { - this.variables = value; - } - - /** - * <p> - * Java class for anonymous complex type. - * - * <p> - * The following schema fragment specifies the expected content contained within this class. - * - * <pre> - * <complexType> - * <complexContent> - * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <sequence> - * <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/> - * </sequence> - * </restriction> - * </complexContent> - * </complexType> - * </pre> - * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = {"variable"}) - public static class Variables { - - protected List<String> variable; - - /** - * Gets the value of the variable property. - * - * <p> - * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a <CODE>set</CODE> method for the variable property. - * - * <p> - * For example, to add a new item, do as follows: - * - * <pre> - * getVariable().add(newItem); - * </pre> - * - * - * <p> - * Objects of the following type(s) are allowed in the list - * {@link String } - * - * @return the variable - */ - public List<String> getVariable() { - if (variable == null) { - variable = new ArrayList<String>(); - } - return this.variable; - } - - } - - } - - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/ObjectFactory.java b/aai-core/src/main/java/org/onap/aai/domain/restServiceException/ObjectFactory.java deleted file mode 100644 index 95eb2cba..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/ObjectFactory.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2015.02.11 at 04:54:29 PM EST -// - -package org.onap.aai.domain.restServiceException; - -import javax.xml.bind.annotation.XmlRegistry; - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the org.onap.aai.domain.restServiceException package. - * <p> - * An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: - * org.onap.aai.domain.restServiceException - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Fault }. - * - * @return the fault - */ - public Fault createFault() { - return new Fault(); - } - - /** - * Create an instance of {@link Fault.RequestError } - * - * @return the request error - */ - public Fault.RequestError createFaultRequestError() { - return new Fault.RequestError(); - } - - /** - * Create an instance of {@link Fault.RequestError.ServiceException } - * - * @return the service exception - */ - public Fault.RequestError.ServiceException createFaultRequestErrorServiceException() { - return new Fault.RequestError.ServiceException(); - } - - /** - * Create an instance of {@link Fault.RequestError.ServiceException.Variables } - * - * @return the variables - */ - public Fault.RequestError.ServiceException.Variables createFaultRequestErrorServiceExceptionVariables() { - return new Fault.RequestError.ServiceException.Variables(); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/RESTResponse.java b/aai-core/src/main/java/org/onap/aai/domain/restServiceException/RESTResponse.java deleted file mode 100644 index 09178937..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/RESTResponse.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.domain.restServiceException; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Generated; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Generated("org.jsonschema2pojo") -@JsonPropertyOrder({"requestError"}) -public class RESTResponse { - - @JsonProperty("requestError") - private RequestError requestError; - @JsonIgnore - private Map<String, Object> additionalProperties = new HashMap<String, Object>(); - - /** - * Gets the request error. - * - * @return The requestError - */ - @JsonProperty("requestError") - public RequestError getRequestError() { - return requestError; - } - - /** - * Sets the request error. - * - * @param requestError The requestError - */ - @JsonProperty("requestError") - public void setRequestError(RequestError requestError) { - this.requestError = requestError; - } - - /** - * Gets the additional properties. - * - * @return the additional properties - */ - @JsonAnyGetter - public Map<String, Object> getAdditionalProperties() { - return this.additionalProperties; - } - - /** - * Sets the additional property. - * - * @param name the name - * @param value the value - */ - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/RequestError.java b/aai-core/src/main/java/org/onap/aai/domain/restServiceException/RequestError.java deleted file mode 100644 index 38320218..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/RequestError.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.domain.restServiceException; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Generated; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Generated("org.jsonschema2pojo") -@JsonPropertyOrder({"serviceException"}) -public class RequestError { - - @JsonProperty("serviceException") - private ServiceException serviceException; - @JsonIgnore - private Map<String, Object> additionalProperties = new HashMap<String, Object>(); - - /** - * Gets the service exception. - * - * @return The serviceException - */ - @JsonProperty("serviceException") - public ServiceException getServiceException() { - return serviceException; - } - - /** - * Sets the service exception. - * - * @param serviceException The serviceException - */ - @JsonProperty("serviceException") - public void setServiceException(ServiceException serviceException) { - this.serviceException = serviceException; - } - - /** - * Gets the additional properties. - * - * @return the additional properties - */ - @JsonAnyGetter - public Map<String, Object> getAdditionalProperties() { - return this.additionalProperties; - } - - /** - * Sets the additional property. - * - * @param name the name - * @param value the value - */ - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/ServiceException.java b/aai-core/src/main/java/org/onap/aai/domain/restServiceException/ServiceException.java deleted file mode 100644 index ec658ce3..00000000 --- a/aai-core/src/main/java/org/onap/aai/domain/restServiceException/ServiceException.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.domain.restServiceException; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.annotation.Generated; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Generated("org.jsonschema2pojo") -@JsonPropertyOrder({"messageId", "text", "variables"}) -public class ServiceException { - - @JsonProperty("messageId") - private String messageId; - @JsonProperty("text") - private String text; - @JsonProperty("variables") - private List<String> variables = new ArrayList<String>(); - @JsonIgnore - private Map<String, Object> additionalProperties = new HashMap<String, Object>(); - - /** - * Gets the message id. - * - * @return The messageId - */ - @JsonProperty("messageId") - public String getMessageId() { - return messageId; - } - - /** - * Sets the message id. - * - * @param messageId The messageId - */ - @JsonProperty("messageId") - public void setMessageId(String messageId) { - this.messageId = messageId; - } - - /** - * Gets the text. - * - * @return The text - */ - @JsonProperty("text") - public String getText() { - return text; - } - - /** - * Sets the text. - * - * @param text The text - */ - @JsonProperty("text") - public void setText(String text) { - this.text = text; - } - - /** - * Gets the variables. - * - * @return The variables - */ - @JsonProperty("variables") - public List<String> getVariables() { - return variables; - } - - /** - * Sets the variables. - * - * @param variables The variables - */ - @JsonProperty("variables") - public void setVariables(List<String> variables) { - this.variables = variables; - } - - /** - * Gets the additional properties. - * - * @return the additional properties - */ - @JsonAnyGetter - public Map<String, Object> getAdditionalProperties() { - return this.additionalProperties; - } - - /** - * Sets the additional property. - * - * @param name the name - * @param value the value - */ - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/domain/translog/TransactionLogEntries.java b/aai-core/src/main/java/org/onap/aai/domain/translog/TransactionLogEntries.java index 7f02cb53..e81b3e3c 100644 --- a/aai-core/src/main/java/org/onap/aai/domain/translog/TransactionLogEntries.java +++ b/aai-core/src/main/java/org/onap/aai/domain/translog/TransactionLogEntries.java @@ -18,29 +18,28 @@ * ============LICENSE_END========================================================= */ // -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 -// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2015.03.20 at 09:46:47 AM CDT +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 +// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2015.03.20 at 09:46:47 AM CDT // package org.onap.aai.domain.translog; -import java.util.ArrayList; -import java.util.List; - import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import java.util.ArrayList; +import java.util.List; /** * <p> * Java class for anonymous complex type. - * + * * <p> * The following schema fragment specifies the expected content contained within this class. - * + * * <pre> * <complexType> * <complexContent> @@ -102,8 +101,8 @@ import javax.xml.bind.annotation.XmlType; * </complexContent> * </complexType> * </pre> - * - * + * + * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = {"transactionLogEntries"}) diff --git a/aai-core/src/main/java/org/onap/aai/domain/translog/TransactionLogEntry.java b/aai-core/src/main/java/org/onap/aai/domain/translog/TransactionLogEntry.java index 2ce485be..16c773ae 100644 --- a/aai-core/src/main/java/org/onap/aai/domain/translog/TransactionLogEntry.java +++ b/aai-core/src/main/java/org/onap/aai/domain/translog/TransactionLogEntry.java @@ -20,14 +20,10 @@ package org.onap.aai.domain.translog; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - import org.eclipse.persistence.oxm.annotations.XmlCDATA; +import javax.xml.bind.annotation.*; + @XmlAccessorType(XmlAccessType.FIELD) @XmlType( name = "", @@ -70,11 +66,11 @@ public class TransactionLogEntry { /** * Gets the value of the transcationLogEntryId property. - * + * * @return * possible object is * {@link String } - * + * */ public String getTransactionLogEntryId() { return transactionLogEntryId; @@ -82,11 +78,11 @@ public class TransactionLogEntry { /** * Sets the value of the transactionLogEntryId property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setTransactionLogEntryId(String value) { this.transactionLogEntryId = value; @@ -94,11 +90,11 @@ public class TransactionLogEntry { /** * Gets the value of the status property. - * + * * @return * possible object is * {@link String } - * + * */ public String getStatus() { return status; @@ -106,11 +102,11 @@ public class TransactionLogEntry { /** * Sets the value of the status property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setStatus(String value) { this.status = value; @@ -118,11 +114,11 @@ public class TransactionLogEntry { /** * Gets the value of the rqstDate property. - * + * * @return * possible object is * {@link String } - * + * */ public String getRqstDate() { @@ -131,11 +127,11 @@ public class TransactionLogEntry { /** * Sets the value of the rqstDate property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setRqstDate(String value) { this.rqstDate = value; @@ -143,11 +139,11 @@ public class TransactionLogEntry { /** * Gets the value of the respDate property. - * + * * @return * possible object is * {@link String } - * + * */ public String getRespDate() { @@ -156,11 +152,11 @@ public class TransactionLogEntry { /** * Sets the value of the respDate property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setRespDate(String value) { this.respDate = value; @@ -168,11 +164,11 @@ public class TransactionLogEntry { /** * Gets the value of the sourceId property. - * + * * @return * possible object is * {@link String } - * + * */ public String getSourceId() { return sourceId; @@ -180,11 +176,11 @@ public class TransactionLogEntry { /** * Sets the value of the sourceId property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setSourceId(String value) { this.sourceId = value; @@ -192,11 +188,11 @@ public class TransactionLogEntry { /** * Gets the value of the resourceId property. - * + * * @return * possible object is * {@link String } - * + * */ public String getResourceId() { return resourceId; @@ -204,11 +200,11 @@ public class TransactionLogEntry { /** * Sets the value of the resourceId property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setResourceId(String value) { this.resourceId = value; @@ -216,11 +212,11 @@ public class TransactionLogEntry { /** * Gets the value of the resourceType property. - * + * * @return * possible object is * {@link String } - * + * */ public String getResourceType() { return resourceType; @@ -228,11 +224,11 @@ public class TransactionLogEntry { /** * Sets the value of the resourceType property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setResourceType(String value) { this.resourceType = value; @@ -240,11 +236,11 @@ public class TransactionLogEntry { /** * Gets the value of the rqstBuf property. - * + * * @return * possible object is * {@link String } - * + * */ public String getRqstBuf() { return rqstBuf; @@ -252,11 +248,11 @@ public class TransactionLogEntry { /** * Sets the value of the rqstBuf property. - * + * * @param value * allowed object is * {@link String } - * + * */ @XmlCDATA public void setRqstBuf(String value) { @@ -265,11 +261,11 @@ public class TransactionLogEntry { /** * Gets the value of the respBuf property. - * + * * @return * possible object is * {@link String } - * + * */ public String getrespBuf() { return respBuf; @@ -277,11 +273,11 @@ public class TransactionLogEntry { /** * Sets the value of the respBuf property. - * + * * @param value * allowed object is * {@link String } - * + * */ @XmlCDATA public void setrespBuf(String value) { @@ -290,11 +286,11 @@ public class TransactionLogEntry { /** * Gets the value of the notificationPayload property. - * + * * @return * possible object is * {@link String } - * + * */ public String getNotificationPayload() { return notificationPayload; @@ -302,11 +298,11 @@ public class TransactionLogEntry { /** * Sets the value of the notificationPayload property. - * + * * @param value * allowed object is * {@link String } - * + * */ @XmlCDATA public void setNotificationPayload(String value) { @@ -315,11 +311,11 @@ public class TransactionLogEntry { /** * Gets the value of the notificationId property. - * + * * @return * possible object is * {@link String } - * + * */ public String getNotificationId() { return notificationId; @@ -327,11 +323,11 @@ public class TransactionLogEntry { /** * Sets the value of the notificationId property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setNotificationId(String value) { this.notificationId = value; @@ -339,11 +335,11 @@ public class TransactionLogEntry { /** * Gets the value of the notificationId property. - * + * * @return * possible object is * {@link String } - * + * */ public String getNotificationStatus() { return notificationStatus; @@ -351,11 +347,11 @@ public class TransactionLogEntry { /** * Sets the value of the notificationId property. - * + * * @param value * allowed object is * {@link String } - * + * */ public void setNotificationStatus(String value) { this.notificationStatus = value; @@ -363,11 +359,11 @@ public class TransactionLogEntry { /** * Gets the value of the notificationTopic property. - * + * * @return * possible object is * {@link String } - * + * */ public String getNotificationTopic() { return notificationTopic; @@ -384,11 +380,11 @@ public class TransactionLogEntry { /** * Gets the value of the notificationEntityLink property. - * + * * @return * possible object is * {@link String } - * + * */ public String getNotificationEntityLink() { return notificationEntityLink; diff --git a/aai-core/src/main/java/org/onap/aai/exceptions/AAIException.java b/aai-core/src/main/java/org/onap/aai/exceptions/AAIException.java deleted file mode 100644 index 320d5630..00000000 --- a/aai-core/src/main/java/org/onap/aai/exceptions/AAIException.java +++ /dev/null @@ -1,153 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Modifications Copyright © 2018 IBM. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.exceptions; - -import java.util.Collection; -import java.util.LinkedList; - -import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.logging.ErrorObject; -import org.onap.aai.logging.ErrorObjectNotFoundException; - -public class AAIException extends Exception { - - private static final String UPDATE_ERROR_PROPERTIES_BEFORE_USING_THIS_EXCEPTION_CODE = - " - update error.properties before using this exception code"; - private static final String FAILED_TO_INSTANTIATE_AAI_EXCEPTION_WITH_CODE = - "Failed to instantiate AAIException with code="; - public static final String DEFAULT_EXCEPTION_CODE = "AAI_4000"; - private static final long serialVersionUID = 1L; - - private final String code; - private final ErrorObject errorObject; - private final Collection<String> templateVars; - - /** - * Instantiates a new AAI exception. - */ - public AAIException() { - super(); - this.code = DEFAULT_EXCEPTION_CODE; - this.templateVars = new LinkedList<>(); - - try { - this.errorObject = ErrorLogHelper.getErrorObject(getCode()); - } catch (ErrorObjectNotFoundException e) { - throw new RuntimeException(FAILED_TO_INSTANTIATE_AAI_EXCEPTION_WITH_CODE + getCode() - + UPDATE_ERROR_PROPERTIES_BEFORE_USING_THIS_EXCEPTION_CODE); - } - } - - /** - * Instantiates a new AAI exception. - * - * @param code the code - */ - public AAIException(String code) { - super(); - - this.code = code; - this.templateVars = new LinkedList<>(); - - try { - this.errorObject = ErrorLogHelper.getErrorObject(getCode()); - } catch (ErrorObjectNotFoundException e) { - throw new RuntimeException(FAILED_TO_INSTANTIATE_AAI_EXCEPTION_WITH_CODE + getCode() - + UPDATE_ERROR_PROPERTIES_BEFORE_USING_THIS_EXCEPTION_CODE); - } - } - - /** - * Instantiates a new AAI exception. - * - * @param code the code - * @param details the details - */ - public AAIException(String code, String details) { - super(details); - - this.code = code; - this.templateVars = new LinkedList<>(); - - try { - this.errorObject = ErrorLogHelper.getErrorObject(getCode()); - errorObject.setDetails(details); - } catch (ErrorObjectNotFoundException e) { - throw new RuntimeException(FAILED_TO_INSTANTIATE_AAI_EXCEPTION_WITH_CODE + getCode() - + UPDATE_ERROR_PROPERTIES_BEFORE_USING_THIS_EXCEPTION_CODE); - } - } - - /** - * Instantiates a new AAI exception. - * - * @param code the code - * @param cause the cause - */ - public AAIException(String code, Throwable cause) { - super(cause); - - this.code = code; - this.templateVars = new LinkedList<>(); - - try { - this.errorObject = ErrorLogHelper.getErrorObject(getCode()); - } catch (ErrorObjectNotFoundException e) { - throw new RuntimeException(FAILED_TO_INSTANTIATE_AAI_EXCEPTION_WITH_CODE + getCode() - + UPDATE_ERROR_PROPERTIES_BEFORE_USING_THIS_EXCEPTION_CODE); - } - } - - /** - * Instantiates a new AAI exception. - * - * @param code the code - * @param cause the cause - * @param details the details - */ - public AAIException(String code, Throwable cause, String details) { - super(details, cause); - - this.code = code; - this.templateVars = new LinkedList<>(); - - try { - this.errorObject = ErrorLogHelper.getErrorObject(getCode()); - } catch (ErrorObjectNotFoundException e) { - throw new RuntimeException(FAILED_TO_INSTANTIATE_AAI_EXCEPTION_WITH_CODE + getCode() - + UPDATE_ERROR_PROPERTIES_BEFORE_USING_THIS_EXCEPTION_CODE); - } - } - - public String getCode() { - return code; - } - - public ErrorObject getErrorObject() { - return errorObject; - } - - public Collection<String> getTemplateVars() { - return templateVars; - } -} diff --git a/aai-core/src/main/java/org/onap/aai/exceptions/AAIExceptionWithInfo.java b/aai-core/src/main/java/org/onap/aai/exceptions/AAIExceptionWithInfo.java deleted file mode 100644 index e7f2901e..00000000 --- a/aai-core/src/main/java/org/onap/aai/exceptions/AAIExceptionWithInfo.java +++ /dev/null @@ -1,135 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.exceptions; - -import java.util.HashMap; - -public class AAIExceptionWithInfo extends AAIException { - - HashMap<String, Object> infoHash; - String info; - - /** - * Instantiates a new AAI exception with info. - * - * @param infoHash the info hash - * @param info the info - */ - public AAIExceptionWithInfo(HashMap<String, Object> infoHash, String info) { - super(); - setInfoHash(infoHash); - setInfo(info); - } - - /** - * Instantiates a new AAI exception with info. - * - * @param code the code - * @param infoHash the info hash - * @param info the info - */ - public AAIExceptionWithInfo(String code, HashMap<String, Object> infoHash, String info) { - super(code); - setInfoHash(infoHash); - setInfo(info); - } - - /** - * Instantiates a new AAI exception with info. - * - * @param code the code - * @param details the details - * @param infoHash the info hash - * @param info the info - */ - public AAIExceptionWithInfo(String code, String details, HashMap<String, Object> infoHash, String info) { - super(code, details); - setInfoHash(infoHash); - setInfo(info); - } - - /** - * Instantiates a new AAI exception with info. - * - * @param code the code - * @param cause the cause - * @param infoHash the info hash - * @param info the info - */ - public AAIExceptionWithInfo(String code, Throwable cause, HashMap<String, Object> infoHash, String info) { - super(code, cause); - setInfoHash(infoHash); - setInfo(info); - } - - /** - * Instantiates a new AAI exception with info. - * - * @param code the code - * @param cause the cause - * @param details the details - * @param infoHash the info hash - * @param info the info - */ - public AAIExceptionWithInfo(String code, Throwable cause, String details, HashMap<String, Object> infoHash, - String info) { - super(code, cause, details); - setInfoHash(infoHash); - setInfo(info); - } - - /** - * Gets the info hash. - * - * @return the info hash - */ - public HashMap<String, Object> getInfoHash() { - return infoHash; - } - - /** - * Sets the info hash. - * - * @param infoHash the info hash - */ - public void setInfoHash(HashMap<String, Object> infoHash) { - this.infoHash = infoHash; - } - - /** - * Gets the info. - * - * @return the info - */ - public String getInfo() { - return info; - } - - /** - * Sets the info. - * - * @param info the new info - */ - public void setInfo(String info) { - this.info = info; - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/extensions/ExtensionController.java b/aai-core/src/main/java/org/onap/aai/extensions/ExtensionController.java index 13c2de94..ec28858e 100644 --- a/aai-core/src/main/java/org/onap/aai/extensions/ExtensionController.java +++ b/aai-core/src/main/java/org/onap/aai/extensions/ExtensionController.java @@ -20,8 +20,8 @@ package org.onap.aai.extensions; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.lang.reflect.Method; @@ -30,7 +30,7 @@ import org.onap.aai.util.AAIConfig; public class ExtensionController { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ExtensionController.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ExtensionController.class); /** * Run extension. diff --git a/aai-core/src/main/java/org/onap/aai/introspection/Introspector.java b/aai-core/src/main/java/org/onap/aai/introspection/Introspector.java index 11e6233f..53f2a2cd 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/Introspector.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/Introspector.java @@ -20,15 +20,9 @@ package org.onap.aai.introspection; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.CaseFormat; - -import java.io.UnsupportedEncodingException; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.stream.Collectors; - import org.apache.commons.lang.ClassUtils; import org.eclipse.persistence.exceptions.DynamicException; import org.onap.aai.config.SpringContextAware; @@ -43,9 +37,14 @@ import org.onap.aai.schema.enums.PropertyMetadata; import org.onap.aai.setup.SchemaVersion; import org.onap.aai.workarounds.NamingExceptions; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.stream.Collectors; + public abstract class Introspector implements Cloneable { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(Introspector.class); + private static final Logger LOGGER = LoggerFactory.getLogger(Introspector.class); protected String className; protected String uriChain = ""; @@ -54,6 +53,7 @@ public abstract class Introspector implements Cloneable { private Set<String> uniqueProperties = null; private Set<String> indexedProperties = null; private Set<String> allKeys = null; + private Set<String> dslStartNodeProperties = null; protected CaseFormatStore caseFormatStore = null; protected NodeIngestor nodeIngestor; @@ -177,7 +177,7 @@ public abstract class Introspector implements Cloneable { if (obj != null) { try { - if (!nameClass.isAssignableFrom(obj.getClass())) { + if (!obj.getClass().getName().equals(nameClass.getName())) { if (nameClass.isPrimitive()) { nameClass = ClassUtils.primitiveToWrapper(nameClass); result = nameClass.getConstructor(String.class).newInstance(obj.toString()); @@ -229,15 +229,8 @@ public abstract class Introspector implements Cloneable { public Set<String> getProperties(PropertyPredicate<Introspector, String> p) { final Set<String> temp = new LinkedHashSet<>(); - this.getProperties().stream().filter(item -> { - return p.test(this, item); - }).forEach(item -> { - temp.add(item); - }); - final Set<String> result = Collections.unmodifiableSet(temp); - - return result; - + this.getProperties().stream().filter(item -> p.test(this, item)).forEach(temp::add); + return Collections.unmodifiableSet(temp); } public Set<String> getSimpleProperties(PropertyPredicate<Introspector, String> p) { @@ -301,6 +294,31 @@ public abstract class Introspector implements Cloneable { return result; } + public Set<String> getDslStartNodeProperties() { + Set<String> result = null; + + if (this.dslStartNodeProperties == null) { + /* + * The dslStartNodeProperties will have keys by default + * If dslStartNodeProps exist in the oxm use it + * if not use the indexedProps + */ + result = new LinkedHashSet<>(this.getKeys()); + + String dslKeys = this.getMetadata(ObjectMetadata.DSL_START_NODE_PROPS); + String indexedKeys = this.getMetadata(ObjectMetadata.INDEXED_PROPS); + if (dslKeys != null) { + Arrays.stream(dslKeys.split(",")).forEach(result::add); + } + else if(indexedKeys != null){ + Arrays.stream(indexedKeys.split(",")).forEach(result::add); + } + this.dslStartNodeProperties = Collections.unmodifiableSet(result); + } + result = this.dslStartNodeProperties; + return result; + } + public Set<String> getUniqueProperties() { Set<String> result = null; if (this.uniqueProperties == null) { diff --git a/aai-core/src/main/java/org/onap/aai/introspection/IntrospectorWalker.java b/aai-core/src/main/java/org/onap/aai/introspection/IntrospectorWalker.java index aa5ae156..93a48290 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/IntrospectorWalker.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/IntrospectorWalker.java @@ -20,8 +20,8 @@ package org.onap.aai.introspection; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.LinkedHashSet; @@ -34,7 +34,7 @@ import org.onap.aai.logging.LogFormatTools; public class IntrospectorWalker { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(IntrospectorWalker.class); + private static final Logger LOGGER = LoggerFactory.getLogger(IntrospectorWalker.class); private Wanderer w = null; private Set<String> blacklist = null; diff --git a/aai-core/src/main/java/org/onap/aai/introspection/JSONStrategy.java b/aai-core/src/main/java/org/onap/aai/introspection/JSONStrategy.java index e628d5a4..55580dc3 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/JSONStrategy.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/JSONStrategy.java @@ -26,7 +26,6 @@ import java.util.Map; import java.util.Set; import java.util.UUID; -import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.onap.aai.schema.enums.ObjectMetadata; import org.onap.aai.schema.enums.PropertyMetadata; @@ -150,7 +149,7 @@ public class JSONStrategy extends Introspector { Object resultObject = null; Class<?> resultClass = null; resultObject = this.getValue(name); - if (resultObject instanceof JSONArray) { + if (resultObject.getClass().getName().equals("org.json.simple.JSONArray")) { resultClass = ((List) resultObject).get(0).getClass(); } @@ -274,10 +273,10 @@ public class JSONStrategy extends Introspector { /* * @Override * public String findEdgeName(String parent, String child) { - * + * * // Always has for now * return "has"; - * + * * } */ diff --git a/aai-core/src/main/java/org/onap/aai/introspection/MoxyLoader.java b/aai-core/src/main/java/org/onap/aai/introspection/MoxyLoader.java index 02254a8b..7471c745 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/MoxyLoader.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/MoxyLoader.java @@ -20,8 +20,8 @@ package org.onap.aai.introspection; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.CaseFormat; import com.google.common.collect.ImmutableMap; @@ -52,7 +52,7 @@ import org.onap.aai.workarounds.NamingExceptions; public class MoxyLoader extends Loader { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(MoxyLoader.class); + private static final Logger LOGGER = LoggerFactory.getLogger(MoxyLoader.class); private DynamicJAXBContext jaxbContext = null; private Map<String, Introspector> allObjs = null; diff --git a/aai-core/src/main/java/org/onap/aai/introspection/MoxyStrategy.java b/aai-core/src/main/java/org/onap/aai/introspection/MoxyStrategy.java index 15311638..57e41081 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/MoxyStrategy.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/MoxyStrategy.java @@ -20,8 +20,8 @@ package org.onap.aai.introspection; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.CaseFormat; import com.google.common.base.Joiner; @@ -54,7 +54,7 @@ import org.springframework.web.util.UriUtils; public class MoxyStrategy extends Introspector { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(MoxyStrategy.class); + private static final Logger LOGGER = LoggerFactory.getLogger(MoxyStrategy.class); private DynamicEntity internalObject = null; private DynamicType internalType = null; private DynamicJAXBContext jaxbContext = null; diff --git a/aai-core/src/main/java/org/onap/aai/introspection/generator/CreateExample.java b/aai-core/src/main/java/org/onap/aai/introspection/generator/CreateExample.java index 73f0a346..8288fd68 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/generator/CreateExample.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/generator/CreateExample.java @@ -20,17 +20,17 @@ package org.onap.aai.introspection.generator; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.*; + import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.introspection.*; - public class CreateExample implements Wanderer { private SecureRandom rand = new SecureRandom(); - private final long range = 100000000L; + private static final long range = 100000000L; private Loader loader = null; private Introspector result = null; private String objectName = null; diff --git a/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/DataCopy.java b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/DataCopy.java index 6a6ee4c1..0994f023 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/DataCopy.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/DataCopy.java @@ -20,17 +20,6 @@ package org.onap.aai.introspection.sideeffect; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collections; -import java.util.List; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Optional; - -import javax.ws.rs.core.MultivaluedMap; - import org.apache.tinkerpop.gremlin.structure.Vertex; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; @@ -42,6 +31,16 @@ import org.onap.aai.schema.enums.PropertyMetadata; import org.onap.aai.serialization.db.DBSerializer; import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import javax.ws.rs.core.MultivaluedMap; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; + public class DataCopy extends SideEffect { public DataCopy(Introspector obj, Vertex self, TransactionalGraphEngine dbEngine, DBSerializer serializer) { @@ -69,14 +68,12 @@ public class DataCopy extends SideEffect { } else { if (results.isEmpty()) { throw new AAIException("AAI_6114", "object located at " + uri + " not found"); - } else if (results.size() > 1) { + } else { throw new AAIMultiplePropertiesException( "multiple values of " + entry.getKey() + " found when searching " + uri); } } - } else { - // skip processing because no required properties were specified - } + } //else skip processing because no required properties were specified } @Override diff --git a/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/PrivateEdge.java b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/PrivateEdge.java index f4f0bfac..06586317 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/PrivateEdge.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/PrivateEdge.java @@ -21,15 +21,6 @@ package org.onap.aai.introspection.sideeffect; import com.google.common.collect.Multimap; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; -import java.util.Map.Entry; - -import javax.ws.rs.core.MultivaluedMap; - import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; @@ -42,7 +33,10 @@ import org.onap.aai.edges.enums.EdgeType; import org.onap.aai.edges.exceptions.AmbiguousRuleChoiceException; import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.introspection.*; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.LoaderFactory; +import org.onap.aai.introspection.ModelType; import org.onap.aai.introspection.sideeffect.exceptions.AAIMultiplePropertiesException; import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.restcore.util.URITools; @@ -52,6 +46,13 @@ import org.onap.aai.serialization.db.EdgeSerializer; import org.onap.aai.serialization.db.exceptions.EdgeMultiplicityException; import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import javax.ws.rs.core.MultivaluedMap; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.Map.Entry; + public class PrivateEdge extends SideEffect { public PrivateEdge(Introspector obj, Vertex self, TransactionalGraphEngine dbEngine, DBSerializer serializer) { @@ -111,40 +112,38 @@ public class PrivateEdge extends SideEffect { throw new EdgeMultiplicityException(message); } - for (Entry<String, EdgeRule> edgeEntry : edgeRulesMap.entries()) { - EdgeRule edgeRule = edgeIngestor.getRule(edgeQuery); - Iterator<Edge> edges = self.edges(edgeRule.getDirection(), edgeRule.getLabel().toString()); - if (edges.hasNext()) { - Edge edge = edges.next(); - EdgeStatus status = checkStatus(obj, self); - switch (status) { - case CREATED: - edgeSerializer.addPrivateEdge(this.dbEngine.asAdmin().getTraversalSource(), self, - otherVertex, edgeRule.getLabel()); - break; - case MODIFIED: - edge.remove(); - edgeSerializer.addPrivateEdge(this.dbEngine.asAdmin().getTraversalSource(), self, - otherVertex, edgeRule.getLabel()); - break; - case REMOVED: - edge.remove(); - break; - case UNCHANGED: - break; - } - } else { - edgeSerializer.addPrivateEdge(this.dbEngine.asAdmin().getTraversalSource(), self, - otherVertex, edgeRule.getLabel()); + EdgeRule edgeRule = edgeIngestor.getRule(edgeQuery); + Iterator<Edge> edges = self.edges(edgeRule.getDirection(), edgeRule.getLabel()); + if (edges.hasNext()) { + Edge edge = edges.next(); + EdgeStatus status = checkStatus(obj, self); + switch (status) { + case CREATED: + edgeSerializer.addPrivateEdge(this.dbEngine.asAdmin().getTraversalSource(), self, + otherVertex, edgeRule.getLabel()); + break; + case MODIFIED: + edge.remove(); + edgeSerializer.addPrivateEdge(this.dbEngine.asAdmin().getTraversalSource(), self, + otherVertex, edgeRule.getLabel()); + break; + case REMOVED: + edge.remove(); + break; + case UNCHANGED: + break; } + } else { + edgeSerializer.addPrivateEdge(this.dbEngine.asAdmin().getTraversalSource(), self, + otherVertex, edgeRule.getLabel()); } } } else { if (results.isEmpty()) { throw new AAIException("AAI_6114", "object located at " + uri + " not found"); - } else if (results.size() > 1) { + } else { throw new AAIMultiplePropertiesException( - "multiple values of " + entry.getKey() + " found when searching " + uri); + "multiple values of " + entry.getKey() + " found when searching " + uri); } } } @@ -159,7 +158,7 @@ public class PrivateEdge extends SideEffect { for (String key : templateKeys) { String currentObjValue = obj.getValue(key); Map<PropertyMetadata, String> map = obj.getPropertyMetadata(key); - String oldVertexValue = null; + String oldVertexValue; if (map.containsKey(PropertyMetadata.DB_ALIAS)) { oldVertexValue = self.<String>property(key + AAIProperties.DB_ALIAS_SUFFIX).orElse(null); diff --git a/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/SideEffect.java b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/SideEffect.java index d86c18a0..a71ffa4e 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/SideEffect.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/SideEffect.java @@ -20,8 +20,8 @@ package org.onap.aai.introspection.sideeffect; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; @@ -46,7 +46,7 @@ import org.onap.aai.setup.SchemaVersions; public abstract class SideEffect { protected static final Pattern template = Pattern.compile("\\{(.*?)\\}"); - private static final EELFLogger logger = EELFManager.getInstance().getLogger(SideEffect.class); + private static final Logger logger = LoggerFactory.getLogger(SideEffect.class); protected final Introspector obj; protected final TransactionalGraphEngine dbEngine; diff --git a/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/SideEffectRunner.java b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/SideEffectRunner.java index ffd9a8c8..8bc83156 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/SideEffectRunner.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/SideEffectRunner.java @@ -20,8 +20,8 @@ package org.onap.aai.introspection.sideeffect; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; diff --git a/aai-core/src/main/java/org/onap/aai/logging/CNName.java b/aai-core/src/main/java/org/onap/aai/logging/CNName.java deleted file mode 100644 index 5337afe3..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/CNName.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import static java.util.Base64.getDecoder; - -import ch.qos.logback.access.pattern.AccessConverter; -import ch.qos.logback.access.spi.IAccessEvent; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -import java.security.cert.X509Certificate; - -import javax.security.auth.x500.X500Principal; -import javax.servlet.http.HttpServletRequest; - -public class CNName extends AccessConverter { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(CNName.class); - - /** - * Converts access events to String response codes - * - * @param accessEvent the IAccessEvent - */ - public String convert(IAccessEvent accessEvent) { - if (!isStarted()) { - return "INACTIVE_HEADER_CONV"; - } - - String cipherSuite = (String) accessEvent.getRequest().getAttribute("javax.servlet.request.cipher_suite"); - String authUser = null; - if (cipherSuite != null) { - try { - X509Certificate certChain[] = (X509Certificate[]) accessEvent.getRequest() - .getAttribute("javax.servlet.request.X509Certificate"); - if (certChain == null || certChain.length == 0) { - - HttpServletRequest request = accessEvent.getRequest(); - - String authorization = request.getHeader("Authorization"); - - // Set the auth user to "-" so if the authorization header is not found - // Or if the decoded basic auth credentials are not found in the format required - // it should return "-" - // If the decoded string is in the right format, find the index of ":" - // Then get the substring of the starting point to the colon not including the colon - - authUser = "-"; - - if (authorization != null && authorization.startsWith("Basic ")) { - String credentials = authorization.replace("Basic ", ""); - byte[] userCredentials = getDecoder().decode(credentials.getBytes("utf-8")); - credentials = new String(userCredentials); - - int codePoint = credentials.indexOf(':'); - - if (codePoint != -1) { - authUser = credentials.substring(0, codePoint); - } - - } - - return authUser; - - } else { - X509Certificate clientCert = certChain[0]; - X500Principal subjectDN = clientCert.getSubjectX500Principal(); - authUser = subjectDN.toString(); - return authUser; - } - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - return "-"; - } - } else { - return "-"; - } - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/DME2RestFlag.java b/aai-core/src/main/java/org/onap/aai/logging/DME2RestFlag.java deleted file mode 100644 index 768c095b..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/DME2RestFlag.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.access.pattern.AccessConverter; -import ch.qos.logback.access.spi.IAccessEvent; - -public class DME2RestFlag extends AccessConverter { - - /** - * @{inheritDoc} - */ - @Override - public String convert(IAccessEvent accessEvent) { - if (!isStarted()) { - return "INACTIVE_HEADER_CONV"; - } - - String flag = "-"; - - if (accessEvent.getRequestParameter("envContext").length > 0 - && !accessEvent.getRequestParameter("envContext")[0].isEmpty() - && !accessEvent.getRequestParameter("envContext")[0].equals("-") - && accessEvent.getRequestParameter("routeOffer").length > 0 - && !accessEvent.getRequestParameter("routeOffer")[0].isEmpty() - && !accessEvent.getRequestParameter("routeOffer")[0].equals("-") - && accessEvent.getRequestParameter("version").length > 0 - && !accessEvent.getRequestParameter("version")[0].isEmpty() - && !accessEvent.getRequestParameter("version")[0].equals("-")) { - flag = "DME2"; - } else { - flag = "REST"; - } - - return flag; - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/EcompElapsedTime.java b/aai-core/src/main/java/org/onap/aai/logging/EcompElapsedTime.java deleted file mode 100644 index 66d27868..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EcompElapsedTime.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; - -import org.onap.aai.logging.LoggingContext.LoggingField; - -public class EcompElapsedTime extends ClassicConverter { - - private static final String DEFAULT_ELAPSED_TIME_FORMAT = "%d"; - - private String ELAPSED_TIME_FORMAT; - - @Override - public void start() { - ELAPSED_TIME_FORMAT = getFirstOption(); - } - - @Override - public String convert(ILoggingEvent event) { - final long end = event.getTimeStamp(); - - if (!event.getMDCPropertyMap().containsKey(LoggingField.START_TIME.toString())) { - return format(0); - } else if (event.getMDCPropertyMap().containsKey(LoggingField.ELAPSED_TIME.toString())) { - return format(Integer.parseInt(event.getMDCPropertyMap().get(LoggingField.ELAPSED_TIME.toString()))); - } - - final long start = - LogFormatTools.toTimestamp(event.getMDCPropertyMap().get(LoggingField.START_TIME.toString())); - - return format(end - start); - } - - private String format(long elapsedTime) { - if (ELAPSED_TIME_FORMAT == null) { - return format(DEFAULT_ELAPSED_TIME_FORMAT, elapsedTime); - } - - return format(ELAPSED_TIME_FORMAT, elapsedTime); - } - - private String format(String format, long elapsedTime) { - return String.format(format, elapsedTime); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/EcompEncoder.java b/aai-core/src/main/java/org/onap/aai/logging/EcompEncoder.java deleted file mode 100644 index 88587297..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EcompEncoder.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.encoder.PatternLayoutEncoder; - -public class EcompEncoder extends PatternLayoutEncoder { - - @Override - public void start() { - PatternLayout patternLayout = new EcompPatternLayout(); - patternLayout.setContext(context); - patternLayout.setPattern(getPattern()); - patternLayout.setOutputPatternAsHeader(outputPatternAsHeader); - patternLayout.start(); - this.layout = patternLayout; - super.start(); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/EcompErrorCategory.java b/aai-core/src/main/java/org/onap/aai/logging/EcompErrorCategory.java deleted file mode 100644 index 452fcd08..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EcompErrorCategory.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class EcompErrorCategory extends ClassicConverter { - - @Override - public String convert(ILoggingEvent event) { - - final Level lev = event.getLevel(); - final String defaultCategory = "WARN"; - - if ((Level.WARN).equals(lev)) { - return (defaultCategory); - } else if ((Level.ERROR).equals(lev)) { - return ("ERROR"); - } - return (defaultCategory); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/EcompPatternLayout.java b/aai-core/src/main/java/org/onap/aai/logging/EcompPatternLayout.java deleted file mode 100644 index 43c147a0..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EcompPatternLayout.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.PatternLayout; - -public class EcompPatternLayout extends PatternLayout { - static { - PatternLayout.defaultConverterMap.put("ecompStartTime", EcompStartTime.class.getName()); - PatternLayout.defaultConverterMap.put("ecompElapsedTime", EcompElapsedTime.class.getName()); - PatternLayout.defaultConverterMap.put("eelfClassOfCaller", EelfClassOfCaller.class.getName()); - PatternLayout.defaultConverterMap.put("ecompErrorCategory", EcompErrorCategory.class.getName()); - PatternLayout.defaultConverterMap.put("ecompResponseCode", EcompResponseCode.class.getName()); - PatternLayout.defaultConverterMap.put("ecompResponseDescription", EcompResponseDescription.class.getName()); - PatternLayout.defaultConverterMap.put("ecompStatusCode", EcompStatusCode.class.getName()); - PatternLayout.defaultConverterMap.put("ecompServiceName", EcompServiceName.class.getName()); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/EcompResponseCode.java b/aai-core/src/main/java/org/onap/aai/logging/EcompResponseCode.java deleted file mode 100644 index 1dc59b4e..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EcompResponseCode.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; - -import org.onap.aai.logging.LoggingContext.LoggingField; - -public class EcompResponseCode extends ClassicConverter { - - @Override - public String convert(ILoggingEvent event) { - - if (!event.getMDCPropertyMap().containsKey(LoggingField.RESPONSE_CODE.toString())) { - // if response code is not set, return "unknown" (900) - return LoggingContext.UNKNOWN_ERROR; - } - return event.getMDCPropertyMap().get(LoggingField.RESPONSE_CODE.toString()); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/EcompResponseDescription.java b/aai-core/src/main/java/org/onap/aai/logging/EcompResponseDescription.java deleted file mode 100644 index b72cc100..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EcompResponseDescription.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; -import org.onap.aai.logging.LoggingContext.LoggingField; - -public class EcompResponseDescription extends ClassicConverter { - public static final String DEFAULT_DESCRIPTION = "Unknown response/error description"; - - @Override - public String convert(ILoggingEvent event) { - - if (!event.getMDCPropertyMap().containsKey(LoggingField.RESPONSE_DESCRIPTION.toString())) { - return (DEFAULT_DESCRIPTION); - } - // Replace pipes and new lines - String currentDesc = event.getMDCPropertyMap().get(LoggingField.RESPONSE_DESCRIPTION.toString()); - if ((currentDesc == null) || (currentDesc.length() == 0)) { - return (DEFAULT_DESCRIPTION); - } - currentDesc = currentDesc.replaceAll("\\|", "!"); - currentDesc = currentDesc.replaceAll("[\\r\\n]+", "^"); - return event.getMDCPropertyMap().get(currentDesc); - } -} - - diff --git a/aai-core/src/main/java/org/onap/aai/logging/EcompServiceName.java b/aai-core/src/main/java/org/onap/aai/logging/EcompServiceName.java deleted file mode 100644 index 10d7a211..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EcompServiceName.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; - -import org.onap.aai.logging.LoggingContext.LoggingField; - -public class EcompServiceName extends ClassicConverter { - @Override - public String convert(ILoggingEvent event) { - if (!event.getMDCPropertyMap().containsKey(LoggingField.SERVICE_NAME.toString())) { - return "AAI"; - } - return event.getMDCPropertyMap().get(LoggingField.SERVICE_NAME.toString()); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/EcompStartTime.java b/aai-core/src/main/java/org/onap/aai/logging/EcompStartTime.java deleted file mode 100644 index 8f015414..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EcompStartTime.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; - -import org.onap.aai.logging.LoggingContext.LoggingField; - -public class EcompStartTime extends ClassicConverter { - - @Override - public String convert(ILoggingEvent event) { - - if (!event.getMDCPropertyMap().containsKey(LoggingField.START_TIME.toString())) { - return LogFormatTools.toDate(event.getTimeStamp()); - } - - return event.getMDCPropertyMap().get(LoggingField.START_TIME.toString()); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/EcompStatusCode.java b/aai-core/src/main/java/org/onap/aai/logging/EcompStatusCode.java deleted file mode 100644 index 4319bbbd..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EcompStatusCode.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; - -import org.onap.aai.logging.LoggingContext.LoggingField; - -public class EcompStatusCode extends ClassicConverter { - @Override - public String convert(ILoggingEvent event) { - if (!event.getMDCPropertyMap().containsKey(LoggingField.STATUS_CODE.toString())) { - return LoggingContext.StatusCode.COMPLETE.toString(); - } - return event.getMDCPropertyMap().get(LoggingField.STATUS_CODE.toString()); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/EelfClassOfCaller.java b/aai-core/src/main/java/org/onap/aai/logging/EelfClassOfCaller.java deleted file mode 100644 index dc9bc2c2..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/EelfClassOfCaller.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import ch.qos.logback.classic.pattern.NamedConverter; -import ch.qos.logback.classic.spi.CallerData; -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class EelfClassOfCaller extends NamedConverter { - protected String getFullyQualifiedName(ILoggingEvent event) { - - StackTraceElement[] cda = event.getCallerData(); - - // If using the EELFLogger, it "hides" the calling class because it wraps the logging calls - // Without this, you'd only ever see "EELF SLF4jWrapper" when using the - // %C pattern converter - if (cda != null && cda.length > 2) { - return cda[2].getClassName(); - } else if (cda != null && cda.length > 0) { - return cda[0].getClassName(); - } else { - return CallerData.NA; - } - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/ErrorLogHelper.java b/aai-core/src/main/java/org/onap/aai/logging/ErrorLogHelper.java deleted file mode 100644 index 01327606..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/ErrorLogHelper.java +++ /dev/null @@ -1,633 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; - -import javax.ws.rs.core.MediaType; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.Marshaller; - -import org.apache.commons.lang.StringUtils; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.logging.LoggingContext.StatusCode; -import org.onap.aai.util.AAIConfig; -import org.onap.aai.util.AAIConstants; -import org.onap.aai.util.MapperUtil; -import org.slf4j.MDC; - -/** - * - * This classes loads the application error properties file - * and provides a method that returns an ErrorObject - * - */ - -public class ErrorLogHelper { - - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ErrorLogHelper.class); - private static final HashMap<String, ErrorObject> ERROR_OBJECTS = new HashMap<String, ErrorObject>(); - - static { - try { - loadProperties(); - } catch (IOException e) { - throw new RuntimeException("Failed to load error.properties file", e); - } catch (ErrorObjectFormatException e) { - throw new RuntimeException("Failed to parse error.properties file", e); - } - } - - /** - * Load properties. - * - * @throws ErrorObjectFormatException - * @throws Exception the exception - */ - public static void loadProperties() throws IOException, ErrorObjectFormatException { - final String filePath = AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "error.properties"; - final InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath); - final Properties properties = new Properties(); - - if (is != null) { - properties.load(is); - } else { - try (final FileInputStream fis = new FileInputStream(filePath)) { - properties.load(fis); - } - } - - for (Entry<Object, Object> entry : properties.entrySet()) { - final String key = (String) entry.getKey(); - final String value = (String) entry.getValue(); - final String[] errorProperties = value.split(":"); - - if (errorProperties.length != 7) - throw new ErrorObjectFormatException(); - - final ErrorObject errorObject = new ErrorObject(); - - errorObject.setDisposition(errorProperties[0].trim()); - errorObject.setCategory(errorProperties[1].trim()); - errorObject.setSeverity(errorProperties[2].trim()); - errorObject.setErrorCode(errorProperties[3].trim()); - errorObject.setHTTPResponseCode(errorProperties[4].trim()); - errorObject.setRESTErrorCode(errorProperties[5].trim()); - errorObject.setErrorText(errorProperties[6].trim()); - - ERROR_OBJECTS.put(key, errorObject); - } - } - - /** - * Logs a known A&AI exception (i.e. one that can be found in error.properties) - * - * @param key The key for the error in the error.properties file - * @throws IOException - * @throws ErrorObjectNotFoundException - * @throws ErrorObjectFormatException - */ - public static ErrorObject getErrorObject(String code) throws ErrorObjectNotFoundException { - - if (code == null) - throw new IllegalArgumentException("Key cannot be null"); - - final ErrorObject errorObject = ERROR_OBJECTS.get(code); - - if (errorObject == null) { - LOGGER.warn("Unknown AAIException with code=" + code + ". Using default AAIException"); - return ERROR_OBJECTS.get(AAIException.DEFAULT_EXCEPTION_CODE); - } - - return errorObject; - } - - /** - * Determines whether category is policy or not. If policy (1), this is a POL error, else it's a SVC error. - * The AAIRESTException may contain a different ErrorObject than that created with the REST error key. - * This allows lower level exception detail to be returned to the client to help troubleshoot the problem. - * If no error object is embedded in the AAIException, one will be created using the error object from the - * AAIException. - * - * @param are must have a restError value whose numeric value must match what should be returned in the REST API - * @param variables optional list of variables to flesh out text in error string - * @return appropriately formatted JSON response per the REST API spec. - * @throws ErrorObjectFormatException - * @throws ErrorObjectNotFoundException - * @throws IOException - * @deprecated - */ - public static String getRESTAPIErrorResponse(AAIException are, ArrayList<String> variables) { - List<MediaType> acceptHeaders = new ArrayList<MediaType>(); - acceptHeaders.add(MediaType.APPLICATION_JSON_TYPE); - - return getRESTAPIErrorResponse(acceptHeaders, are, variables); - } - - /** - * Determines whether category is policy or not. If policy (1), this is a POL error, else it's a SVC error. - * The AAIRESTException may contain a different ErrorObject than that created with the REST error key. - * This allows lower level exception detail to be returned to the client to help troubleshoot the problem. - * If no error object is embedded in the AAIException, one will be created using the error object from the - * AAIException. - * - * @param acceptHeadersOrig the accept headers orig - * @param are must have a restError value whose numeric value must match what should be returned in the REST API - * @param variables optional list of variables to flesh out text in error string - * @return appropriately formatted JSON response per the REST API spec. - * @throws ErrorObjectFormatException - * @throws ErrorObjectNotFoundException - * @throws IOException - */ - public static String getRESTAPIErrorResponse(List<MediaType> acceptHeadersOrig, AAIException are, - ArrayList<String> variables) { - - StringBuilder text = new StringBuilder(); - String response = null; - - List<MediaType> acceptHeaders = new ArrayList<MediaType>(); - // we might have an exception but no accept header, so we'll set default to JSON - boolean foundValidAcceptHeader = false; - for (MediaType mt : acceptHeadersOrig) { - if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt) || MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) { - acceptHeaders.add(mt); - foundValidAcceptHeader = true; - } - } - if (foundValidAcceptHeader == false) { - // override the exception, client needs to set an appropriate Accept header - are = new AAIException("AAI_4014"); - acceptHeaders.add(MediaType.APPLICATION_JSON_TYPE); - } - - final ErrorObject eo = are.getErrorObject(); - - int restErrorCode = Integer.parseInt(eo.getRESTErrorCode()); - - ErrorObject restErrorObject; - - try { - restErrorObject = ErrorLogHelper.getErrorObject("AAI_" + restErrorCode); - } catch (ErrorObjectNotFoundException e) { - LOGGER.warn("Failed to find related error object AAI_" + restErrorCode + " for error object " - + eo.getErrorCode() + "; using AAI_" + restErrorCode); - restErrorObject = eo; - } - - text.append(restErrorObject.getErrorText()); - - // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n - // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the - // error, are ordered based on the error string. - int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%"); - text.append(" (msg=%").append(localDataIndex + 1).append(") (ec=%").append(localDataIndex + 2).append(")"); - - if (variables == null) { - variables = new ArrayList<String>(); - } - - if (variables.size() < localDataIndex) { - ErrorLogHelper.logError("AAI_4011", "data missing for rest error"); - while (variables.size() < localDataIndex) { - variables.add("null"); - } - } - - // This will put the error code and error text into the right positions - if (are.getMessage() == null || are.getMessage().length() == 0) { - variables.add(localDataIndex++, eo.getErrorText()); - } else { - variables.add(localDataIndex++, eo.getErrorText() + ":" + are.getMessage()); - } - variables.add(localDataIndex, eo.getErrorCodeString()); - - for (MediaType mediaType : acceptHeaders) { - if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) { - JAXBContext context = null; - try { - if (eo.getCategory().equals("1")) { - - context = JAXBContext.newInstance(org.onap.aai.domain.restPolicyException.Fault.class); - Marshaller m = context.createMarshaller(); - m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); - m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); - - org.onap.aai.domain.restPolicyException.ObjectFactory factory = - new org.onap.aai.domain.restPolicyException.ObjectFactory(); - org.onap.aai.domain.restPolicyException.Fault fault = factory.createFault(); - org.onap.aai.domain.restPolicyException.Fault.RequestError requestError = - factory.createFaultRequestError(); - org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException policyException = - factory.createFaultRequestErrorPolicyException(); - org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException.Variables polvariables = - factory.createFaultRequestErrorPolicyExceptionVariables(); - - policyException.setMessageId("POL" + eo.getRESTErrorCode()); - policyException.setText(text.toString()); - for (int i = 0; i < variables.size(); i++) { - polvariables.getVariable().add(variables.get(i)); - } - policyException.setVariables(polvariables); - requestError.setPolicyException(policyException); - fault.setRequestError(requestError); - - StringWriter sw = new StringWriter(); - m.marshal(fault, sw); - - response = sw.toString(); - - } else { - - context = JAXBContext.newInstance(org.onap.aai.domain.restServiceException.Fault.class); - Marshaller m = context.createMarshaller(); - m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); - m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); - - org.onap.aai.domain.restServiceException.ObjectFactory factory = - new org.onap.aai.domain.restServiceException.ObjectFactory(); - org.onap.aai.domain.restServiceException.Fault fault = factory.createFault(); - org.onap.aai.domain.restServiceException.Fault.RequestError requestError = - factory.createFaultRequestError(); - org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException serviceException = - factory.createFaultRequestErrorServiceException(); - org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException.Variables svcvariables = - factory.createFaultRequestErrorServiceExceptionVariables(); - serviceException.setMessageId("SVC" + eo.getRESTErrorCode()); - serviceException.setText(text.toString()); - for (int i = 0; i < variables.size(); i++) { - svcvariables.getVariable().add(variables.get(i)); - } - serviceException.setVariables(svcvariables); - requestError.setServiceException(serviceException); - fault.setRequestError(requestError); - - StringWriter sw = new StringWriter(); - m.marshal(fault, sw); - - response = sw.toString(); - - } - } catch (Exception ex) { - LOGGER.error( - "We were unable to create a rest exception to return on an API because of a parsing error " - + ex.getMessage()); - } - } else { - try { - if (eo.getCategory().equals("1")) { - org.onap.aai.domain.restPolicyException.RESTResponse restresp = - new org.onap.aai.domain.restPolicyException.RESTResponse(); - org.onap.aai.domain.restPolicyException.RequestError reqerr = - new org.onap.aai.domain.restPolicyException.RequestError(); - org.onap.aai.domain.restPolicyException.PolicyException polexc = - new org.onap.aai.domain.restPolicyException.PolicyException(); - polexc.setMessageId("POL" + eo.getRESTErrorCode()); - polexc.setText(text.toString()); - polexc.setVariables(variables); - reqerr.setPolicyException(polexc); - restresp.setRequestError(reqerr); - response = (MapperUtil.writeAsJSONString((Object) restresp)); - - } else { - org.onap.aai.domain.restServiceException.RESTResponse restresp = - new org.onap.aai.domain.restServiceException.RESTResponse(); - org.onap.aai.domain.restServiceException.RequestError reqerr = - new org.onap.aai.domain.restServiceException.RequestError(); - org.onap.aai.domain.restServiceException.ServiceException svcexc = - new org.onap.aai.domain.restServiceException.ServiceException(); - svcexc.setMessageId("SVC" + eo.getRESTErrorCode()); - svcexc.setText(text.toString()); - svcexc.setVariables(variables); - reqerr.setServiceException(svcexc); - restresp.setRequestError(reqerr); - response = (MapperUtil.writeAsJSONString((Object) restresp)); - } - } catch (AAIException ex) { - LOGGER.error( - "We were unable to create a rest exception to return on an API because of a parsing error " - + ex.getMessage()); - } - } - } - - return response; - } - - /** - * Gets the RESTAPI error response with logging. - * - * @param acceptHeadersOrig the accept headers orig - * @param are the are - * @param variables the variables - * @param logline the logline - * @return the RESTAPI error response with logging - * @throws ErrorObjectFormatException - * @throws ErrorObjectNotFoundException - * @throws IOException - */ - public static String getRESTAPIErrorResponseWithLogging(List<MediaType> acceptHeadersOrig, AAIException are, - ArrayList<String> variables) { - String response = ErrorLogHelper.getRESTAPIErrorResponse(acceptHeadersOrig, are, variables); - - LOGGER.error(are.getMessage() + " " + LogFormatTools.getStackTop(are)); - - return response; - } - - /** - * Gets the RESTAPI info response. - * - * @param acceptHeaders the accept headers - * @param areList the are list - * @return the RESTAPI info response - * @throws ErrorObjectFormatException - * @throws ErrorObjectNotFoundException - * @throws IOException - */ - public static Object getRESTAPIInfoResponse(List<MediaType> acceptHeaders, - HashMap<AAIException, ArrayList<String>> areList) { - - Object respObj = null; - - org.onap.aai.domain.restResponseInfo.ObjectFactory factory = - new org.onap.aai.domain.restResponseInfo.ObjectFactory(); - org.onap.aai.domain.restResponseInfo.Info info = factory.createInfo(); - org.onap.aai.domain.restResponseInfo.Info.ResponseMessages responseMessages = - factory.createInfoResponseMessages(); - Iterator<Entry<AAIException, ArrayList<String>>> it = areList.entrySet().iterator(); - - while (it.hasNext()) { - Entry<AAIException, ArrayList<String>> pair = (Entry<AAIException, ArrayList<String>>) it.next(); - AAIException are = pair.getKey(); - ArrayList<String> variables = pair.getValue(); - - StringBuilder text = new StringBuilder(); - - ErrorObject eo = are.getErrorObject(); - - int restErrorCode = Integer.parseInt(eo.getRESTErrorCode()); - ErrorObject restErrorObject; - try { - restErrorObject = ErrorLogHelper.getErrorObject("AAI_" + String.format("%04d", restErrorCode)); - } catch (ErrorObjectNotFoundException e) { - restErrorObject = eo; - } - text.append(restErrorObject.getErrorText()); - - // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n - // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the - // error, are ordered based on the error string. - int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%"); - text.append(" (msg=%").append(localDataIndex + 1).append(") (rc=%").append(localDataIndex + 2).append(")"); - - if (variables == null) { - variables = new ArrayList<String>(); - } - - if (variables.size() < localDataIndex) { - ErrorLogHelper.logError("AAI_4011", "data missing for rest error"); - while (variables.size() < localDataIndex) { - variables.add("null"); - } - } - - // This will put the error code and error text into the right positions - if (are.getMessage() == null) { - variables.add(localDataIndex++, eo.getErrorText()); - } else { - variables.add(localDataIndex++, eo.getErrorText() + ":" + are.getMessage()); - } - variables.add(localDataIndex, eo.getErrorCodeString()); - - try { - org.onap.aai.domain.restResponseInfo.Info.ResponseMessages.ResponseMessage responseMessage = - factory.createInfoResponseMessagesResponseMessage(); - org.onap.aai.domain.restResponseInfo.Info.ResponseMessages.ResponseMessage.Variables infovariables = - factory.createInfoResponseMessagesResponseMessageVariables(); - - responseMessage.setMessageId("INF" + eo.getRESTErrorCode()); - responseMessage.setText(text.toString()); - for (int i = 0; i < variables.size(); i++) { - infovariables.getVariable().add(variables.get(i)); - } - - responseMessage.setVariables(infovariables); - responseMessages.getResponseMessage().add(responseMessage); - - } catch (Exception ex) { - LOGGER.error("We were unable to create a rest exception to return on an API because of a parsing error " - + ex.getMessage()); - } - } - - info.setResponseMessages(responseMessages); - respObj = (Object) info; - - return respObj; - } - - /** - * Determines whether category is policy or not. If policy (1), this is a POL error, else it's a SVC error. - * The AAIRESTException may contain a different ErrorObject than that created with the REST error key. - * This allows lower level exception detail to be returned to the client to help troubleshoot the problem. - * If no error object is embedded in the AAIException, one will be created using the error object from the - * AAIException. - * - * @param are must have a restError value whose numeric value must match what should be returned in the REST API - * @param variables optional list of variables to flesh out text in error string - * @return appropriately formatted JSON response per the REST API spec. - * @throws ErrorObjectFormatException - * @throws ErrorObjectNotFoundException - * @throws IOException - */ - public static String getRESTAPIPolicyErrorResponseXML(AAIException are, ArrayList<String> variables) { - - StringBuilder text = new StringBuilder(); - String response = null; - JAXBContext context = null; - - ErrorObject eo = are.getErrorObject(); - - int restErrorCode = Integer.parseInt(eo.getRESTErrorCode()); - ErrorObject restErrorObject; - try { - restErrorObject = ErrorLogHelper.getErrorObject("AAI_" + restErrorCode); - } catch (ErrorObjectNotFoundException e) { - restErrorObject = eo; - } - - text.append(restErrorObject.getErrorText()); - - // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n - // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the - // error, are ordered based on the error string. - int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%"); - text.append(" (msg=%").append(localDataIndex + 1).append(") (ec=%").append(localDataIndex + 2).append(")"); - - if (variables == null) { - variables = new ArrayList<String>(); - } - - if (variables.size() < localDataIndex) { - ErrorLogHelper.logError("AAI_4011", "data missing for rest error"); - while (variables.size() < localDataIndex) { - variables.add("null"); - } - } - - // This will put the error code and error text into the right positions - if (are.getMessage() == null) { - variables.add(localDataIndex++, eo.getErrorText()); - } else { - variables.add(localDataIndex++, eo.getErrorText() + ":" + are.getMessage()); - } - variables.add(localDataIndex, eo.getErrorCodeString()); - - try { - if (eo.getCategory().equals("1")) { - - context = JAXBContext.newInstance(org.onap.aai.domain.restPolicyException.Fault.class); - Marshaller m = context.createMarshaller(); - m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); - m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); - - org.onap.aai.domain.restPolicyException.ObjectFactory factory = - new org.onap.aai.domain.restPolicyException.ObjectFactory(); - org.onap.aai.domain.restPolicyException.Fault fault = factory.createFault(); - org.onap.aai.domain.restPolicyException.Fault.RequestError requestError = - factory.createFaultRequestError(); - org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException policyException = - factory.createFaultRequestErrorPolicyException(); - org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException.Variables polvariables = - factory.createFaultRequestErrorPolicyExceptionVariables(); - - policyException.setMessageId("POL" + eo.getRESTErrorCode()); - policyException.setText(text.toString()); - for (int i = 0; i < variables.size(); i++) { - polvariables.getVariable().add(variables.get(i)); - } - policyException.setVariables(polvariables); - requestError.setPolicyException(policyException); - fault.setRequestError(requestError); - - StringWriter sw = new StringWriter(); - m.marshal(fault, sw); - - response = sw.toString(); - - } else { - - context = JAXBContext.newInstance(org.onap.aai.domain.restServiceException.Fault.class); - Marshaller m = context.createMarshaller(); - m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); - m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); - - org.onap.aai.domain.restServiceException.ObjectFactory factory = - new org.onap.aai.domain.restServiceException.ObjectFactory(); - org.onap.aai.domain.restServiceException.Fault fault = factory.createFault(); - org.onap.aai.domain.restServiceException.Fault.RequestError requestError = - factory.createFaultRequestError(); - org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException serviceException = - factory.createFaultRequestErrorServiceException(); - org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException.Variables svcvariables = - factory.createFaultRequestErrorServiceExceptionVariables(); - serviceException.setMessageId("POL" + eo.getRESTErrorCode()); - serviceException.setText(text.toString()); - for (int i = 0; i < variables.size(); i++) { - svcvariables.getVariable().add(variables.get(i)); - } - serviceException.setVariables(svcvariables); - requestError.setServiceException(serviceException); - fault.setRequestError(requestError); - - StringWriter sw = new StringWriter(); - m.marshal(fault, sw); - - response = sw.toString(); - - } - } catch (Exception ex) { - LOGGER.error("We were unable to create a rest exception to return on an API because of a parsing error " - + ex.getMessage()); - } - return response; - } - - public static void logException(AAIException e) { - final ErrorObject errorObject = e.getErrorObject(); - - // MDC.put("severity", errorObject.getSeverity()); //TODO Use LoggingContext.severity(int severity) - String severityCode = errorObject.getSeverityCode(errorObject.getSeverity()); - - if (!AAIConfig.isEmpty(severityCode)) { - int sevCode = Integer.parseInt(severityCode); - if (sevCode > 0 && sevCode <= 3) { - LoggingContext.severity(sevCode); - } - } - String stackTrace = ""; - try { - stackTrace = LogFormatTools.getStackTop(e); - } catch (Exception a) { - // ignore - } - final String errorMessage = new StringBuilder().append(errorObject.getErrorText()).append(":") - .append(errorObject.getRESTErrorCode()).append(":").append(errorObject.getHTTPResponseCode()) - .append(":").append(e.getMessage()).toString().replaceAll("\\n", "^"); - - LoggingContext.responseCode(Integer.toString(errorObject.getHTTPResponseCode().getStatusCode())); - LoggingContext.responseDescription(errorMessage); - LoggingContext.statusCode(StatusCode.ERROR); - - final String details = - new StringBuilder().append(errorObject.getErrorCodeString()).append(" ").append(stackTrace).toString(); - - if (errorObject.getSeverity().equalsIgnoreCase("WARN")) - LOGGER.warn(details); - else if (errorObject.getSeverity().equalsIgnoreCase("ERROR")) - LOGGER.error(details); - else if (errorObject.getSeverity().equalsIgnoreCase("FATAL")) - LOGGER.error(details); - else if (errorObject.getSeverity().equals("INFO")) - LOGGER.info(details); - } - - public static void logError(String code) { - logError(code, ""); - } - - public static void logError(String code, String message) { - logException(new AAIException(code, message)); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/ErrorObject.java b/aai-core/src/main/java/org/onap/aai/logging/ErrorObject.java deleted file mode 100644 index 6048c18b..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/ErrorObject.java +++ /dev/null @@ -1,359 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import javax.ws.rs.core.Response.Status; - -/** - * - * Contains the definition of all error message fields to be mapped from the Error - * properties file - * - */ -public class ErrorObject { - - private String disposition; - private String category; - private String severity; - private Status httpResponseCode = Status.INTERNAL_SERVER_ERROR; // default - private String restErrorCode = "3002"; - private String errorCode; - private String errorText; - private String details; - - /** - * Instantiates a new error object. - */ - public ErrorObject() { - super(); - } - - /** - * Creates an error object with the default HTTP Error Code (Status.INTERNAL_SERVER_ERROR) - * - * @param disposition the disposition - * @param category the category - * @param severity the severity - * @param httpResponseCode the http response code - * @param restErrorCode the rest error code - * @param errorCode the error code - * @param errorText the error text - */ - public ErrorObject(String disposition, String category, String severity, Integer httpResponseCode, - String restErrorCode, String errorCode, String errorText) { - super(); - this.setDisposition(disposition); - this.setCategory(category); - this.severity = severity; - this.setHTTPResponseCode(httpResponseCode); - this.setRESTErrorCode(restErrorCode); - this.setErrorCode(errorCode); - this.setErrorText(errorText); - } - - // OLD STARTS HERE - - /** - * Instantiates a new error object. - * - * @param severity the severity - * @param errorCode the error code - * @param errorText the error text - * @param disposition the disposition - * @param category the category - */ - public ErrorObject(String severity, String errorCode, String errorText, String disposition, String category) { - this(severity, Status.INTERNAL_SERVER_ERROR, errorCode, errorText, disposition, category); - } - - /** - * Instantiates a new error object. - * - * @param severity the severity - * @param httpResponseCode the http response code - * @param errorCode the error code - * @param errorText the error text - * @param disposition the disposition - * @param category the category - */ - public ErrorObject(String severity, Integer httpResponseCode, String errorCode, String errorText, - String disposition, String category) { - super(); - this.severity = severity; - this.setHTTPResponseCode(httpResponseCode); - this.setErrorCode(errorCode); - this.setErrorText(errorText); - this.setDisposition(disposition); - this.setCategory(category); - } - - /** - * Instantiates a new error object. - * - * @param severity the severity - * @param httpResponseCode the http response code - * @param errorCode the error code - * @param errorText the error text - * @param disposition the disposition - * @param category the category - */ - public ErrorObject(String severity, Status httpResponseCode, String errorCode, String errorText, String disposition, - String category) { - super(); - this.severity = severity; - this.setHTTPResponseCode(httpResponseCode); - this.setErrorCode(errorCode); - this.setErrorText(errorText); - this.setDisposition(disposition); - this.setCategory(category); - } - - /** - * Gets the disposition. - * - * @return the disposition - */ - public String getDisposition() { - return disposition; - } - - /** - * Sets the disposition. - * - * @param disposition the new disposition - */ - public void setDisposition(String disposition) { - this.disposition = disposition; - } - - /** - * Gets the category. - * - * @return the category - */ - public String getCategory() { - return category; - } - - /** - * Sets the category. - * - * @param category the new category - */ - public void setCategory(String category) { - this.category = category; - } - - /** - * Gets the severity. - * - * @return the severity - */ - public String getSeverity() { - return severity; - } - - /** - * Sets the severity. - * - * @param severity the new severity - */ - public void setSeverity(String severity) { - this.severity = severity; - } - - /** - * Gets the error code. - * - * @return the error code - */ - public String getErrorCode() { - return errorCode; - } - - /** - * Sets the error code. - * - * @param errorCode the new error code - */ - public void setErrorCode(String errorCode) { - this.errorCode = errorCode; - } - - /** - * Gets the HTTP response code. - * - * @return the HTTP response code - */ - public Status getHTTPResponseCode() { - return httpResponseCode; - } - - /** - * Sets the HTTP response code. - * - * @param httpResponseCode the new HTTP response code - */ - public void setHTTPResponseCode(Integer httpResponseCode) { - this.httpResponseCode = Status.fromStatusCode(httpResponseCode); - if (this.httpResponseCode == null) { - throw new IllegalArgumentException( - "setHTTPResponseCode was passed an invalid Integer value, fix error.properties or your code " - + httpResponseCode); - } - } - - /** - * Sets the HTTP response code. - * - * @param httpResponseCode the new HTTP response code - */ - public void setHTTPResponseCode(String httpResponseCode) { - this.httpResponseCode = Status.fromStatusCode(Integer.valueOf(httpResponseCode)); - if (this.httpResponseCode == null) { - throw new IllegalArgumentException( - "setHTTPResponseCode was passed an invalid String value, fix error.properties or your code " - + httpResponseCode); - } - } - - /** - * Sets the REST error code. - * - * @param restErrorCode the new REST error code - */ - public void setRESTErrorCode(String restErrorCode) { - this.restErrorCode = restErrorCode; - } - - /** - * Gets the REST error code. - * - * @return the REST error code - */ - public String getRESTErrorCode() { - return this.restErrorCode; - } - - /** - * Sets the HTTP response code. - * - * @param httpResponseCode the new HTTP response code - */ - public void setHTTPResponseCode(Status httpResponseCode) { - this.httpResponseCode = httpResponseCode; - if (this.httpResponseCode == null) { - throw new IllegalArgumentException( - "setHTTPResponseCode was passed an invalid String value, fix error.properties or your code " - + httpResponseCode); - } - } - - /** - * Gets the error text. - * - * @return the error text - */ - public String getErrorText() { - return errorText; - } - - /** - * Sets the error text. - * - * @param errorText the new error text - */ - public void setErrorText(String errorText) { - this.errorText = errorText; - } - - /** - * Gets the details. - * - * @return the details - */ - public String getDetails() { - return details; - } - - /** - * Sets the details. - * - * @param details the new details - */ - public void setDetails(String details) { - this.details = details == null ? "" : details; - } - - /** - * Gets the error code string. This is also the string - * configured in Nagios to alert on - * - * @return the error code string - */ - // Get the X.Y.Z representation of the error code - public String getErrorCodeString() { - String prefix = null; - switch (disposition) { - default: - prefix = ""; - break; - case "5": - prefix = "ERR."; - break; - } - return prefix + disposition + "." + category + "." + errorCode; - } - - /** - * Gets the severity Code. This is also the string - * configured in Nagios to alert on - * - * @return the severity - */ - // Get the numerical value of severity - public String getSeverityCode(String severity) { - String severityCode = ""; - switch (severity) { - case "WARN": - severityCode = "1"; - break; - case "ERROR": - severityCode = "2"; - break; - case "FATAL": - severityCode = "3"; - break; - } - return severityCode; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return "ErrorObject [errorCode=" + errorCode + ", errorText=" + errorText + ", restErrorCode=" + restErrorCode - + ", httpResponseCode=" + httpResponseCode + ", severity=" + severity + ", disposition=" + disposition - + ", category=" + category + "]"; - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/ErrorObjectNotFoundException.java b/aai-core/src/main/java/org/onap/aai/logging/ErrorObjectNotFoundException.java deleted file mode 100644 index 3daf7137..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/ErrorObjectNotFoundException.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -public class ErrorObjectNotFoundException extends Exception { - - private static final long serialVersionUID = 4115316781400786740L; - - public ErrorObjectNotFoundException() { - // TODO Auto-generated constructor stub - } - - public ErrorObjectNotFoundException(String message) { - super(message); - // TODO Auto-generated constructor stub - } - - public ErrorObjectNotFoundException(Throwable cause) { - super(cause); - // TODO Auto-generated constructor stub - } - - public ErrorObjectNotFoundException(String message, Throwable cause) { - super(message, cause); - // TODO Auto-generated constructor stub - } - - public ErrorObjectNotFoundException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - // TODO Auto-generated constructor stub - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/LogFormatTools.java b/aai-core/src/main/java/org/onap/aai/logging/LogFormatTools.java deleted file mode 100644 index 804801f1..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/LogFormatTools.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; - -import org.apache.commons.lang.exception.ExceptionUtils; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.util.AAIConfig; -import org.onap.aai.util.AAIConstants; - -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()); - } - - public static String toDate(long timestamp) { - return DTF.format(Instant.ofEpochMilli(timestamp)); - } - - public static long toTimestamp(String date) { - return ZonedDateTime.parse(date, DTF).toInstant().toEpochMilli(); - } - - /** - * Gets the stack top. - * - * @param e the e - * @return the stack top - * @throws NumberFormatException the number format exception - * @throws AAIException the AAI exception - */ - public static String getStackTop(Throwable e) { - // StringBuilder is more efficient than StringBuffer and should only - // StringBuffer is only supposed to be used if multiple threads are modifying - // the same object and since this object is created locally not necessary - StringBuilder stackMessage = new StringBuilder(); - int maxStackTraceEntries = 10; - try { - maxStackTraceEntries = Integer.valueOf(AAIConfig.get(AAIConstants.LOGGING_MAX_STACK_TRACE_ENTRIES)); - } catch (AAIException a) { - // ignore, use default - } catch (NumberFormatException n) { - // ignore, use default - } - if (e != null) { - Throwable rootCause = ExceptionUtils.getRootCause(e); - if (rootCause != null) { - stackMessage.append("root cause=" + ExceptionUtils.getRootCause(e)); - StackTraceElement[] elements = rootCause.getStackTrace(); - int i = 0; - for (StackTraceElement element : elements) { - if (i < maxStackTraceEntries) { - stackMessage.append(" ClassName- "); - stackMessage.append(element.getClassName()); - stackMessage.append(" :LineNumber- "); - stackMessage.append(element.getLineNumber()); - stackMessage.append(" :MethodName- "); - stackMessage.append(element.getMethodName()); - } - i++; - } - } else if (e.getCause() != null) { - stackMessage.append("cause=" + e.getCause()); - StackTraceElement[] elements = e.getCause().getStackTrace(); - int i = 0; - for (StackTraceElement element : elements) { - if (i < maxStackTraceEntries) { - stackMessage.append(" ClassName- "); - stackMessage.append(element.getClassName()); - stackMessage.append(" :LineNumber- "); - stackMessage.append(element.getLineNumber()); - stackMessage.append(" :MethodName- "); - stackMessage.append(element.getMethodName()); - } - i++; - } - } else if (e.getStackTrace() != null) { - stackMessage.append("ex=" + e.toString()); - StackTraceElement[] elements = e.getStackTrace(); - int i = 0; - for (StackTraceElement element : elements) { - if (i < maxStackTraceEntries) { - stackMessage.append(" ClassName- "); - stackMessage.append(element.getClassName()); - stackMessage.append(" :LineNumber- "); - stackMessage.append(element.getLineNumber()); - stackMessage.append(" :MethodName- "); - stackMessage.append(element.getMethodName()); - } - i++; - } - } - } - return stackMessage.toString(); - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/LoggingContext.java b/aai-core/src/main/java/org/onap/aai/logging/LoggingContext.java deleted file mode 100644 index 5630fd10..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/LoggingContext.java +++ /dev/null @@ -1,417 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.slf4j.MDC; - -public class LoggingContext { - - public enum StatusCode { - COMPLETE, ERROR - } - - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(LoggingContext.class); - - private static final String PREVIOUS_CONTEXTS_KEY = "_PREVIOUS_CONTEXTS"; - - // Response codes from Logging Guidelines - public static final String SUCCESS = "0"; - public static final String PERMISSION_ERROR = "100"; - public static final String AVAILABILITY_TIMEOUT_ERROR = "200"; - public static final String DATA_ERROR = "300"; - public static final String SCHEMA_ERROR = "400"; - public static final String BUSINESS_PROCESS_ERROR = "500"; - public static final String UNKNOWN_ERROR = "900"; - - protected static final Map<String, String> responseMap = new HashMap(); - - static { - responseMap.put(SUCCESS, "Success"); - responseMap.put(UNKNOWN_ERROR, "Unknown error"); - } - - // Specific Log Event Fields - public enum LoggingField { - START_TIME("startTime"), REQUEST_ID("requestId"), SERVICE_INSTANCE_ID("serviceInstanceId"), SERVER_NAME( - "serverName"), SERVICE_NAME("serviceName"), PARTNER_NAME("partnerName"), STATUS_CODE( - "statusCode"), RESPONSE_CODE("responseCode"), RESPONSE_DESCRIPTION( - "responseDescription"), INSTANCE_UUID("instanceUUID"), SEVERITY( - "severity"), SERVER_IP_ADDRESS( - "serverIpAddress"), ELAPSED_TIME("elapsedTime"), SERVER( - "server"), CLIENT_IP_ADDRESS("clientIpAddress"), UNUSED( - "unused"), PROCESS_KEY("processKey"), CUSTOM_FIELD_1( - "customField1"), CUSTOM_FIELD_2( - "customField2"), CUSTOM_FIELD_3( - "customField3"), CUSTOM_FIELD_4( - "customField4"), - - // Specific Metric Log Event Fields - TARGET_ENTITY("targetEntity"), TARGET_SERVICE_NAME("targetServiceName"), - // A&AI Specific Log Event Fields - COMPONENT("component"), STOP_WATCH_START("stopWatchStart"); - - private final String text; - - private LoggingField(final String text) { - this.text = text; - } - - @Override - public String toString() { - return text; - } - } - - public static void init() { - LoggingContext.clear(); - LoggingContext.startTime(); - LoggingContext.server(); - LoggingContext.serverIpAddress(); - } - - public static void startTime() { - MDC.put(LoggingField.START_TIME.toString(), LogFormatTools.getCurrentDateTime()); - } - - public static UUID requestId() { - final String sUuid = MDC.get(LoggingField.REQUEST_ID.toString()); - - if (sUuid == null) - return null; - - return UUID.fromString(sUuid); - } - - public static void requestId(UUID requestId) { - MDC.put(LoggingField.REQUEST_ID.toString(), requestId.toString()); - } - - public static void requestId(String requestId) { - try { - if (requestId.contains(":")) { - String[] uuidParts = requestId.split(":"); - requestId = uuidParts[0]; - } - MDC.put(LoggingField.REQUEST_ID.toString(), UUID.fromString(requestId).toString()); - } catch (IllegalArgumentException e) { - final UUID generatedRequestUuid = UUID.randomUUID(); - MDC.put(LoggingField.REQUEST_ID.toString(), generatedRequestUuid.toString()); - LoggingContext.save(); - // set response code to 0 since we don't know what the outcome of this request is yet - String responseCode = LoggingContext.DATA_ERROR; - LoggingContext.responseCode(responseCode); - LoggingContext.responseDescription("Unable to use UUID " + requestId + " (Not formatted properly) "); - LoggingContext.statusCode(StatusCode.ERROR); - - LOGGER.warn("Using generated UUID=" + generatedRequestUuid); - LoggingContext.restore(); - - } - } - - public static void serviceInstanceId(String serviceInstanceId) { - MDC.put(LoggingField.SERVICE_INSTANCE_ID.toString(), serviceInstanceId); - } - - public static void serverName(String serverName) { - MDC.put(LoggingField.SERVER_NAME.toString(), serverName); - } - - public static void serviceName(String serviceName) { - MDC.put(LoggingField.SERVICE_NAME.toString(), serviceName); - } - - public static void partnerName(String partnerName) { - MDC.put(LoggingField.PARTNER_NAME.toString(), partnerName); - } - - public static void statusCode(StatusCode statusCode) { - MDC.put(LoggingField.STATUS_CODE.toString(), statusCode.toString()); - } - - public static String responseCode() { - return MDC.get(LoggingField.RESPONSE_CODE.toString()); - } - - public static void responseCode(String responseCode) { - MDC.put(LoggingField.RESPONSE_CODE.toString(), responseCode); - } - - public static void responseDescription(String responseDescription) { - MDC.put(LoggingField.RESPONSE_DESCRIPTION.toString(), responseDescription); - } - - public static Object instanceUuid() { - return UUID.fromString(MDC.get(LoggingField.INSTANCE_UUID.toString())); - } - - public static void instanceUuid(UUID instanceUuid) { - MDC.put(LoggingField.INSTANCE_UUID.toString(), instanceUuid.toString()); - } - - public static void severity(int severity) { - MDC.put(LoggingField.SEVERITY.toString(), String.valueOf(severity)); - } - - public static void successStatusFields() { - responseCode(SUCCESS); - statusCode(StatusCode.COMPLETE); - responseDescription("Success"); - } - - private static void serverIpAddress() { - try { - MDC.put(LoggingField.SERVER_IP_ADDRESS.toString(), InetAddress.getLocalHost().getHostAddress()); - } catch (UnknownHostException e) { - LOGGER.warn("Unable to resolve server IP address - will not be displayed in logged events"); - } - } - - public static void elapsedTime(long elapsedTime, TimeUnit timeUnit) { - MDC.put(LoggingField.ELAPSED_TIME.toString(), - String.valueOf(TimeUnit.MILLISECONDS.convert(elapsedTime, timeUnit))); - } - - private static void server() { - try { - MDC.put(LoggingField.SERVER.toString(), InetAddress.getLocalHost().getCanonicalHostName()); - } catch (UnknownHostException e) { - LOGGER.warn("Unable to resolve server IP address - hostname will not be displayed in logged events"); - } - } - - public static void clientIpAddress(InetAddress clientIpAddress) { - MDC.put(LoggingField.CLIENT_IP_ADDRESS.toString(), clientIpAddress.getHostAddress()); - } - - public static void clientIpAddress(String clientIpAddress) { - try { - MDC.put(LoggingField.CLIENT_IP_ADDRESS.toString(), InetAddress.getByName(clientIpAddress).getHostAddress()); - } catch (UnknownHostException e) { - // Ignore, will not be thrown since InetAddress.getByName(String) only - // checks the validity of the passed in string - } - } - - public static void unused(String unused) { - LOGGER.warn("Using field '" + LoggingField.UNUSED + "' (seems like this should go unused...)"); - MDC.put(LoggingField.UNUSED.toString(), unused); - } - - public static void processKey(String processKey) { - MDC.put(LoggingField.PROCESS_KEY.toString(), processKey); - } - - public static String customField1() { - return MDC.get(LoggingField.CUSTOM_FIELD_1.toString()); - } - - public static void customField1(String customField1) { - MDC.put(LoggingField.CUSTOM_FIELD_1.toString(), customField1); - } - - public static void customField2(String customField2) { - MDC.put(LoggingField.CUSTOM_FIELD_2.toString(), customField2); - } - - public static void customField3(String customField3) { - MDC.put(LoggingField.CUSTOM_FIELD_3.toString(), customField3); - } - - public static void customField4(String customField4) { - MDC.put(LoggingField.CUSTOM_FIELD_4.toString(), customField4); - } - - public static void component(String component) { - MDC.put(LoggingField.COMPONENT.toString(), component); - } - - public static void targetEntity(String targetEntity) { - MDC.put(LoggingField.TARGET_ENTITY.toString(), targetEntity); - } - - public static void targetServiceName(String targetServiceName) { - MDC.put(LoggingField.TARGET_SERVICE_NAME.toString(), targetServiceName); - } - - public static boolean isStopWatchStarted() { - final String rawStopWatchStart = MDC.get(LoggingField.STOP_WATCH_START.toString()); - return rawStopWatchStart != null; - } - - public static void stopWatchStart() { - MDC.put(LoggingField.STOP_WATCH_START.toString(), String.valueOf(System.nanoTime())); - } - - public static double stopWatchStop() { - final long stopWatchEnd = System.nanoTime(); - final String rawStopWatchStart = MDC.get(LoggingField.STOP_WATCH_START.toString()); - - if (rawStopWatchStart == null) - throw new StopWatchNotStartedException(); - - final Long stopWatchStart = Long.valueOf(rawStopWatchStart); - - MDC.remove(LoggingField.STOP_WATCH_START.toString()); - - final double elapsedTimeMillis = (stopWatchEnd - stopWatchStart) / 1000.0 / 1000.0; - - LoggingContext.elapsedTime((long) elapsedTimeMillis, TimeUnit.MILLISECONDS); - - return elapsedTimeMillis; - } - - public static void put(String key, String value) { - MDC.put(key, value); - } - - public static void clear() { - MDC.clear(); - } - - public static void remove(String key) { - MDC.remove(key); - } - - public static void save() { - final JSONObject context = new JSONObject(); - - for (LoggingField field : LoggingField.values()) { - if (field == LoggingField.ELAPSED_TIME) - continue; - - try { - context.put(field.toString(), MDC.get(field.toString())); - } catch (JSONException e) { - // Ignore - only occurs when the key is null (which can't happen) - // or the value is invalid (everything is converted to a string - // before it get put() to the MDC) - } - } - - final String rawJsonArray = MDC.get(PREVIOUS_CONTEXTS_KEY); - - if (rawJsonArray == null) { - final JSONArray stack = new JSONArray().put(context); - - MDC.put(PREVIOUS_CONTEXTS_KEY, stack.toString()); - } else { - try { - final JSONArray stack = new JSONArray(rawJsonArray).put(context); - - MDC.put(PREVIOUS_CONTEXTS_KEY, stack.toString()); - } catch (JSONException e) { - // Ignore - } - } - } - - public static void restore() { - - final String rawPreviousContexts = MDC.get(PREVIOUS_CONTEXTS_KEY); - - if (rawPreviousContexts == null) { - throw new LoggingContextNotExistsException(); - } - - try { - final JSONArray previousContexts = new JSONArray(rawPreviousContexts); - final JSONObject previousContext = previousContexts.getJSONObject(previousContexts.length() - 1); - - @SuppressWarnings("unchecked") - final Iterator<String> keys = previousContext.keys(); - boolean foundElapsedTime = false; - while (keys.hasNext()) { - final String key = keys.next(); - if (LoggingField.ELAPSED_TIME.toString().equals(key)) { - foundElapsedTime = true; - } - try { - MDC.put(key, previousContext.getString(key)); - } catch (JSONException e) { - // Ignore, only occurs when the key is null (cannot happen) - // or the value is invalid (they are all strings) - } - } - if (!foundElapsedTime) { - MDC.remove(LoggingField.ELAPSED_TIME.toString()); - } - MDC.put(PREVIOUS_CONTEXTS_KEY, removeLast(previousContexts).toString()); - } catch (JSONException e) { - // Ignore, the previousContext is serialized from a JSONObject - } - } - - public static void restoreIfPossible() { - try { - restore(); - } catch (LoggingContextNotExistsException e) { - // Ignore - } - } - - /** - * AJSC declares an ancient version of org.json:json in one of the parent POMs of this project. - * I tried to update our version of that library in our POM, but it's ignored because of the way - * AJSC has organized their <dependencies>. Had they put it into the <dependencyManagement> section, - * this method would not be necessary. - */ - private static JSONArray removeLast(JSONArray previousContexts) { - final JSONArray result = new JSONArray(); - - for (int i = 0; i < previousContexts.length() - 1; i++) { - try { - result.put(previousContexts.getJSONObject(i)); - } catch (JSONException e) { - // Ignore - not possible - } - } - - return result; - } - - public static Map<String, String> getCopy() { - final Map<String, String> copy = new HashMap<>(); - - for (LoggingField field : LoggingField.values()) { - final String value = MDC.get(field.toString()); - - if (value != null) - copy.put(field.toString(), value); - } - - return copy; - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/StopWatch.java b/aai-core/src/main/java/org/onap/aai/logging/StopWatch.java deleted file mode 100644 index 0d93827f..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/StopWatch.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import org.onap.aai.logging.LoggingContext.LoggingField; - -public final class StopWatch { - - private StopWatch() { - } - - public static void start() { - LoggingContext.stopWatchStart(); - } - - public static double stop() { - return LoggingContext.stopWatchStop(); - } - - public static void conditionalStart() { - if (LoggingContext.isStopWatchStarted()) { - return; - } - start(); - } - - public static double stopIfStarted() { - if (LoggingContext.isStopWatchStarted()) { - return (stop()); - } - return (0); - } - - public static void clear() { - LoggingContext.remove(LoggingField.STOP_WATCH_START.toString()); - LoggingContext.remove(LoggingField.ELAPSED_TIME.toString()); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/logging/StopWatchNotStartedException.java b/aai-core/src/main/java/org/onap/aai/logging/StopWatchNotStartedException.java deleted file mode 100644 index e4819c5c..00000000 --- a/aai-core/src/main/java/org/onap/aai/logging/StopWatchNotStartedException.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -public class StopWatchNotStartedException extends RuntimeException { - - private static final long serialVersionUID = -4540164295822859408L; - - public StopWatchNotStartedException() { - super(); - } - - public StopWatchNotStartedException(String message) { - super(message); - } - - public StopWatchNotStartedException(Throwable cause) { - super(cause); - } - - public StopWatchNotStartedException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/parsers/query/LegacyQueryParser.java b/aai-core/src/main/java/org/onap/aai/parsers/query/LegacyQueryParser.java index c9412733..ca735357 100644 --- a/aai-core/src/main/java/org/onap/aai/parsers/query/LegacyQueryParser.java +++ b/aai-core/src/main/java/org/onap/aai/parsers/query/LegacyQueryParser.java @@ -20,8 +20,8 @@ package org.onap.aai.parsers.query; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; import java.net.URI; @@ -49,7 +49,7 @@ import org.onap.aai.schema.enums.PropertyMetadata; */ public class LegacyQueryParser extends QueryParser implements Parsable { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(LegacyQueryParser.class); + private static final Logger LOGGER = LoggerFactory.getLogger(LegacyQueryParser.class); private Introspector previous = null; diff --git a/aai-core/src/main/java/org/onap/aai/parsers/query/RelationshipQueryParser.java b/aai-core/src/main/java/org/onap/aai/parsers/query/RelationshipQueryParser.java index 0958a81e..e1319802 100644 --- a/aai-core/src/main/java/org/onap/aai/parsers/query/RelationshipQueryParser.java +++ b/aai-core/src/main/java/org/onap/aai/parsers/query/RelationshipQueryParser.java @@ -20,8 +20,8 @@ package org.onap.aai.parsers.query; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; @@ -41,7 +41,7 @@ import org.springframework.context.ApplicationContext; */ public class RelationshipQueryParser extends LegacyQueryParser { - private static final EELFLogger logger = EELFManager.getInstance().getLogger(RelationshipQueryParser.class); + private static final Logger logger = LoggerFactory.getLogger(RelationshipQueryParser.class); private Introspector relationship = null; diff --git a/aai-core/src/main/java/org/onap/aai/parsers/relationship/RelationshipToURI.java b/aai-core/src/main/java/org/onap/aai/parsers/relationship/RelationshipToURI.java index 0b072b88..0ee22f50 100644 --- a/aai-core/src/main/java/org/onap/aai/parsers/relationship/RelationshipToURI.java +++ b/aai-core/src/main/java/org/onap/aai/parsers/relationship/RelationshipToURI.java @@ -20,8 +20,8 @@ package org.onap.aai.parsers.relationship; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; import java.net.URI; @@ -57,7 +57,7 @@ import org.springframework.context.ApplicationContext; */ public class RelationshipToURI { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(RelationshipToURI.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RelationshipToURI.class); private Introspector relationship = null; diff --git a/aai-core/src/main/java/org/onap/aai/prevalidation/Validation.java b/aai-core/src/main/java/org/onap/aai/prevalidation/Validation.java new file mode 100644 index 00000000..d420c558 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/prevalidation/Validation.java @@ -0,0 +1,92 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright © 2018 IBM. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.prevalidation; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; +import java.util.Objects; + +public class Validation { + + @SerializedName("validationId") + private String validationId; + + @SerializedName("action") + private String action; + + @SerializedName("violations") + private List<Violation> violations; + + public String getValidationId() { + return validationId; + } + + public void setValidationId(String validationId) { + this.validationId = validationId; + } + + public List<Violation> getViolations() { + return violations; + } + + public void setViolations(List<Violation> violations) { + this.violations = violations; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Validation that = (Validation) o; + return Objects.equals(validationId, that.validationId) && + Objects.equals(action, that.action) && + Objects.equals(violations, that.violations); + } + + @Override + public int hashCode() { + return Objects.hash(validationId, action, violations); + } + + @Override + public String toString() { + return "Validation{" + + "validationId='" + validationId + '\'' + + ", action='" + action + '\'' + + ", violations=" + violations + + '}'; + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationConfiguration.java b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationConfiguration.java new file mode 100644 index 00000000..36569dd0 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationConfiguration.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright © 2018 IBM. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.prevalidation; + +import org.onap.aai.restclient.RestClient; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Profile("pre-validation") +@Configuration +public class ValidationConfiguration { + + @Bean(name = "validationRestClient") + @ConditionalOnProperty(name = "validation.service.client", havingValue = "two-way-ssl", matchIfMissing = true) + public RestClient validationRestClientTwoWaySSL() { + return new ValidationServiceRestClient(); + } + + @Bean(name = "validationRestClient") + @ConditionalOnProperty(name = "validation.service.client", havingValue = "no-auth") + public RestClient validationRestClientNoAuth() { + return new ValidationServiceNoAuthClient(); + } + + @Bean(name = "validationRestClient") + @ConditionalOnProperty(name = "validation.service.client", havingValue = "one-way-ssl") + public RestClient validationRestClientOneWaySSL() { + return new ValidationServiceOneWayClient(); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationService.java b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationService.java new file mode 100644 index 00000000..78083ecb --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationService.java @@ -0,0 +1,299 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright © 2018 IBM. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.prevalidation; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import org.apache.http.conn.ConnectTimeoutException; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.rest.ueb.NotificationEvent; +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.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.util.*; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * <b>ValidationService</b> routes all the writes to the database + * excluding deletes for now to the validation service to verify + * that the request is an valid one before committing to the database + */ +@Service +@Profile("pre-validation") +public class ValidationService { + + /** + * Error indicating that the service trying to connect is down + */ + static final String CONNECTION_REFUSED_STRING = + "Connection refused to the validation microservice due to service unreachable"; + + /** + * Error indicating that the server is unable to reach the port + * Could be server related connectivity issue + */ + static final String CONNECTION_TIMEOUT_STRING = + "Connection timeout to the validation microservice as this could " + + "indicate the server is unable to reach port, " + + "please check on server by running: nc -w10 -z -v ${VALIDATION_HOST} ${VALIDATION_PORT}"; + + /** + * Error indicating that the request exceeded the allowed time + * + * Note: This means that the service could be active its + * just taking some time to process our request + */ + static final String REQUEST_TIMEOUT_STRING = + "Request to validation service took longer than the currently set timeout"; + + static final String VALIDATION_ENDPOINT = "/v1/app/validate"; + static final String VALIDATION_HEALTH_ENDPOINT = "/v1/core/core-service/info"; + + private static final String ENTITY_TYPE = "entity-type"; + private static final String ACTION = "action"; + private static final String SOURCE_NAME = "source-name"; + + private static final String DELETE = "DELETE"; + + private static final Logger LOGGER = LoggerFactory.getLogger(ValidationService.class); + + private final RestClient validationRestClient; + + private final String appName; + + private final Set<String> validationNodeTypes; + + private List<Pattern> exclusionList; + + private final Gson gson; + + @Autowired + public ValidationService( + @Qualifier("validationRestClient") RestClient validationRestClient, + @Value("${spring.application.name}") String appName, + @Value("${validation.service.node-types}") String validationNodes, + @Value("${validation.service.exclusion-regexes}") String exclusionRegexes + ){ + this.validationRestClient = validationRestClient; + this.appName = appName; + + this.validationNodeTypes = Arrays + .stream(validationNodes.split(",")) + .collect(Collectors.toSet()); + + if(exclusionRegexes == null || exclusionRegexes.isEmpty()){ + this.exclusionList = new ArrayList<>(); + } else { + this.exclusionList = Arrays + .stream(exclusionRegexes.split(",")) + .map(Pattern::compile) + .collect(Collectors.toList()); + } + this.gson = new Gson(); + LOGGER.info("Successfully initialized the pre validation service"); + } + + @PostConstruct + public void initialize() throws AAIException { + + Map<String, String> httpHeaders = new HashMap<>(); + + httpHeaders.put("X-FromAppId", appName); + httpHeaders.put("X-TransactionID", UUID.randomUUID().toString()); + httpHeaders.put("Content-Type", "application/json"); + + ResponseEntity<String> healthCheckResponse = null; + + try { + + healthCheckResponse = validationRestClient.execute( + VALIDATION_HEALTH_ENDPOINT, + HttpMethod.GET, + httpHeaders, + null + ); + + } catch(Exception ex){ + AAIException validationException = new AAIException("AAI_4021", ex); + throw validationException; + } + + if(!isSuccess(healthCheckResponse)){ + throw new AAIException("AAI_4021"); + } + + LOGGER.info("Successfully connected to the validation service endpoint"); + } + + public boolean shouldValidate(String nodeType){ + return this.validationNodeTypes.contains(nodeType); + } + + public void validate(List<NotificationEvent> notificationEvents) throws AAIException { + + if(notificationEvents == null || notificationEvents.isEmpty()){ + return; + } + + { + // Get the first notification and if the source of that notification + // is in one of the regexes then we skip sending it to validation + NotificationEvent notification = notificationEvents.get(0); + Introspector eventHeader = notification.getEventHeader(); + if(eventHeader != null){ + String source = eventHeader.getValue(SOURCE_NAME); + for(Pattern pattern: exclusionList){ + if(pattern.matcher(source).matches()){ + return; + } + } + } + + } + + for (NotificationEvent event : notificationEvents) { + + Introspector eventHeader = event.getEventHeader(); + + if(eventHeader == null){ + // Should I skip processing the request and let it continue + // or fail the request and cause client impact + continue; + } + + String entityType = eventHeader.getValue(ENTITY_TYPE); + String action = eventHeader.getValue(ACTION); + + /** + * Skipping the delete events for now + * Note: Might revisit this later when validation supports DELETE events + */ + if(DELETE.equalsIgnoreCase(action)){ + continue; + } + + if (this.shouldValidate(entityType)) { + List<String> violations = this.preValidate(event.getNotificationEvent()); + if(!violations.isEmpty()){ + AAIException aaiException = new AAIException("AAI_4019"); + aaiException.getTemplateVars().addAll(violations); + throw aaiException; + } + } + } + } + + List<String> preValidate(String body) throws AAIException { + + Map<String, String> httpHeaders = new HashMap<>(); + + httpHeaders.put("X-FromAppId", appName); + httpHeaders.put("X-TransactionID", UUID.randomUUID().toString()); + httpHeaders.put("Content-Type", "application/json"); + + List<String> violations = new ArrayList<>(); + ResponseEntity responseEntity; + try { + + responseEntity = validationRestClient.execute( + VALIDATION_ENDPOINT, + HttpMethod.POST, + httpHeaders, + body + ); + + if(isSuccess(responseEntity)){ + LOGGER.debug("Validation Service returned following response status code {} and body {}", responseEntity.getStatusCodeValue(), responseEntity.getBody()); + } else { + Validation validation = null; + try { + validation = gson.fromJson(responseEntity.getBody().toString(), Validation.class); + } catch(JsonSyntaxException jsonException){ + LOGGER.warn("Unable to convert the response body {}", jsonException.getMessage()); + } + + if(validation == null){ + LOGGER.debug( + "Validation Service following status code {} with body {}", + responseEntity.getStatusCodeValue(), + responseEntity.getBody() + ); + } else { + violations.addAll(extractViolations(validation)); + } + } + } catch(Exception e){ + // If the exception cause is client side timeout + // then proceed as if it passed validation + // resources microservice shouldn't be blocked because of validation service + // is taking too long or if the validation service is down + // Any other exception it should block the request from passing? + if(e.getCause() instanceof SocketTimeoutException){ + LOGGER.error(REQUEST_TIMEOUT_STRING, e.getCause()); + } else if(e.getCause() instanceof ConnectException){ + LOGGER.error(CONNECTION_REFUSED_STRING, e.getCause()); + } else if(e.getCause() instanceof ConnectTimeoutException){ + LOGGER.error(CONNECTION_TIMEOUT_STRING, e.getCause()); + } else { + LOGGER.error("Unknown exception thrown please investigate", e.getCause()); + } + } + return violations; + } + + boolean isSuccess(ResponseEntity responseEntity){ + return responseEntity != null && responseEntity.getStatusCode().is2xxSuccessful(); + } + + List<String> extractViolations(Validation validation) { + + List<String> errorMessages = new ArrayList<>(); + + if(validation == null){ + return errorMessages; + } + + List<Violation> violations = validation.getViolations(); + + if (violations != null && !violations.isEmpty()) { + for (Violation violation : validation.getViolations()) { + LOGGER.info(violation.getErrorMessage()); + errorMessages.add(violation.getErrorMessage()); + } + } + + return errorMessages; + } +} diff --git a/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationServiceNoAuthClient.java b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationServiceNoAuthClient.java new file mode 100644 index 00000000..d373ae78 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationServiceNoAuthClient.java @@ -0,0 +1,79 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2018-19 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.prevalidation; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.onap.aai.restclient.NoAuthRestClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.util.MultiValueMap; + +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +public class ValidationServiceNoAuthClient extends NoAuthRestClient { + + private static Logger logger = LoggerFactory.getLogger(ValidationServiceNoAuthClient.class); + + @Value("${validation.service.base.url}") + private String baseUrl; + + @Value("${validation.service.timeout-in-milliseconds}") + private Integer timeout; + + @Override + protected HttpComponentsClientHttpRequestFactory getHttpRequestFactory() throws Exception { + HttpComponentsClientHttpRequestFactory requestFactory = super.getHttpRequestFactory(); + requestFactory.setConnectionRequestTimeout(timeout); + requestFactory.setReadTimeout(timeout); + requestFactory.setConnectTimeout(timeout); + return requestFactory; + } + + @Override + public String getBaseUrl() { + return baseUrl; + } + + @Override + public MultiValueMap<String, String> getHeaders(Map<String, String> headers) { + HttpHeaders httpHeaders = new HttpHeaders(); + + String defaultAccept = headers.getOrDefault(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString()); + String defaultContentType = + headers.getOrDefault(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON.toString()); + + if (headers.isEmpty()) { + httpHeaders.setAccept(Collections.singletonList(MediaType.parseMediaType(defaultAccept))); + httpHeaders.setContentType(MediaType.parseMediaType(defaultContentType)); + } + + httpHeaders.add("X-FromAppId", appName); + httpHeaders.add("X-TransactionId", UUID.randomUUID().toString()); + headers.forEach(httpHeaders::add); + return httpHeaders; + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationServiceOneWayClient.java b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationServiceOneWayClient.java new file mode 100644 index 00000000..40efd469 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationServiceOneWayClient.java @@ -0,0 +1,92 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2018-19 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.prevalidation; + +import org.onap.aai.restclient.OneWaySSLRestClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.util.MultiValueMap; + +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +public class ValidationServiceOneWayClient extends OneWaySSLRestClient { + + @Value("${validation.service.base.url}") + private String baseUrl; + + @Value("${validation.service.ssl.trust-store}") + private String truststorePath; + + @Value("${validation.service.ssl.trust-store-password}") + private String truststorePassword; + + @Value("${validation.service.timeout-in-milliseconds}") + private Integer timeout; + + @Override + public String getBaseUrl() { + return baseUrl; + } + + @Override + protected String getTruststorePath() { + return truststorePath; + } + + @Override + protected char[] getTruststorePassword() { + return truststorePassword.toCharArray(); + } + + @Override + protected HttpComponentsClientHttpRequestFactory getHttpRequestFactory() throws Exception { + HttpComponentsClientHttpRequestFactory requestFactory = super.getHttpRequestFactory(); + requestFactory.setConnectionRequestTimeout(timeout); + requestFactory.setReadTimeout(timeout); + requestFactory.setConnectTimeout(timeout); + return requestFactory; + } + + @Override + public MultiValueMap<String, String> getHeaders(Map<String, String> headers) { + HttpHeaders httpHeaders = new HttpHeaders(); + + String defaultAccept = headers.getOrDefault(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString()); + String defaultContentType = + headers.getOrDefault(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON.toString()); + + if (headers.isEmpty()) { + httpHeaders.setAccept(Collections.singletonList(MediaType.parseMediaType(defaultAccept))); + httpHeaders.setContentType(MediaType.parseMediaType(defaultContentType)); + } + + httpHeaders.add("X-FromAppId", appName); + httpHeaders.add("X-TransactionId", UUID.randomUUID().toString()); + httpHeaders.add("X-TransactionId", appName); + headers.forEach(httpHeaders::add); + return httpHeaders; + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationServiceRestClient.java b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationServiceRestClient.java new file mode 100644 index 00000000..8674272e --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationServiceRestClient.java @@ -0,0 +1,108 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright © 2018 IBM. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.prevalidation; + +import org.onap.aai.restclient.TwoWaySSLRestClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.util.MultiValueMap; + +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +public class ValidationServiceRestClient extends TwoWaySSLRestClient { + + @Value("${validation.service.base.url}") + private String baseUrl; + + @Value("${validation.service.ssl.key-store}") + private String keystorePath; + + @Value("${validation.service.ssl.trust-store}") + private String truststorePath; + + @Value("${validation.service.ssl.key-store-password}") + private String keystorePassword; + + @Value("${validation.service.ssl.trust-store-password}") + private String truststorePassword; + + @Value("${validation.service.timeout-in-milliseconds}") + private Integer timeout; + + @Override + public String getBaseUrl() { + return baseUrl; + } + + @Override + protected String getKeystorePath() { + return keystorePath; + } + + @Override + protected String getTruststorePath() { + return truststorePath; + } + + @Override + protected char[] getKeystorePassword() { + return keystorePassword.toCharArray(); + } + + @Override + protected char[] getTruststorePassword() { + return truststorePassword.toCharArray(); + } + + protected HttpComponentsClientHttpRequestFactory getHttpRequestFactory() throws Exception { + HttpComponentsClientHttpRequestFactory requestFactory = super.getHttpRequestFactory(); + requestFactory.setConnectionRequestTimeout(timeout); + requestFactory.setReadTimeout(timeout); + requestFactory.setConnectTimeout(timeout); + return requestFactory; + } + + @Override + public MultiValueMap<String, String> getHeaders(Map<String, String> headers) { + HttpHeaders httpHeaders = new HttpHeaders(); + + String defaultAccept = headers.getOrDefault(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString()); + String defaultContentType = + headers.getOrDefault(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON.toString()); + + if (headers.isEmpty()) { + httpHeaders.setAccept(Collections.singletonList(MediaType.parseMediaType(defaultAccept))); + httpHeaders.setContentType(MediaType.parseMediaType(defaultContentType)); + } + + httpHeaders.add("X-FromAppId", appName); + httpHeaders.add("X-TransactionId", UUID.randomUUID().toString()); + headers.forEach(httpHeaders::add); + return httpHeaders; + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/prevalidation/Violation.java b/aai-core/src/main/java/org/onap/aai/prevalidation/Violation.java new file mode 100644 index 00000000..e5472a7c --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/prevalidation/Violation.java @@ -0,0 +1,128 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2018-19 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.prevalidation; + +import com.google.gson.annotations.SerializedName; + +import java.util.Objects; + +public class Violation { + + @SerializedName("violationId") + private String violationId; + + @SerializedName("modelName") + private String modelName; + + @SerializedName("category") + private String category; + + @SerializedName("severity") + private String severity; + + @SerializedName("violationType") + private String violationType; + + @SerializedName("errorMessage") + private String errorMessage; + + public String getViolationId() { + return violationId; + } + + public void setViolationId(String violationId) { + this.violationId = violationId; + } + + public String getModelName() { + return modelName; + } + + public void setModelName(String modelName) { + this.modelName = modelName; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public String getViolationType() { + return violationType; + } + + public void setViolationType(String violationType) { + this.violationType = violationType; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + @Override + public String toString() { + return "Violation{" + + "violationId='" + violationId + '\'' + + ", modelName='" + modelName + '\'' + + ", category='" + category + '\'' + + ", severity='" + severity + '\'' + + ", violationType='" + violationType + '\'' + + ", errorMessage='" + errorMessage + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Violation violation = (Violation) o; + return Objects.equals(violationId, violation.violationId) && + Objects.equals(modelName, violation.modelName) && + Objects.equals(category, violation.category) && + Objects.equals(severity, violation.severity) && + Objects.equals(violationType, violation.violationType) && + Objects.equals(errorMessage, violation.errorMessage); + } + + @Override + public int hashCode() { + return Objects.hash(violationId, modelName, category, severity, violationType, errorMessage); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java b/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java index 272a2c21..1dc3f1d6 100644 --- a/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java +++ b/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java @@ -64,7 +64,6 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { */ public GraphTraversalBuilder(Loader loader, GraphTraversalSource source) { super(loader, source); - traversal = (GraphTraversal<Vertex, E>) __.<E>start(); } @@ -73,7 +72,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { * Instantiates a new graph traversal builder. * * @param loader the loader - * @param start the start + * @param start the start */ public GraphTraversalBuilder(Loader loader, GraphTraversalSource source, Vertex start) { super(loader, source, start); @@ -89,12 +88,33 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { public QueryBuilder<Vertex> getVerticesByProperty(String key, Object value) { // correct value call because the index is registered as an Integer - traversal.has(key, this.correctObjectType(value)); - + this.vertexHas(key, this.correctObjectType(value)); stepIndex++; return (QueryBuilder<Vertex>) this; } + @Override + protected void vertexHas(String key, Object value) { + traversal.has(key, value); + } + + @Override + protected void vertexHasNot(String key) { + traversal.hasNot(key); + } + + @Override + protected void vertexHas(String key) { + traversal.has(key); + } + + //TODO: Remove this once we test this - at this point i dont thib this is required + //because predicare is an object + /*@Override + protected void vertexHas(final String key, final P<?> predicate) { + traversal.has(key, predicate); + }*/ + /** * @{inheritDoc} */ @@ -107,7 +127,21 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { correctedValues.add(this.correctObjectType(item)); } - traversal.has(key, P.within(correctedValues)); + this.vertexHas(key, P.within(correctedValues)); + stepIndex++; + return (QueryBuilder<Vertex>) this; + } + + /** + * @{inheritDoc} + */ + public QueryBuilder<Vertex> getVerticesByCommaSeperatedValue(String key, String value) { + ArrayList<String> values = new ArrayList<>(Arrays.asList(value.split(","))); + int size = values.size(); + for (int i = 0; i < size; i++) { + values.set(i, values.get(i).trim()); + } + this.vertexHas(key, P.within(values)); stepIndex++; return (QueryBuilder<Vertex>) this; @@ -120,7 +154,8 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { public QueryBuilder<Vertex> getVerticesStartsWithProperty(String key, Object value) { // correct value call because the index is registered as an Integer - traversal.has(key, org.janusgraph.core.attribute.Text.textPrefix(value)); + //TODO Check if this needs to be in QB and add these as internal + this.vertexHas(key, org.janusgraph.core.attribute.Text.textPrefix(value)); stepIndex++; return (QueryBuilder<Vertex>) this; @@ -131,8 +166,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { */ @Override public QueryBuilder<Vertex> getVerticesByProperty(String key) { - - traversal.has(key); + this.vertexHas(key); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -142,8 +176,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { */ @Override public QueryBuilder<Vertex> getVerticesExcludeByProperty(String key) { - - traversal.hasNot(key); + this.vertexHasNot(key); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -155,8 +188,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { public QueryBuilder<Vertex> getVerticesExcludeByProperty(String key, Object value) { // correct value call because the index is registered as an Integer - traversal.has(key, P.neq(this.correctObjectType(value))); - + this.vertexHas(key, P.neq(this.correctObjectType(value))); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -173,16 +205,14 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { correctedValues.add(this.correctObjectType(item)); } - traversal.has(key, P.without(correctedValues)); - + this.vertexHas(key, P.without(correctedValues)); stepIndex++; return (QueryBuilder<Vertex>) this; } @Override public QueryBuilder<Vertex> getVerticesGreaterThanProperty(final String key, Object value) { - - traversal.has(key, P.gte(this.correctObjectType(value))); + this.vertexHas(key, P.gte(this.correctObjectType(value))); stepIndex++; return (QueryBuilder<Vertex>) this; @@ -190,8 +220,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { @Override public QueryBuilder<Vertex> getVerticesLessThanProperty(final String key, Object value) { - - traversal.has(key, P.lte(this.correctObjectType(value))); + this.vertexHas(key, P.lte(this.correctObjectType(value))); stepIndex++; return (QueryBuilder<Vertex>) this; @@ -214,7 +243,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { public QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map) { for (Map.Entry<String, String> es : map.entrySet()) { - traversal.has(es.getKey(), es.getValue()); + this.vertexHas(es.getKey(), es.getValue()); stepIndex++; } traversal.has(AAIProperties.NODE_TYPE, type); @@ -234,7 +263,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { bValue = (Boolean) value; } - traversal.has(key, bValue); + this.vertexHas(key, bValue); stepIndex++; } return (QueryBuilder<Vertex>) this; @@ -257,9 +286,9 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { if (val != null) { // this is because the index is registered as an Integer if (val.getClass().equals(Long.class)) { - traversal.has(key, new Integer(val.toString())); + this.vertexHas(key, new Integer(val.toString())); } else { - traversal.has(key, val); + this.vertexHas(key, val); } stepIndex++; } @@ -290,9 +319,9 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { } // this is because the index is registered as an Integer if (val.getClass().equals(Long.class)) { - traversal.has(prop, new Integer(val.toString())); + this.vertexHas(prop, new Integer(val.toString())); } else { - traversal.has(prop, val); + this.vertexHas(prop, val); } stepIndex++; } @@ -326,7 +355,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { */ @Override public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) - throws AAIException { + throws AAIException { createTraversal(type, parent, child, false); return (QueryBuilder<Vertex>) this; @@ -334,13 +363,13 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { @Override public QueryBuilder<Vertex> createPrivateEdgeTraversal(EdgeType type, Introspector parent, Introspector child) - throws AAIException { + throws AAIException { this.createTraversal(type, parent, child, true); return (QueryBuilder<Vertex>) this; } private void createTraversal(EdgeType type, Introspector parent, Introspector child, boolean isPrivateEdge) - throws AAIException { + throws AAIException { String isAbstractType = parent.getMetadata(ObjectMetadata.ABSTRACT); if ("true".equals(isAbstractType)) { markParentBoundary(); @@ -352,18 +381,17 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { } /** - * * @{inheritDoc} */ @Override public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, - List<String> labels) throws AAIException { + List<String> labels) throws AAIException { this.edgeQueryToVertex(type, out, in, labels); return (QueryBuilder<Vertex>) this; } private Traversal<Vertex, Vertex>[] handleAbstractEdge(EdgeType type, Introspector abstractParent, - Introspector child, boolean isPrivateEdge) throws AAIException { + Introspector child, boolean isPrivateEdge) throws AAIException { String childName = child.getDbName(); String inheritorMetadata = abstractParent.getMetadata(ObjectMetadata.INHERITORS); String[] inheritors = inheritorMetadata.split(","); @@ -399,7 +427,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { innerTraversal.in(inLabels.toArray(new String[inLabels.size()])); } else { innerTraversal.union(__.out(outLabels.toArray(new String[outLabels.size()])), - __.in(inLabels.toArray(new String[inLabels.size()]))); + __.in(inLabels.toArray(new String[inLabels.size()]))); } innerTraversal.has(AAIProperties.NODE_TYPE, childName); @@ -411,7 +439,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { } public QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, - List<String> labels) throws AAIException { + List<String> labels) throws AAIException { Introspector outObj = loader.introspectorFromName(outNodeType); Introspector inObj = loader.introspectorFromName(inNodeType); this.edgeQuery(type, outObj, inObj, labels); @@ -556,6 +584,23 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { return this; } + @Override + public QueryBuilder<E> valueMap() { + this.traversal.valueMap(); + stepIndex++; + + return this; + } + + @Override + public QueryBuilder<E> valueMap(String... names) { + this.traversal.valueMap(names); + stepIndex++; + + return this; + } + + /** * {@inheritDoc} */ @@ -649,12 +694,12 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { * Edge query. * * @param outObj the out type - * @param inObj the in type + * @param inObj the in type * @throws NoEdgeRuleFoundException * @throws AAIException */ private void edgeQueryToVertex(EdgeType type, Introspector outObj, Introspector inObj, List<String> labels) - throws AAIException { + throws AAIException { String outType = outObj.getDbName(); String inType = inObj.getDbName(); @@ -686,7 +731,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { } if (rules.isEmpty()) { throw new NoEdgeRuleFoundException( - "No edge rules found for " + outType + " and " + inType + " of type " + type.toString()); + "No edge rules found for " + outType + " and " + inType + " of type " + type.toString()); } } @@ -711,7 +756,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { traversal.in(inLabels.toArray(new String[inLabels.size()])); } else { traversal.union(__.out(outLabels.toArray(new String[outLabels.size()])), - __.in(inLabels.toArray(new String[inLabels.size()]))); + __.in(inLabels.toArray(new String[inLabels.size()]))); } stepIndex++; @@ -724,12 +769,12 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { * Edge query. * * @param outObj the out type - * @param inObj the in type + * @param inObj the in type * @throws NoEdgeRuleFoundException * @throws AAIException */ private void edgeQuery(EdgeType type, Introspector outObj, Introspector inObj, List<String> labels) - throws AAIException { + throws AAIException { String outType = outObj.getDbName(); String inType = inObj.getDbName(); @@ -777,7 +822,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { traversal.inE(inLabels.toArray(new String[inLabels.size()])); } else { traversal.union(__.outE(outLabels.toArray(new String[outLabels.size()])), - __.inE(inLabels.toArray(new String[inLabels.size()]))); + __.inE(inLabels.toArray(new String[inLabels.size()]))); } } @@ -902,4 +947,5 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> { return (QueryBuilder<Edge>) this; } + } diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java index 98da0766..fcfeb268 100644 --- a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java +++ b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java @@ -22,6 +22,8 @@ package org.onap.aai.query.builder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.Joiner; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; @@ -54,10 +56,14 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { private static final String ARGUMENT2 = "#!#argument#!#"; private static final String HAS = ".has('"; + private static final String SINGLE_QUOTE = "'"; + private static final String ESCAPE_SINGLE_QUOTE = "\\'"; private GremlinGroovyShell gremlinGroovy = new GremlinGroovyShell(); private GraphTraversal<?, ?> completeTraversal = null; protected List<String> list = null; + private static final Logger LOGGER = LoggerFactory.getLogger(QueryBuilder.class); + /** * Instantiates a new gremlin query builder. * @@ -79,6 +85,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { list = new ArrayList<>(); } + @Override public QueryBuilder<Vertex> exactMatchQuery(Introspector obj) { // TODO not implemented because this is implementation is no longer used @@ -87,6 +94,22 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { return (QueryBuilder<Vertex>) this; } + @Override + protected void vertexHas(String key, Object value) { + list.add(HAS + key + "', " + value + ")"); + } + + @Override + protected void vertexHasNot(String key) { + list.add(".hasNot('" + key + "')"); + + } + + @Override + protected void vertexHas(String key) { + list.add(HAS + key + "')"); + } + /** * @{inheritDoc} */ @@ -95,11 +118,16 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { String term = ""; if (value != null && !(value instanceof String)) { + String valueString = value.toString(); + if (valueString.indexOf('\'') != -1) { + value = valueString.replace(SINGLE_QUOTE, ESCAPE_SINGLE_QUOTE); + } + LOGGER.trace("Inside getVerticesByProperty(): key = {}, value = {}", key, value); term = value.toString(); } else { term = "'" + value + "'"; } - list.add(HAS + key + "', " + term + ")"); + this.vertexHas(key, term); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -109,7 +137,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { */ @Override public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, Object value) { - list.add(HAS + key + "', " + value + ")"); + this.vertexHas(key, value); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -125,7 +153,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { bValue = (Boolean) value; } - list.add(HAS + key + "', " + bValue + ")"); + this.vertexHas(key, bValue); stepIndex++; } return (QueryBuilder<Vertex>) this; @@ -148,7 +176,31 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { } String argument = Joiner.on(",").join(arguments); predicate = predicate.replace(ARGUMENT2, argument); - list.add(HAS + key + "', " + predicate + ")"); + this.vertexHas(key, predicate); + stepIndex++; + return (QueryBuilder<Vertex>) this; + } + + /** + * @{inheritDoc} + */ + @Override + public QueryBuilder<Vertex> getVerticesByCommaSeperatedValue(String key, String value) { + ArrayList<String> arguments = new ArrayList<>(Arrays.asList(value.split(","))); + //add the single quotes + for (int i = 0; i < arguments.size(); i++) { + if(arguments.get(i) != null && !arguments.get(i).startsWith("'") + && !arguments.get(i).endsWith("'")) { + arguments.set(i,"'" + arguments.get(i).trim() + "'"); + } + else { + arguments.set(i, arguments.get(i).trim()); + } + } + String predicate = "P.within(#!#argument#!#)"; + String argument = Joiner.on(",").join(arguments); + predicate = predicate.replace(ARGUMENT2, argument); + this.vertexHas(key, predicate); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -158,8 +210,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { */ @Override public QueryBuilder<Vertex> getVerticesByProperty(String key) { - - list.add(HAS + key + "')"); + this.vertexHas(key); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -169,8 +220,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { */ @Override public QueryBuilder<Vertex> getVerticesExcludeByProperty(String key) { - - list.add(".hasNot('" + key + "')"); + this.vertexHasNot(key); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -180,7 +230,6 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { */ @Override public QueryBuilder<Vertex> getVerticesStartsWithProperty(String key, Object value) { - String term = ""; String predicate = "org.janusgraph.core.attribute.Text.textPrefix(#!#argument#!#)"; if (value != null && !(value instanceof String)) { @@ -189,7 +238,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { term = "'" + value + "'"; } predicate = predicate.replace(ARGUMENT2, term); - list.add(HAS + key + "', " + predicate + ")"); + this.vertexHas(key, predicate); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -208,7 +257,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { term = "'" + value + "'"; } predicate = predicate.replace(ARGUMENT2, term); - list.add(HAS + key + "', " + predicate + ")"); + this.vertexHas(key, predicate); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -230,7 +279,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { } String argument = Joiner.on(",").join(arguments); predicate = predicate.replace(ARGUMENT2, argument); - list.add(HAS + key + "', " + predicate + ")"); + this.vertexHas(key, predicate); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -245,7 +294,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { term = "'" + value + "'"; } predicate = predicate.replace("#!#argument1#!#", term); - list.add(HAS + key + "', " + predicate + ")"); + this.vertexHas(key, predicate); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -260,7 +309,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { term = "'" + value + "'"; } predicate = predicate.replace("#!#argument1#!#", term); - list.add(HAS + key + "', " + predicate + ")"); + this.vertexHas(key, predicate); stepIndex++; return (QueryBuilder<Vertex>) this; } @@ -281,6 +330,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { public QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map) { for (Map.Entry<String, String> es : map.entrySet()) { + //TODO what is this and where is it used - need to check list.add(HAS + es.getKey() + "', '" + es.getValue() + "')"); stepIndex++; } @@ -594,6 +644,20 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { } @Override + public QueryBuilder<E> fold() { + this.list.add(".fold()"); + stepIndex++; + return this; + } + + @Override + public QueryBuilder<E> id() { + this.list.add(".id()"); + stepIndex++; + return this; + } + + @Override public QueryBuilder<E> dedup() { this.list.add(".dedup()"); stepIndex++; @@ -656,6 +720,31 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { return this; } + + @Override + public QueryBuilder<E> valueMap() { + this.list.add(".valueMap()"); + stepIndex++; + + return this; + } + + @Override + public QueryBuilder<E> valueMap(String... names) { + String stepString = ".valueMap('"; + for (int i = 0; i < names.length; i++) { + stepString = stepString + names[i] + "'"; + if (i != (names.length - 1)) { + stepString = stepString + ",'"; + } + } + stepString = stepString + ")"; + this.list.add(stepString); + stepIndex++; + + return this; + } + /** * {@inheritDoc} @@ -853,4 +942,9 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> { return (QueryBuilder<Edge>) this; } + /* + * This is required for the subgraphstrategies to work + */ + + } diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinTraversal.java b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinTraversal.java index 710db480..9cd35ab9 100644 --- a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinTraversal.java +++ b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinTraversal.java @@ -61,6 +61,7 @@ public class GremlinTraversal<E> extends GremlinQueryBuilder<E> { this.factory = new TraversalStrategy(this.loader, this); } + protected GremlinTraversal(List<String> traversal, Loader loader, GraphTraversalSource source, GremlinQueryBuilder<E> gtb) { super(loader, source); diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/HistoryGremlinTraversal.java b/aai-core/src/main/java/org/onap/aai/query/builder/HistoryGremlinTraversal.java new file mode 100644 index 00000000..5b14995c --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/query/builder/HistoryGremlinTraversal.java @@ -0,0 +1,170 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.query.builder; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.parsers.query.TraversalStrategy; + +import javax.ws.rs.core.MultivaluedMap; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +/** + * The Class GremlinTraversal. + */ +public class HistoryGremlinTraversal<E> extends GremlinTraversal<E> { + + /** + * Instantiates a new gremlin traversal. + * + * @param loader the loader + */ + public HistoryGremlinTraversal(Loader loader, GraphTraversalSource source) { + super(loader, source); + } + + /** + * Instantiates a new gremlin traversal. + * + * @param loader the loader + * @param start the start + */ + public HistoryGremlinTraversal(Loader loader, GraphTraversalSource source, Vertex start) { + super(loader, source, start); + } + + + protected HistoryGremlinTraversal(List<String> traversal, Loader loader, GraphTraversalSource source, + GremlinQueryBuilder<E> gtb) { + super(traversal, loader, source, gtb); + } + + /** + * @{inheritDoc} + */ + @Override + public QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException { + return factory.buildURIParser(uri); + } + + /** + * @{inheritDoc} + */ + @Override + public QueryParser createQueryFromRelationship(Introspector relationship) + throws UnsupportedEncodingException, AAIException { + return factory.buildRelationshipParser(relationship); + } + + /** + * @{inheritDoc} + */ + @Override + public QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams) + throws UnsupportedEncodingException, AAIException { + return factory.buildURIParser(uri, queryParams); + } + + /** + * @{inheritDoc} + */ + @Override + public QueryParser createQueryFromObjectName(String objName) { + return factory.buildObjectNameParser(objName); + } + + /** + * @{inheritDoc} + */ + @Override + public QueryBuilder<E> newInstance(Vertex start) { + return new HistoryGremlinTraversal<>(loader, source, start); + } + + /** + * @{inheritDoc} + */ + @Override + public QueryBuilder<E> newInstance() { + return new HistoryGremlinTraversal<>(loader, source); + } + + @Override + protected QueryBuilder<E> cloneQueryAtStep(int index) { + + int idx = index; + + if (idx == 0) { + idx = stepIndex; + } + + List<String> newList = new ArrayList<>(); + for (int i = 0; i < idx; i++) { + newList.add(this.list.get(i)); + } + + return new HistoryGremlinTraversal<>(newList, loader, source, this); + } + + @Override + protected void vertexHas(String key, Object value) { + super.vertexHas(key, value); + touchHistoryProperties(key, value); + } + + @Override + protected void vertexHasNot(String key) { + super.vertexHasNot(key); + touchHistoryProperties(key); + + } + + @Override + protected void vertexHas(String key) { + super.vertexHas(key); + touchHistoryProperties(key); + } + + /* + * This is required for the subgraphstrategies to work + */ + private void touchHistoryProperties(String key){ + if(key != null && !key.isEmpty() && !key.equals(AAIProperties.NODE_TYPE)) { + list.add(".where(__.properties('" + key + "'))"); + } + + } + + private void touchHistoryProperties(String key, Object value) { + if(key != null && !key.isEmpty() && !key.equals(AAIProperties.NODE_TYPE)) { + list.add(".where(__.properties('" + key + "').hasValue(" + value + "))"); + } + } +} diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/HistoryTraversalURIOptimizedQuery.java b/aai-core/src/main/java/org/onap/aai/query/builder/HistoryTraversalURIOptimizedQuery.java new file mode 100644 index 00000000..aeb5cd19 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/query/builder/HistoryTraversalURIOptimizedQuery.java @@ -0,0 +1,93 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.query.builder; + +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.Step; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +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.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.schema.enums.ObjectMetadata; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +public class HistoryTraversalURIOptimizedQuery<E> extends TraversalURIOptimizedQuery { + + protected Map<Integer, String> stepToAaiUri = new HashMap<>(); + + public HistoryTraversalURIOptimizedQuery(Loader loader, GraphTraversalSource source) { + super(loader, source); + } + + public HistoryTraversalURIOptimizedQuery(Loader loader, GraphTraversalSource source, Vertex start) { + super(loader, source, start); + } + + protected HistoryTraversalURIOptimizedQuery(GraphTraversal traversal, Loader loader, GraphTraversalSource source, + GraphTraversalBuilder gtb) { + super(traversal, loader, source, gtb); + } + + protected HistoryTraversalURIOptimizedQuery(GraphTraversal traversal, Loader loader, GraphTraversalSource source, + GraphTraversalBuilder gtb, Map<Integer, String> stepToAaiUri) { + super(traversal, loader, source, gtb, stepToAaiUri); + } + + @Override + protected void vertexHas(String key, Object value) { + super.vertexHas(key, value); + touchHistoryProperties(key, value); + } + + @Override + protected void vertexHasNot(String key) { + super.vertexHasNot(key); + touchHistoryProperties(key); + } + + @Override + protected void vertexHas(String key) { + super.vertexHas(key); + touchHistoryProperties(key); + } + + private void touchHistoryProperties(String key){ + if(key != null && !key.isEmpty() && !key.equals(AAIProperties.NODE_TYPE)) { + traversal.where(__.properties(key)); + } + } + + private void touchHistoryProperties(String key, Object value){ + if(key != null && !key.isEmpty() && !key.equals(AAIProperties.NODE_TYPE)) { + traversal.where(__.properties(key).hasValue(value)); + } + } +} diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java b/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java index a214811c..007f9798 100644 --- a/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java +++ b/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java @@ -20,14 +20,6 @@ package org.onap.aai.query.builder; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.ws.rs.core.MultivaluedMap; - import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; @@ -42,11 +34,17 @@ import org.onap.aai.edges.enums.EdgeType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; -import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.parsers.query.QueryParserStrategy; import org.springframework.context.ApplicationContext; +import javax.ws.rs.core.MultivaluedMap; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + /** * The Class QueryBuilder. */ @@ -113,9 +111,21 @@ public abstract class QueryBuilder<E> implements Iterator<E> { */ public abstract QueryBuilder<Vertex> getVerticesByProperty(String key, Object value); + + /** + * Gets the edges by property. + * + * @param key the key + * @param value the value + * @return the vertices by property + */ + public QueryBuilder<Edge> getEdgesByProperty(String key, Object value) { + return this.has(key, value.toString()); + } + /** * filters by all the values for this property - * + * * @param key * @param values * @return vertices that match these values @@ -126,7 +136,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * filters by all the values for this property - * + * * @param key * @param values * @return vertices that match these values @@ -134,10 +144,18 @@ public abstract class QueryBuilder<E> implements Iterator<E> { public abstract QueryBuilder<Vertex> getVerticesByProperty(String key, List<?> values); /** + * filters by all the values for this property + * + * @param key + * @param value in comma delimited string format + * @return vertices that match these values + */ + public abstract QueryBuilder<Vertex> getVerticesByCommaSeperatedValue(String key, String value); + + /** * Gets the vertices that have this property key. * * @param key the key - * @param value the value * @return the vertices by property */ public abstract QueryBuilder<Vertex> getVerticesByProperty(String key); @@ -146,14 +164,13 @@ public abstract class QueryBuilder<E> implements Iterator<E> { * Gets the vertices that do not have this property key. * * @param key the key - * @param value the value * @return the vertices by property */ public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key); /** * filters by elements that start with the value for this property - * + * * @param key * @param value * @return vertices that match these values @@ -171,7 +188,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * filters by all the values for this property and excludes the vertices - * + * * @param key * @param values * @return vertices that match these values @@ -182,7 +199,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * filters by all the values for this property and excludes the vertices - * + * * @param key * @param values * @return vertices that match these values @@ -191,18 +208,18 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * filters by all the values greater than for this property - * + * * @param key - * @param values + * @param value * @return vertices that match these values */ public abstract QueryBuilder<Vertex> getVerticesGreaterThanProperty(String key, Object value); /** * filters by all the values less than for this property - * + * * @param key - * @param values + * @param value * @return vertices that match these values */ @@ -334,7 +351,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * - * @param MissingOptionalParameter + * @param edgeType * @param outNodeType * @param inNodeType * @return @@ -348,6 +365,22 @@ public abstract class QueryBuilder<E> implements Iterator<E> { return this.createEdgeTraversal(outNodeType, inNodeType); } + /** + * + * @param edgeType + * @param outNodeType + * @param inNodeType + * @return + * @throws AAIException + */ + public QueryBuilder<Vertex> createEdgeTraversalWithLabels(MissingOptionalParameter edgeType, String outNodeType, + String inNodeType, List<String> labels) throws AAIException { + /* + * When no optional parameter edgetype is sent get all edges between the 2 nodetypes + */ + return this.createEdgeTraversalWithLabels(outNodeType, inNodeType, labels); + } + public QueryBuilder<Vertex> createEdgeTraversal(String outNodeType, String inNodeType) throws AAIException { Introspector out = loader.introspectorFromName(outNodeType); @@ -380,6 +413,38 @@ public abstract class QueryBuilder<E> implements Iterator<E> { return queryBuilder; } + public QueryBuilder<Vertex> createEdgeTraversalWithLabels(String outNodeType, String inNodeType, List<String> labels) throws AAIException { + + Introspector out = loader.introspectorFromName(outNodeType); + Introspector in = loader.introspectorFromName(inNodeType); + + QueryBuilder<Vertex> cousinBuilder = null; + QueryBuilder<Vertex> treeBuilder = null; + QueryBuilder<Vertex> queryBuilder = null; + + try { + cousinBuilder = this.newInstance().createEdgeTraversalWithLabels(EdgeType.COUSIN, out, in, labels); + } catch (AAIException e) { + } + + if (cousinBuilder != null) { + try { + treeBuilder = this.newInstance().createEdgeTraversalWithLabels(EdgeType.TREE, out, in, labels); + } catch (AAIException e) { + } + if (treeBuilder != null) { + queryBuilder = this.union(new QueryBuilder[] {cousinBuilder, treeBuilder}); + } else { + queryBuilder = this.union(new QueryBuilder[] {cousinBuilder}); + } + } else { + treeBuilder = this.newInstance().createEdgeTraversalWithLabels(EdgeType.TREE, out, in, labels); + queryBuilder = this.union(new QueryBuilder[] {treeBuilder}); + } + + return queryBuilder; + } + public QueryBuilder<Vertex> createPrivateEdgeTraversal(EdgeType type, String outNodeType, String inNodeType) throws AAIException { Introspector out = loader.introspectorFromName(outNodeType); @@ -415,6 +480,43 @@ public abstract class QueryBuilder<E> implements Iterator<E> { public abstract QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException; + + /** + * This method and it's overloaded counterpart are conditional statements. + * This method creates an edge traversal step if an optional property is present + * This is necessary in cases such as "if the Optional Property 1 is sent, + * find all Nodes of type A with edges to Nodes of type B with property 1, + * otherwise, simply find all nodes of type A". + * @param type + * @param outNodeType + * @param inNodeType + * @param value + * @return + * @throws AAIException + */ + public QueryBuilder<Vertex> createEdgeTraversalIfParameterIsPresent(EdgeType type, String outNodeType, String inNodeType, + Object value) throws AAIException { + return this.createEdgeTraversal(type, outNodeType, inNodeType); + } + + /** + * This method and it's overloaded counterpart are conditional statements. + * This method skips an edge traversal step if there is an optional property missing. + * This is necessary in cases such as "if the Optional Property 1 is sent, + * find all Nodes of type A with edges to Nodes of type B with property 1, + * otherwise, simply find all nodes of type A". + * @param type + * @param outNodeType + * @param inNodeType + * @param value + * @return + * @throws AAIException + */ + public QueryBuilder<Vertex> createEdgeTraversalIfParameterIsPresent(EdgeType type, String outNodeType, String inNodeType, + MissingOptionalParameter value) throws AAIException { + return (QueryBuilder<Vertex>) this; + } + /** * * @param type @@ -467,7 +569,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * Creates a queryparser from a given object name. - * + * * @param objName - name of the object type as it appears in the database * @return */ @@ -538,7 +640,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * uses all fields in the introspector to create a query - * + * * @param obj * @return */ @@ -547,7 +649,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * lets you join any number of QueryBuilders * <b>be careful about starting with a union it will not use indexes</b> - * + * * @param builder * @return */ @@ -563,6 +665,10 @@ public abstract class QueryBuilder<E> implements Iterator<E> { public abstract QueryBuilder<E> unfold(); + public abstract QueryBuilder<E> fold(); + + public abstract QueryBuilder<E> id(); + public abstract QueryBuilder<E> dedup(); public abstract QueryBuilder<E> emit(); @@ -591,6 +697,10 @@ public abstract class QueryBuilder<E> implements Iterator<E> { public abstract QueryBuilder<E> by(String name); + public abstract QueryBuilder<E> valueMap(); + + public abstract QueryBuilder<E> valueMap(String... names); + public abstract QueryBuilder<E> both(); public abstract QueryBuilder<Tree> tree(); @@ -598,7 +708,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * Used to prevent the traversal from repeating its path through the graph. * See http://tinkerpop.apache.org/docs/3.0.1-incubating/#simplepath-step for more info. - * + * * @return a QueryBuilder with the simplePath step appended to its traversal */ public abstract QueryBuilder<E> simplePath(); @@ -617,7 +727,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * Used to skip step if there is an optional property missing. - * + * * @param key * @param value * @return @@ -629,7 +739,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * TODO the edge direction is hardcoded here, make it more generic * Returns the parent edge of the vertex - * + * * @return */ public QueryBuilder<Edge> getParentEdge() { @@ -640,7 +750,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> { /** * TODO the edge direction is hardcoded here, make it more generic * Returns the parent vertex of the vertex - * + * * @return */ public QueryBuilder<Vertex> getParentVertex() { @@ -672,4 +782,13 @@ public abstract class QueryBuilder<E> implements Iterator<E> { public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, MissingOptionalParameter value) { return getVerticesByProperty(key, value); } + + protected abstract void vertexHas(String key, Object value) ; + + protected abstract void vertexHasNot(String key); + + protected abstract void vertexHas(String key); + + //TODO: This probably is not required but need to test + // protected abstract void vertexHas(final String key, final P<?> predicate); } diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java b/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java index cf99fd10..579c3571 100644 --- a/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java +++ b/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java @@ -30,7 +30,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step; 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.Vertex; -import org.onap.aai.edges.enums.EdgeType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; @@ -47,6 +46,7 @@ public class TraversalQuery<E> extends GraphTraversalBuilder<E> { * * @param loader the loader */ + public TraversalQuery(Loader loader, GraphTraversalSource source) { super(loader, source); this.factory = new TraversalStrategy(this.loader, this); @@ -125,6 +125,16 @@ public class TraversalQuery<E> extends GraphTraversalBuilder<E> { } @Override + public QueryBuilder<E> fold() { + return this; + } + + @Override + public QueryBuilder<E> id() { + return this; + } + + @Override protected QueryBuilder<E> cloneQueryAtStep(int index) { GraphTraversal.Admin<Vertex, E> cloneAdmin = getCloneAdmin(index); return new TraversalQuery<>(cloneAdmin, loader, source, this); diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/TraversalURIOptimizedQuery.java b/aai-core/src/main/java/org/onap/aai/query/builder/TraversalURIOptimizedQuery.java index 91d2d084..0e2a9cad 100644 --- a/aai-core/src/main/java/org/onap/aai/query/builder/TraversalURIOptimizedQuery.java +++ b/aai-core/src/main/java/org/onap/aai/query/builder/TraversalURIOptimizedQuery.java @@ -145,7 +145,6 @@ public class TraversalURIOptimizedQuery<E> extends TraversalQuery { } return shouldOptimize; - } private Optional<String> getStepUriFromIntrospector(Introspector obj) { @@ -166,7 +165,7 @@ public class TraversalURIOptimizedQuery<E> extends TraversalQuery { return Optional.of(uri); } - private int getLastURIStepKey() { + protected int getLastURIStepKey() { return stepToAaiUri.keySet().stream().mapToInt(Integer::intValue).max().getAsInt(); } diff --git a/aai-core/src/main/java/org/onap/aai/rest/db/DBRequest.java b/aai-core/src/main/java/org/onap/aai/rest/db/DBRequest.java index 1f94fbe2..e25a9062 100644 --- a/aai-core/src/main/java/org/onap/aai/rest/db/DBRequest.java +++ b/aai-core/src/main/java/org/onap/aai/rest/db/DBRequest.java @@ -26,6 +26,7 @@ import java.util.Optional; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.UriInfo; +import org.onap.aai.aailog.logs.DBRequestWrapper; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.MarshallerProperties; import org.onap.aai.parsers.query.QueryParser; @@ -34,7 +35,7 @@ import org.onap.aai.restcore.HttpMethod; /** * The Class DBRequest. */ -public class DBRequest { +public class DBRequest implements DBRequestWrapper { private final QueryParser parser; diff --git a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java index 61fc33a4..86d7e1b7 100644 --- a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java +++ b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java @@ -20,57 +20,24 @@ package org.onap.aai.rest.db; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.fge.jsonpatch.JsonPatchException; import com.github.fge.jsonpatch.mergepatch.JsonMergePatch; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriBuilder; - -import org.apache.commons.lang.StringUtils; -import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.janusgraph.core.JanusGraphException; import org.javatuples.Pair; -import org.json.JSONException; -import org.json.JSONObject; +import org.onap.aai.aailog.logs.AaiDBMetricLog; import org.onap.aai.db.props.AAIProperties; -import org.onap.aai.dbmap.DBConnectionType; -import org.onap.aai.domain.responseMessage.AAIResponseMessage; -import org.onap.aai.domain.responseMessage.AAIResponseMessageDatum; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.extensions.AAIExtensionMap; -import org.onap.aai.extensions.ExtensionController; import org.onap.aai.introspection.*; import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.logging.LoggingContext; import org.onap.aai.nodes.NodeIngestor; import org.onap.aai.parsers.query.QueryParser; -import org.onap.aai.parsers.uri.URIToExtensionInformation; -import org.onap.aai.parsers.uri.URIToObject; +import org.onap.aai.prevalidation.ValidationService; import org.onap.aai.rest.ueb.UEBNotification; import org.onap.aai.restcore.HttpMethod; import org.onap.aai.schema.enums.ObjectMetadata; @@ -84,17 +51,31 @@ import org.onap.aai.serialization.queryformats.FormatFactory; import org.onap.aai.serialization.queryformats.Formatter; import org.onap.aai.setup.SchemaVersion; import org.onap.aai.setup.SchemaVersions; +import org.onap.aai.transforms.XmlFormatTransformer; import org.onap.aai.util.AAIConfig; +import org.onap.aai.util.AAIConstants; +import org.onap.aai.util.delta.DeltaEvents; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; + +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.stream.Collectors; /** * The Class HttpEntry. */ public class HttpEntry { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(HttpEntry.class); - private static final String TARGET_ENTITY = "DB"; + private static final Logger LOGGER = LoggerFactory.getLogger(HttpEntry.class); private ModelType introspectorFactoryType; @@ -125,8 +106,24 @@ public class HttpEntry { @Value("${schema.uri.base.path}") private String basePath; + @Value("${delta.events.enabled:false}") + private boolean isDeltaEventsEnabled; + + @Autowired + private XmlFormatTransformer xmlFormatTransformer; + + /** + * Inject the validation service if the profile pre-valiation is enabled, + * Otherwise this variable will be set to null and thats why required=false + * so that it can continue even if pre validation isn't enabled + */ + @Autowired(required = false) + private ValidationService validationService; + private UEBNotification notification; + private int notificationDepth; + /** * Instantiates a new http entry. * @@ -138,23 +135,45 @@ public class HttpEntry { this.queryStyle = queryStyle; } - public HttpEntry setHttpEntryProperties(SchemaVersion version, DBConnectionType connectionType) { + public HttpEntry setHttpEntryProperties(SchemaVersion version) { this.version = version; this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); - this.dbEngine = new JanusGraphDBEngine(queryStyle, connectionType, loader); + this.dbEngine = new JanusGraphDBEngine(queryStyle, loader); getDbEngine().startTransaction(); this.notification = new UEBNotification(loader, loaderFactory, schemaVersions); + if("true".equals(AAIConfig.get("aai.notification.depth.all.enabled", "true"))){ + this.notificationDepth = AAIProperties.MAXIMUM_DEPTH; + } else { + this.notificationDepth = AAIProperties.MINIMUM_DEPTH; + } return this; } - public HttpEntry setHttpEntryProperties(SchemaVersion version, DBConnectionType connectionType, - UEBNotification notification) { + public HttpEntry setHttpEntryProperties(SchemaVersion version, UEBNotification notification) { this.version = version; this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); - this.dbEngine = new JanusGraphDBEngine(queryStyle, connectionType, loader); + this.dbEngine = new JanusGraphDBEngine(queryStyle, loader); this.notification = notification; + + if("true".equals(AAIConfig.get("aai.notification.depth.all.enabled", "true"))){ + this.notificationDepth = AAIProperties.MAXIMUM_DEPTH; + } else { + this.notificationDepth = AAIProperties.MINIMUM_DEPTH; + } + // start transaction on creation + getDbEngine().startTransaction(); + return this; + } + + public HttpEntry setHttpEntryProperties(SchemaVersion version, UEBNotification notification, int notificationDepth) { + this.version = version; + this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); + this.dbEngine = new JanusGraphDBEngine(queryStyle, loader); + + this.notification = notification; + this.notificationDepth = notificationDepth; // start transaction on creation getDbEngine().startTransaction(); return this; @@ -222,7 +241,7 @@ public class HttpEntry { /** * Returns the pagination size - * + * * @return integer of the size of results to be returned when paginated */ public int getPaginationBucket() { @@ -231,7 +250,7 @@ public class HttpEntry { /** * Setter for the pagination bucket variable which stores in this object the size of results to return - * + * * @param pb */ public void setPaginationBucket(int pb) { @@ -240,7 +259,7 @@ public class HttpEntry { /** * Getter to return the pagination index requested by the user when requesting paginated results - * + * * @return */ public int getPaginationIndex() { @@ -250,7 +269,7 @@ public class HttpEntry { /** * Sets the pagination index that was passed in by the user, to determine which index or results to retrieve when * paginated - * + * * @param pi */ public void setPaginationIndex(int pi) { @@ -262,7 +281,7 @@ public class HttpEntry { /** * Sets the total vertices variables and calculates the amount of pages based on size and total vertices - * + * * @param totalVertices * @param paginationBucketSize */ @@ -293,7 +312,7 @@ public class HttpEntry { /** * Process. - * + * * @param requests the requests * @param sourceOfTruth the source of truth * @@ -303,41 +322,44 @@ public class HttpEntry { public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth, boolean enableResourceVersion) throws AAIException { - DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth); - String methodName = "process"; + DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth, notificationDepth); Response response; - Introspector obj = null; - QueryParser query = null; - URI uri = null; + Introspector obj; + QueryParser query; + URI uri; String transactionId = null; - int depth = AAIProperties.MAXIMUM_DEPTH; + int depth; Format format = null; List<Pair<URI, Response>> responses = new ArrayList<>(); - MultivaluedMap<String, String> params = null; - HttpMethod method = null; - String uriTemp = ""; - Boolean success = true; + MultivaluedMap<String, String> params; + HttpMethod method; + String uriTemp; + boolean success = true; QueryEngine queryEngine = dbEngine.getQueryEngine(); - int maxRetries = 10; - int retry = 0; + Set<Vertex> mainVertexesToNotifyOn = new LinkedHashSet<>(); + + AaiDBMetricLog metricLog = new AaiDBMetricLog(AAIConstants.AAI_RESOURCES_MS); + + String outputMediaType = null; + + if(requests != null && !requests.isEmpty()){ + HttpHeaders headers = requests.get(0).getHeaders(); + outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); + } - LoggingContext.save(); for (DBRequest request : requests) { response = null; Status status = Status.NOT_FOUND; method = request.getMethod(); + metricLog.pre(request); try { try { - LoggingContext.targetEntity(TARGET_ENTITY); - LoggingContext.targetServiceName(methodName + " " + method); - obj = request.getIntrospector(); query = request.getParser(); transactionId = request.getTransactionId(); uriTemp = request.getUri().getRawPath().replaceFirst("^v\\d+/", ""); uri = UriBuilder.fromPath(uriTemp).build(); - LoggingContext.startTime(); List<Vertex> vertTemp; List<Vertex> vertices; if (this.isPaginated()) { @@ -348,8 +370,9 @@ public class HttpEntry { } else { vertices = query.getQueryBuilder().toList(); } - boolean isNewVertex = false; - String outputMediaType = getMediaType(request.getHeaders().getAcceptableMediaTypes()); + boolean isNewVertex; + HttpHeaders headers = request.getHeaders(); + outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); String result = null; params = request.getInfo().getQueryParameters(false); depth = setDepth(obj, params.getFirst("depth")); @@ -369,15 +392,14 @@ public class HttpEntry { if (vertices.size() > 1 && processSingle && !(method.equals(HttpMethod.GET) || method.equals(HttpMethod.GET_RELATIONSHIP))) { if (method.equals(HttpMethod.DELETE)) { - LoggingContext.restoreIfPossible(); + throw new AAIException("AAI_6138"); } else { - LoggingContext.restoreIfPossible(); throw new AAIException("AAI_6137"); } } if (method.equals(HttpMethod.PUT)) { - String resourceVersion = (String) obj.getValue("resource-version"); + String resourceVersion = obj.getValue(AAIProperties.RESOURCE_VERSION); if (vertices.isEmpty()) { if (enableResourceVersion) { serializer.verifyResourceVersion("create", query.getResultType(), "", @@ -387,7 +409,7 @@ public class HttpEntry { } else { if (enableResourceVersion) { serializer.verifyResourceVersion("update", query.getResultType(), - vertices.get(0).<String>property("resource-version").orElse(null), + vertices.get(0).<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), resourceVersion, obj.getURI()); } isNewVertex = false; @@ -404,6 +426,22 @@ public class HttpEntry { if (!isNewVertex) { v = vertices.get(0); } + + /* + * This skip-related-to query parameter is used to determine if the relationships object will omit the related-to-property + * If a GET is sent to resources without a format, if format=resource, or if format=resource_and_url with this param set to false + * then behavior will be keep the related-to properties. By default, set to true. + * Otherwise, for any other case, when the skip-related-to parameter exists, has value=true, or some unfamiliar input (e.g. skip-related-to=bogusvalue), the value is true. + */ + boolean isSkipRelatedTo = true; + if (params.containsKey("skip-related-to")) { + String skipRelatedTo = params.getFirst("skip-related-to"); + isSkipRelatedTo = !(skipRelatedTo != null && skipRelatedTo.equals("false")); + } else { + // if skip-related-to param is missing, then default it to false; + isSkipRelatedTo = false; + } + HashMap<String, Introspector> relatedObjects = new HashMap<>(); String nodeOnly = params.getFirst("nodes-only"); boolean isNodeOnly = nodeOnly != null; @@ -412,12 +450,7 @@ public class HttpEntry { if (format == null) { obj = this.getObjectFromDb(vertices, serializer, query, obj, request.getUri(), - depth, isNodeOnly, cleanUp); - - LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs(), - TimeUnit.MILLISECONDS); - LOGGER.info("Completed"); - LoggingContext.restoreIfPossible(); + depth, isNodeOnly, cleanUp, isSkipRelatedTo); if (obj != null) { status = Status.OK; @@ -436,6 +469,14 @@ public class HttpEntry { Formatter formatter = ff.get(format, params); result = formatter.output(vertices.stream().map(vertex -> (Object) vertex) .collect(Collectors.toList())).toString(); + + if(outputMediaType == null){ + outputMediaType = MediaType.APPLICATION_JSON; + } + + if(MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(outputMediaType))){ + result = xmlFormatTransformer.transform(result); + } status = Status.OK; } @@ -443,12 +484,7 @@ public class HttpEntry { case GET_RELATIONSHIP: if (format == null) { obj = this.getRelationshipObjectFromDb(vertices, serializer, query, - request.getInfo().getRequestUri()); - - LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs(), - TimeUnit.MILLISECONDS); - LOGGER.info("Completed"); - LoggingContext.restoreIfPossible(); + request.getInfo().getRequestUri(), isSkipRelatedTo); if (obj != null) { status = Status.OK; @@ -471,49 +507,50 @@ public class HttpEntry { Formatter formatter = ff.get(format, params); result = formatter.output(vertices.stream().map(vertex -> (Object) vertex) .collect(Collectors.toList())).toString(); + + if(outputMediaType == null){ + outputMediaType = MediaType.APPLICATION_JSON; + } + + if(MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(outputMediaType))){ + result = xmlFormatTransformer.transform(result); + } status = Status.OK; } break; case PUT: - response = this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, - sourceOfTruth, version, loader, obj, uri, true); if (isNewVertex) { v = serializer.createNewVertex(obj); } serializer.serializeToDb(obj, v, query, uri.getRawPath(), requestContext); - this.invokeExtension(dbEngine, this.dbEngine.tx(), HttpMethod.PUT, request, - sourceOfTruth, version, loader, obj, uri, false); status = Status.OK; if (isNewVertex) { status = Status.CREATED; } - obj = serializer.getLatestVersionView(v); - if (query.isDependent()) { - relatedObjects = - this.getRelatedObjects(serializer, queryEngine, v, obj, this.loader); + + mainVertexesToNotifyOn.add(v); + if (notificationDepth == AAIProperties.MINIMUM_DEPTH) { + Map<String, Pair<Introspector, LinkedHashMap<String,Introspector>>> allImpliedDeleteObjs = serializer.getImpliedDeleteUriObjectPair(); + + for(Map.Entry<String, Pair<Introspector, LinkedHashMap<String,Introspector>>> entry: allImpliedDeleteObjs.entrySet()){ + // The format is purposefully %s/%s%s due to the fact + // that every aai-uri will have a slash at the beginning + // If that assumption isn't true, then its best to change this code + String curUri = String.format("%s/%s%s", basePath , version , entry.getKey()); + Introspector curObj = entry.getValue().getValue0(); + HashMap<String, Introspector> curObjRelated = entry.getValue().getValue1(); + notification.createNotificationEvent(transactionId, sourceOfTruth, Status.NO_CONTENT, URI.create(curUri), curObj, curObjRelated, basePath); + } } - LoggingContext.elapsedTime( - (long) serializer.getDBTimeMsecs() + (long) queryEngine.getDBTimeMsecs(), - TimeUnit.MILLISECONDS); - LOGGER.info("Completed "); - LoggingContext.restoreIfPossible(); - notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, - relatedObjects, basePath); break; case PUT_EDGE: serializer.touchStandardVertexProperties(v, false); - this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, - version, loader, obj, uri, true); - serializer.createEdge(obj, v); - - LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs(), TimeUnit.MILLISECONDS); - LOGGER.info("Completed"); - LoggingContext.restoreIfPossible(); + Vertex relatedVertex = serializer.createEdge(obj, v); status = Status.OK; - notification.createNotificationEvent(transactionId, sourceOfTruth, status, - new URI(uri.toString().replace("/relationship-list/relationship", "")), - serializer.getLatestVersionView(v), relatedObjects, basePath); + + mainVertexesToNotifyOn.add(v); + serializer.addVertexToEdgeVertexes(relatedVertex); break; case MERGE_PATCH: Introspector existingObj = loader.introspectorFromName(obj.getDbName()); @@ -536,37 +573,23 @@ public class HttpEntry { JsonNode completed = patch.apply(existingNode); String patched = mapper.writeValueAsString(completed); Introspector patchedObj = loader.unmarshal(existingObj.getName(), patched); - if (relationshipList == null) { + if (relationshipList == null && patchedObj.hasProperty("relationship-list")) { // if the caller didn't touch the relationship-list, we shouldn't either patchedObj.setValue("relationship-list", null); } serializer.serializeToDb(patchedObj, v, query, uri.getRawPath(), requestContext); status = Status.OK; - patchedObj = serializer.getLatestVersionView(v); - if (query.isDependent()) { - relatedObjects = this.getRelatedObjects(serializer, queryEngine, v, patchedObj, - this.loader); - } - LoggingContext.elapsedTime( - (long) serializer.getDBTimeMsecs() + (long) queryEngine.getDBTimeMsecs(), - TimeUnit.MILLISECONDS); - LOGGER.info("Completed"); - LoggingContext.restoreIfPossible(); - notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, - patchedObj, relatedObjects, basePath); + mainVertexesToNotifyOn.add(v); } catch (IOException | JsonPatchException e) { - - LOGGER.info("Caught exception: " + e.getMessage()); - LoggingContext.restoreIfPossible(); throw new AAIException("AAI_3000", "could not perform patch operation"); } break; case DELETE: - String resourceVersion = params.getFirst("resource-version"); - obj = serializer.getLatestVersionView(v); + String resourceVersion = params.getFirst(AAIProperties.RESOURCE_VERSION); + obj = serializer.getLatestVersionView(v, notificationDepth); if (query.isDependent()) { relatedObjects = - this.getRelatedObjects(serializer, queryEngine, v, obj, this.loader); + serializer.getRelatedObjects(queryEngine, v, obj, this.loader); } /* * Find all Delete-other-vertex vertices and create structure for notify @@ -576,7 +599,7 @@ public class HttpEntry { */ List<Vertex> deletableVertices = dbEngine.getQueryEngine().findDeletable(v); - Long vId = (Long) v.id(); + Object vId = v.id(); /* * I am assuming vertexId cant be null @@ -595,17 +618,7 @@ public class HttpEntry { this.buildRelatedObjects(serializer, queryEngine, deleteObjects); } - this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, - version, loader, obj, uri, true); serializer.delete(v, deletableVertices, resourceVersion, enableResourceVersion); - this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, - version, loader, obj, uri, false); - - LoggingContext.elapsedTime( - (long) serializer.getDBTimeMsecs() + (long) queryEngine.getDBTimeMsecs(), - TimeUnit.MILLISECONDS); - LOGGER.info("Completed"); - LoggingContext.restoreIfPossible(); status = Status.NO_CONTENT; notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects, basePath); @@ -618,19 +631,16 @@ public class HttpEntry { this.buildNotificationEvent(sourceOfTruth, status, transactionId, notification, deleteObjects, uriMap, deleteRelatedObjects, basePath); } - break; case DELETE_EDGE: serializer.touchStandardVertexProperties(v, false); - serializer.deleteEdge(obj, v); + Optional<Vertex> otherV = serializer.deleteEdge(obj, v); - LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs(), TimeUnit.MILLISECONDS); - LOGGER.info("Completed"); - LoggingContext.restoreIfPossible(); status = Status.NO_CONTENT; - notification.createNotificationEvent(transactionId, sourceOfTruth, Status.OK, - new URI(uri.toString().replace("/relationship-list/relationship", "")), - serializer.getLatestVersionView(v), relatedObjects, basePath); + if (otherV.isPresent()) { + mainVertexesToNotifyOn.add(v); + serializer.addVertexToEdgeVertexes(otherV.get()); + } break; default: break; @@ -659,21 +669,14 @@ public class HttpEntry { } } else if (response == null) { response = Response.status(status).type(outputMediaType).build(); - } else { - // response already set to something - } + } // else, response already set to something + Pair<URI, Response> pairedResp = Pair.with(request.getUri(), response); responses.add(pairedResp); } catch (JanusGraphException e) { this.dbEngine.rollback(); - - LOGGER.info("Caught exception: " + e.getMessage()); - LoggingContext.restoreIfPossible(); throw new AAIException("AAI_6134", e); } - if (retry == maxRetries) { - throw new AAIException("AAI_6134"); - } } catch (AAIException e) { success = false; ArrayList<String> templateVars = new ArrayList<>(); @@ -683,31 +686,123 @@ public class HttpEntry { ErrorLogHelper.logException(e); response = Response.status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper .getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), e, templateVars)) + .type(outputMediaType) .build(); Pair<URI, Response> pairedResp = Pair.with(request.getUri(), response); responses.add(pairedResp); - continue; } catch (Exception e) { success = false; - e.printStackTrace(); AAIException ex = new AAIException("AAI_4000", e); - ArrayList<String> templateVars = new ArrayList<String>(); + ArrayList<String> templateVars = new ArrayList<>(); templateVars.add(request.getMethod().toString()); // GET, PUT, etc - templateVars.add(request.getUri().getPath().toString()); + templateVars.add(request.getUri().getPath()); ErrorLogHelper.logException(ex); response = Response.status(ex.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper .getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), ex, templateVars)) + .type(outputMediaType) .build(); Pair<URI, Response> pairedResp = Pair.with(request.getUri(), response); responses.add(pairedResp); - continue; + } + finally { + if (response != null) { + metricLog.post(request, response); + } } } - notification.triggerEvents(); + + if (success) { + generateEvents(sourceOfTruth, serializer, transactionId, queryEngine, mainVertexesToNotifyOn); + } else { + notification.clearEvents(); + } + return Pair.with(success, responses); } /** + * Generate notification events for the resulting db requests. + */ + private void generateEvents(String sourceOfTruth, DBSerializer serializer, String transactionId, QueryEngine queryEngine, Set<Vertex> mainVertexesToNotifyOn) throws AAIException { + if (notificationDepth == AAIProperties.MINIMUM_DEPTH) { + serializer.getUpdatedVertexes().entrySet().stream().filter(Map.Entry::getValue).map(Map.Entry::getKey).forEach(mainVertexesToNotifyOn::add); + } + Set<Vertex> edgeVertexes = serializer.touchStandardVertexPropertiesForEdges().stream() + .filter(v -> !mainVertexesToNotifyOn.contains(v)).collect(Collectors.toSet()); + try { + createNotificationEvents(mainVertexesToNotifyOn, sourceOfTruth, serializer, transactionId, queryEngine, notificationDepth); + if("true".equals(AAIConfig.get("aai.notification.both.sides.enabled", "true"))){ + createNotificationEvents(edgeVertexes, sourceOfTruth, serializer, transactionId, queryEngine, AAIProperties.MINIMUM_DEPTH); + } + } catch (UnsupportedEncodingException e) { + LOGGER.warn("Encountered exception generating events", e); + } + + // Since @Autowired required is set to false, we need to do a null check + // for the existence of the validationService since its only enabled if profile is enabled + if(validationService != null){ + validationService.validate(notification.getEvents()); + } + notification.triggerEvents(); + if (isDeltaEventsEnabled) { + try { + DeltaEvents deltaEvents = new DeltaEvents(transactionId, sourceOfTruth, version.toString(), serializer.getObjectDeltas()); + deltaEvents.triggerEvents(); + } catch (Exception e) { + LOGGER.error("Error sending Delta Events", e); + } + } + } + + /** + * Generate notification events for provided set of vertexes at the specified depth + */ + private void createNotificationEvents(Set<Vertex> vertexesToNotifyOn, String sourceOfTruth, DBSerializer serializer, + String transactionId, QueryEngine queryEngine, int eventDepth) throws AAIException, UnsupportedEncodingException { + for(Vertex vertex : vertexesToNotifyOn){ + if (canGenerateEvent(vertex)) { + boolean isCurVertexNew = vertex.value(AAIProperties.CREATED_TS).equals(vertex.value(AAIProperties.LAST_MOD_TS)); + Status curObjStatus = (isCurVertexNew) ? Status.CREATED : Status.OK; + + Introspector curObj = serializer.getLatestVersionView(vertex, eventDepth); + String aaiUri = vertex.<String>property(AAIProperties.AAI_URI).value(); + String uri = String.format("%s/%s%s", basePath, version, aaiUri); + HashMap<String, Introspector> curRelatedObjs = new HashMap<>(); + if (!curObj.isTopLevel()) { + curRelatedObjs = serializer.getRelatedObjects(queryEngine, vertex, curObj, this.loader); + } + notification.createNotificationEvent(transactionId, sourceOfTruth, curObjStatus, URI.create(uri), curObj, curRelatedObjs, basePath); + } + } + } + + /** + * Verifies that vertex has needed properties to generate on + * @param vertex Vertex to be verified + * @return <code>true</code> if vertex has necessary properties and exists + */ + private boolean canGenerateEvent(Vertex vertex) { + boolean canGenerate = true; + try { + if(!vertex.property(AAIProperties.AAI_URI).isPresent()){ + LOGGER.debug("Encountered an vertex {} with missing aai-uri", vertex.id()); + canGenerate = false; + } else if(!vertex.property(AAIProperties.CREATED_TS).isPresent() || !vertex.property(AAIProperties.LAST_MOD_TS).isPresent()){ + LOGGER.debug("Encountered an vertex {} with missing timestamp", vertex.id()); + canGenerate = false; + } + } catch (IllegalStateException e) { + if (e.getMessage().contains(" was removed")) { + LOGGER.warn("Attempted to generate event for non existent vertex", e); + } else { + LOGGER.warn("Encountered exception generating events", e); + } + canGenerate = false; + } + return canGenerate; + } + + /** * Gets the media type. * * @param mediaTypeList the media type list @@ -760,7 +855,6 @@ public class HttpEntry { return serializer.dbToObject(results, obj, depth, nodeOnly, cleanUp); } - /** * Gets the object from db. * @@ -770,6 +864,7 @@ public class HttpEntry { * @param uri the uri * @param depth the depth * @param cleanUp the clean up + * @param isSkipRelatedTo include related to flag * @return the object from db * @throws AAIException the AAI exception * @throws IllegalAccessException the illegal access exception @@ -783,9 +878,11 @@ public class HttpEntry { * @throws AAIUnknownObjectException * @throws URISyntaxException */ - private Introspector getRelationshipObjectFromDb(List<Vertex> results, DBSerializer serializer, QueryParser query, - URI uri) throws AAIException, IllegalArgumentException, SecurityException, UnsupportedEncodingException, - AAIUnknownObjectException { + private Introspector getObjectFromDb(List<Vertex> results, DBSerializer serializer, QueryParser query, + Introspector obj, URI uri, int depth, boolean nodeOnly, String cleanUp, boolean isSkipRelatedTo) + throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, + SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, + AAIUnknownObjectException, URISyntaxException { // nothing found if (results.isEmpty()) { @@ -793,104 +890,45 @@ public class HttpEntry { throw new AAIException("AAI_6114", msg); } - if (results.size() > 1) { - throw new AAIException("AAI_6148", uri.getPath()); - } + return serializer.dbToObject(results, obj, depth, nodeOnly, cleanUp, isSkipRelatedTo); - Vertex v = results.get(0); - return serializer.dbToRelationshipObject(v); } /** - * Invoke extension. + * Gets the object from db. * - * @param dbEngine the db engine - * @param g the g - * @param httpMethod the http method - * @param fromAppId the from app id - * @param apiVersion the api version - * @param loader the loader - * @param obj the obj + * @param serializer the serializer + * @param query the query * @param uri the uri - * @param isPreprocess the is preprocess - * @return the response + * @return the object from db + * @throws AAIException the AAI exception + * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception + * @throws InvocationTargetException the invocation target exception + * @throws SecurityException the security exception + * @throws InstantiationException the instantiation exception + * @throws NoSuchMethodException the no such method exception * @throws UnsupportedEncodingException the unsupported encoding exception - * @throws AAIException the AAI exception - */ - private Response invokeExtension(TransactionalGraphEngine dbEngine, Graph g, HttpMethod httpMethod, - DBRequest request, String fromAppId, SchemaVersion apiVersion, Loader loader, Introspector obj, URI uri, - boolean isPreprocess) throws IllegalArgumentException, UnsupportedEncodingException, AAIException { - AAIExtensionMap aaiExtMap = new AAIExtensionMap(); - // ModelInjestor injestor = ModelInjestor.getInstance(); - Response response = null; - URIToExtensionInformation extensionInformation = new URIToExtensionInformation(loader, uri); - aaiExtMap.setHttpEntry(this); - aaiExtMap.setDbRequest(request); - aaiExtMap.setTransId(request.getTransactionId()); - aaiExtMap.setFromAppId(fromAppId); - aaiExtMap.setGraph(g); - aaiExtMap.setApiVersion(apiVersion.toString()); - aaiExtMap.setObjectFromRequest(obj); - aaiExtMap.setObjectFromRequestType(obj.getJavaClassName()); - aaiExtMap.setObjectFromResponse(obj); - aaiExtMap.setObjectFromResponseType(obj.getJavaClassName()); - aaiExtMap.setJaxbContext(nodeIngestor.getContextForVersion(apiVersion)); - aaiExtMap.setUri(uri.getRawPath()); - aaiExtMap.setTransactionalGraphEngine(dbEngine); - aaiExtMap.setLoader(loader); - aaiExtMap.setNamespace(extensionInformation.getNamespace()); - - ExtensionController ext = new ExtensionController(); - ext.runExtension(aaiExtMap.getApiVersion(), extensionInformation.getNamespace(), - extensionInformation.getTopObject(), extensionInformation.getMethodName(httpMethod, isPreprocess), - aaiExtMap, isPreprocess); - - if (aaiExtMap.getPrecheckAddedList().size() > 0) { - response = notifyOnSkeletonCreation(aaiExtMap, obj, request.getHeaders()); - } - - return response; - } - - /** - * Notify on skeleton creation. - * - * @param aaiExtMap the aai ext map - * @param input the input - * @param headers the headers - * @return the response + * @throws MalformedURLException the malformed URL exception + * @throws AAIUnknownObjectException + * @throws URISyntaxException */ - // Legacy support - private Response notifyOnSkeletonCreation(AAIExtensionMap aaiExtMap, Introspector input, HttpHeaders headers) { - Response response = null; - HashMap<AAIException, ArrayList<String>> exceptionList = new HashMap<AAIException, ArrayList<String>>(); - - StringBuilder keyString = new StringBuilder(); + private Introspector getRelationshipObjectFromDb(List<Vertex> results, DBSerializer serializer, QueryParser query, + URI uri, boolean isSkipRelatedTo) throws AAIException, IllegalArgumentException, SecurityException, UnsupportedEncodingException, + AAIUnknownObjectException { - Set<String> resourceKeys = input.getKeys(); - for (String key : resourceKeys) { - keyString.append(key).append("=").append(input.getValue(key).toString()).append(" "); + // nothing found + if (results.isEmpty()) { + String msg = createNotFoundMessage(query.getResultType(), uri); + throw new AAIException("AAI_6114", msg); } - for (AAIResponseMessage msg : aaiExtMap.getPrecheckResponseMessages().getAAIResponseMessage()) { - ArrayList<String> templateVars = new ArrayList<>(); - - templateVars.add("PUT " + input.getDbName()); - templateVars.add(keyString.toString()); - List<String> keys = new ArrayList<>(); - templateVars.add(msg.getAaiResponseMessageResourceType()); - for (AAIResponseMessageDatum dat : msg.getAaiResponseMessageData().getAAIResponseMessageDatum()) { - keys.add(dat.getAaiResponseMessageDatumKey() + "=" + dat.getAaiResponseMessageDatumValue()); - } - templateVars.add(StringUtils.join(keys, ", ")); - exceptionList.put(new AAIException("AAI_0004", msg.getAaiResponseMessageResourceType()), templateVars); + if (results.size() > 1) { + throw new AAIException("AAI_6148", uri.getPath()); } - response = Response.status(Status.ACCEPTED) - .entity(ErrorLogHelper.getRESTAPIInfoResponse(headers.getAcceptableMediaTypes(), exceptionList)) - .build(); - return response; + Vertex v = results.get(0); + return serializer.dbToRelationshipObject(v, isSkipRelatedTo); } /** @@ -901,10 +939,7 @@ public class HttpEntry { * @return the string */ private String createNotFoundMessage(String resultType, URI uri) { - - String msg = "No Node of type " + resultType + " found at: " + uri.getPath(); - - return msg; + return "No Node of type " + resultType + " found at: " + uri.getPath(); } /** @@ -915,11 +950,8 @@ public class HttpEntry { * @return the string */ private String createRelationshipNotFoundMessage(String resultType, URI uri) { - - String msg = "No relationship found of type " + resultType + " at the given URI: " + uri.getPath() + return "No relationship found of type " + resultType + " at the given URI: " + uri.getPath() + "/relationship-list"; - - return msg; } /** @@ -933,16 +965,13 @@ public class HttpEntry { int depth = AAIProperties.MAXIMUM_DEPTH; String getAllRandomStr = AAIConfig.get("aai.rest.getall.depthparam", ""); - if (depthParam != null && getAllRandomStr != null && !getAllRandomStr.isEmpty() - && getAllRandomStr.equals(depthParam)) { + if (getAllRandomStr != null && !getAllRandomStr.isEmpty() && getAllRandomStr.equals(depthParam)) { return depth; } if (depthParam == null) { if (this.version.compareTo(schemaVersions.getDepthVersion()) >= 0) { depth = 0; - } else { - depth = AAIProperties.MAXIMUM_DEPTH; } } else { if (!depthParam.isEmpty() && !"all".equals(depthParam)) { @@ -973,184 +1002,14 @@ public class HttpEntry { return depth; } - /** - * Checks if is modification method. - * - * @param method the method - * @return true, if is modification method - */ - private boolean isModificationMethod(HttpMethod method) { - boolean result = false; - - if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PUT_EDGE) || method.equals(HttpMethod.DELETE_EDGE) - || method.equals(HttpMethod.MERGE_PATCH)) { - result = true; - } - - return result; - - } - - /** - * Given an uri, introspector object and loader object - * it will check if the obj is top level object if it is, - * it will return immediately returning the uri passed in - * If it isn't, it will go through, get the uriTemplate - * from the introspector object and get the count of "/"s - * and remove that part of the uri using substring - * and keep doing that until the current object is top level - * Also added the max depth just so worst case scenario - * Then keep adding aai-uri to the list include the aai-uri passed in - * Convert that list into an array and return it - * <p> - * - * Example: - * - * <blockquote> - * aai-uri -> - * /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1/vservers/vserver/v1 - * - * Given the uriTemplate vserver -> /vservers/vserver/{vserver-id} - * it converts to /vservers/vserver - * - * lastIndexOf /vservers/vserver in - * /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1/vservers/vserver/v1 - * ^ - * | - * | - * lastIndexOf - * Use substring to get the string from 0 to that lastIndexOf - * aai-uri -> /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1 - * - * From this new aai-uri, generate a introspector from the URITOObject class - * and keep doing this until you - * - * </blockquote> - * - * @param aaiUri - aai-uri of the vertex representating the unique id of a given vertex - * @param obj - introspector object of the given starting vertex - * @param loader - Type of loader which will always be MoxyLoader to support model driven - * @return an array of strings which can be used to get the vertexes of parent and grand parents from a given vertex - * @throws UnsupportedEncodingException - * @throws AAIException - */ - String[] convertIntrospectorToUriList(String aaiUri, Introspector obj, Loader loader) - throws UnsupportedEncodingException, AAIException { - - List<String> uriList = new ArrayList<>(); - String template = StringUtils.EMPTY; - String truncatedUri = aaiUri; - int depth = AAIProperties.MAXIMUM_DEPTH; - uriList.add(truncatedUri); - - while (depth >= 0 && !obj.isTopLevel()) { - template = obj.getMetadata(ObjectMetadata.URI_TEMPLATE); - - if (template == null) { - LOGGER.warn("Unable to find the uriTemplate for the object {}", obj.getDbName()); - return null; - } - - int templateCount = StringUtils.countMatches(template, "/"); - int truncatedUriCount = StringUtils.countMatches(truncatedUri, "/"); - - if (templateCount > truncatedUriCount) { - LOGGER.warn("Template uri {} contains more slashes than truncatedUri {}", template, truncatedUri); - return null; - } - - int cutIndex = StringUtils.ordinalIndexOf(truncatedUri, "/", truncatedUriCount - templateCount + 1); - truncatedUri = StringUtils.substring(truncatedUri, 0, cutIndex); - uriList.add(truncatedUri); - obj = new URIToObject(loader, UriBuilder.fromPath(truncatedUri).build()).getEntity(); - depth--; - } - - return uriList.toArray(new String[uriList.size()]); - } - - /** - * - * @param serializer - * @param queryEngine - * @param v - * @param obj - * @param loader - * @return - * @throws IllegalAccessException - * @throws IllegalArgumentException - * @throws InvocationTargetException - * @throws SecurityException - * @throws InstantiationException - * @throws NoSuchMethodException - * @throws UnsupportedEncodingException - * @throws AAIException - * @throws URISyntaxException - */ - private HashMap<String, Introspector> getRelatedObjects(DBSerializer serializer, QueryEngine queryEngine, Vertex v, - Introspector obj, Loader loader) throws IllegalAccessException, IllegalArgumentException, - InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, - UnsupportedEncodingException, AAIException, URISyntaxException { - - HashMap<String, Introspector> relatedVertices = new HashMap<>(); - VertexProperty aaiUriProperty = v.property(AAIProperties.AAI_URI); - - if (!aaiUriProperty.isPresent()) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("For the given vertex {}, it seems aai-uri is not present so not getting related objects", - v.id().toString()); - } else { - LOGGER.info( - "It seems aai-uri is not present in vertex, so not getting related objects, for more info enable debug log"); - } - return relatedVertices; - } - - String aaiUri = aaiUriProperty.value().toString(); - - if (!obj.isTopLevel()) { - String[] uriList = convertIntrospectorToUriList(aaiUri, obj, loader); - List<Vertex> vertexChain = null; - // If the uriList is null then there is something wrong with converting the uri - // into a list of aai-uris so falling back to the old mechanism for finding parents - if (uriList == null) { - LOGGER.info( - "Falling back to the old mechanism due to unable to convert aai-uri to list of uris but this is not optimal"); - vertexChain = queryEngine.findParents(v); - } else { - vertexChain = queryEngine.findParents(uriList); - } - for (Vertex vertex : vertexChain) { - try { - final Introspector vertexObj = serializer.getVertexProperties(vertex); - relatedVertices.put(vertexObj.getObjectId(), vertexObj); - } catch (AAIUnknownObjectException e) { - LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned"); - } - } - } else { - try { - final Introspector vertexObj = serializer.getVertexProperties(v); - relatedVertices.put(vertexObj.getObjectId(), vertexObj); - } catch (AAIUnknownObjectException e) { - LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned"); - } - } - - return relatedVertices; - } - private Map<Vertex, Introspector> buildIntrospectorObjects(DBSerializer serializer, Iterable<Vertex> vertices) { Map<Vertex, Introspector> deleteObjectMap = new HashMap<>(); for (Vertex vertex : vertices) { try { - // deleteObjectMap.computeIfAbsent(vertex, s -> - // serializer.getLatestVersionView(vertex)); - Introspector deleteObj = serializer.getLatestVersionView(vertex); + Introspector deleteObj = serializer.getLatestVersionView(vertex, notificationDepth); deleteObjectMap.put(vertex, deleteObj); } catch (UnsupportedEncodingException | AAIException e) { LOGGER.warn("Unable to get Introspctor Objects, Just continue"); - continue; } } @@ -1170,7 +1029,6 @@ public class HttpEntry { } } catch (UnsupportedEncodingException e) { LOGGER.warn("Unable to get URIs, Just continue"); - continue; } } @@ -1186,15 +1044,13 @@ public class HttpEntry { for (Map.Entry<Vertex, Introspector> entry : introSpector.entrySet()) { try { HashMap<String, Introspector> relatedObjects = - this.getRelatedObjects(serializer, queryEngine, entry.getKey(), entry.getValue(), this.loader); + serializer.getRelatedObjects(queryEngine, entry.getKey(), entry.getValue(), this.loader); if (null != entry.getValue()) { relatedObjectsMap.put(entry.getValue().getObjectId(), relatedObjects); } - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException - | InstantiationException | NoSuchMethodException | UnsupportedEncodingException | AAIException - | URISyntaxException e) { + } catch (IllegalArgumentException | SecurityException + | UnsupportedEncodingException | AAIException e) { LOGGER.warn("Unable to get realted Objects, Just continue"); - continue; } } @@ -1208,10 +1064,8 @@ public class HttpEntry { Map<String, HashMap<String, Introspector>> deleteRelatedObjects, String basePath) { for (Map.Entry<Vertex, Introspector> entry : deleteObjects.entrySet()) { try { - String vertexObjectId = ""; - if (null != entry.getValue()) { - vertexObjectId = entry.getValue().getObjectId(); + String vertexObjectId = entry.getValue().getObjectId(); if (uriMap.containsKey(vertexObjectId) && deleteRelatedObjects.containsKey(vertexObjectId)) { notification.createNotificationEvent(transactionId, sourceOfTruth, status, @@ -1227,12 +1081,38 @@ public class HttpEntry { } public void setPaginationParameters(String resultIndex, String resultSize) { - if (resultIndex != null && resultIndex != "-1" && resultSize != null && resultSize != "-1") { + if (resultIndex != null && !"-1".equals(resultIndex) && resultSize != null && !"-1".equals(resultSize)) { this.setPaginationIndex(Integer.parseInt(resultIndex)); this.setPaginationBucket(Integer.parseInt(resultSize)); } } + public List<Object> getPaginatedVertexListForAggregateFormat(List<Object> aggregateVertexList) throws AAIException { + List<Object> finalList = new Vector<>(); + if (this.isPaginated()) { + if (aggregateVertexList != null && !aggregateVertexList.isEmpty()) { + int listSize = aggregateVertexList.size(); + if (listSize == 1) { + List<Object> vertexList = (List<Object>) aggregateVertexList.get(0); + this.setTotalsForPaging(vertexList.size(), this.getPaginationBucket()); + int startIndex = (this.getPaginationIndex() - 1) * this.getPaginationBucket(); + int endIndex = Math.min((this.getPaginationBucket() * this.getPaginationIndex()), vertexList.size()); + if (startIndex > endIndex) { + throw new AAIException("AAI_6150", + " ResultIndex is not appropriate for the result set, Needs to be <= " + endIndex); + } + finalList.add(new ArrayList<Object>()); + for (int i = startIndex; i < endIndex; i++) { + ((ArrayList<Object>) finalList.get(0)).add(((ArrayList<Object>) aggregateVertexList.get(0)).get(i)); + } + return finalList; + } + } + } + // If the list size is greater than 1 or if pagination is not needed, return the original list. + return aggregateVertexList; + } + public List<Object> getPaginatedVertexList(List<Object> vertexList) throws AAIException { List<Object> vertices; if (this.isPaginated()) { diff --git a/aai-core/src/main/java/org/onap/aai/rest/ueb/NotificationEvent.java b/aai-core/src/main/java/org/onap/aai/rest/ueb/NotificationEvent.java index 61beb8d0..14e554cd 100644 --- a/aai-core/src/main/java/org/onap/aai/rest/ueb/NotificationEvent.java +++ b/aai-core/src/main/java/org/onap/aai/rest/ueb/NotificationEvent.java @@ -63,10 +63,13 @@ public class NotificationEvent { StoreNotificationEvent sne = new StoreNotificationEvent(transactionId, sourceOfTruth); - sne.storeEvent(loader, eventHeader, obj); + sne.storeEventAndSendToJms(loader, eventHeader, obj); } + public String getNotificationEvent() throws AAIException { + return new StoreNotificationEvent(transactionId, sourceOfTruth).storeEventOnly(loader, eventHeader, obj); + } /** * Gets the notification version. * diff --git a/aai-core/src/main/java/org/onap/aai/rest/ueb/UEBNotification.java b/aai-core/src/main/java/org/onap/aai/rest/ueb/UEBNotification.java index b189c050..28a644a9 100644 --- a/aai-core/src/main/java/org/onap/aai/rest/ueb/UEBNotification.java +++ b/aai-core/src/main/java/org/onap/aai/rest/ueb/UEBNotification.java @@ -20,22 +20,13 @@ package org.onap.aai.rest.ueb; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import javax.ws.rs.core.Response.Status; - -import org.onap.aai.config.SpringContextAware; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.LoaderFactory; +import org.onap.aai.introspection.ModelType; import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.onap.aai.introspection.exceptions.AAIUnmarshallingException; import org.onap.aai.logging.LogFormatTools; @@ -43,15 +34,20 @@ import org.onap.aai.parsers.uri.URIToObject; import org.onap.aai.setup.SchemaVersion; import org.onap.aai.setup.SchemaVersions; +import javax.ws.rs.core.Response.Status; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.*; + /** * The Class UEBNotification. */ public class UEBNotification { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(UEBNotification.class); + private static final Logger LOGGER = LoggerFactory.getLogger(UEBNotification.class); private Loader currentVersionLoader = null; - protected List<NotificationEvent> events = null; + protected Map<String, NotificationEvent> events = null; private SchemaVersion notificationVersion = null; /** @@ -60,13 +56,27 @@ public class UEBNotification { * @param loader the loader */ public UEBNotification(Loader loader, LoaderFactory loaderFactory, SchemaVersions schemaVersions) { - events = new ArrayList<>(); + events = new LinkedHashMap<>(); SchemaVersion defaultVersion = schemaVersions.getDefaultVersion(); currentVersionLoader = loaderFactory.createLoaderForVersion(loader.getModelType(), defaultVersion); notificationVersion = defaultVersion; } /** + * Instantiates a new UEB notification. + * + * @param modelType - Model type + * @param loaderFactory - the loader factory + * @param schemaVersions the schema versions bean + */ + public UEBNotification(ModelType modelType, LoaderFactory loaderFactory, SchemaVersions schemaVersions) { + events = new LinkedHashMap<>(); + SchemaVersion defaultVersion = schemaVersions.getDefaultVersion(); + currentVersionLoader = loaderFactory.createLoaderForVersion(modelType, defaultVersion); + notificationVersion = defaultVersion; + } + + /** * Creates the notification event. * * @param transactionId the X-TransactionId @@ -97,7 +107,6 @@ public class UEBNotification { Introspector eventHeader = currentVersionLoader.introspectorFromName("notification-event-header"); URIToObject parser = new URIToObject(currentVersionLoader, uri, relatedObjects); - String entityLink = ""; if ((basePath != null) && (!basePath.isEmpty())) { if (!(basePath.startsWith("/"))) { basePath = "/" + basePath; @@ -113,10 +122,12 @@ public class UEBNotification { } } - if (uri.toString().startsWith("/")) { - entityLink = basePath + notificationVersion + uri; + String uriStr = getUri(uri.toString(), basePath); + String entityLink; + if (uriStr.startsWith("/")) { + entityLink = basePath + notificationVersion + uriStr; } else { - entityLink = basePath + notificationVersion + "/" + uri; + entityLink = basePath + notificationVersion + "/" + uriStr; } eventHeader.setValue("entity-link", entityLink); @@ -166,7 +177,7 @@ public class UEBNotification { } final NotificationEvent event = new NotificationEvent(currentVersionLoader, eventHeader, eventObject, transactionId, sourceOfTruth); - events.add(event); + events.put(uri.toString(), event); } catch (AAIUnknownObjectException e) { throw new RuntimeException("Fatal error - notification-event-header object not found!"); } catch (AAIUnmarshallingException e) { @@ -181,14 +192,41 @@ public class UEBNotification { * @throws AAIException the AAI exception */ public void triggerEvents() throws AAIException { - for (NotificationEvent event : events) { + for (NotificationEvent event : events.values()) { event.trigger(); } - events.clear(); + clearEvents(); } public List<NotificationEvent> getEvents() { + return new ArrayList<>(this.events.values()); + } + public Map<String, NotificationEvent> getEventsMap() { return this.events; } + private String getUri(String uri, String basePath) { + if (uri == null || uri.isEmpty()) { + return uri; + } else if (uri.charAt(0) != '/') { + uri = '/' + uri; + } + + if ((basePath != null) && (!basePath.isEmpty())) { + if (!(basePath.startsWith("/"))) { + basePath = "/" + basePath; + } + if (!(basePath.endsWith("/"))) { + basePath = basePath + "/"; + } + } + + LOGGER.trace("Notification header uri base path:'{}', uri:'{}'", basePath, uri); + + return uri.replaceAll("^" + basePath + "v\\d+", ""); + } + + public void clearEvents() { + events.clear(); + } } diff --git a/aai-core/src/main/java/org/onap/aai/restcore/RESTAPI.java b/aai-core/src/main/java/org/onap/aai/restcore/RESTAPI.java index ae102a83..2b1256ba 100644 --- a/aai-core/src/main/java/org/onap/aai/restcore/RESTAPI.java +++ b/aai-core/src/main/java/org/onap/aai/restcore/RESTAPI.java @@ -20,64 +20,47 @@ package org.onap.aai.restcore; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; -import com.google.common.base.Joiner; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.onap.aai.db.props.AAIProperties; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; -import org.onap.aai.introspection.tools.CreateUUID; -import org.onap.aai.introspection.tools.DefaultFields; -import org.onap.aai.introspection.tools.InjectKeysFromURI; -import org.onap.aai.introspection.tools.IntrospectorValidator; -import org.onap.aai.introspection.tools.Issue; -import org.onap.aai.introspection.tools.RemoveNonVisibleProperty; +import org.onap.aai.introspection.tools.*; import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.logging.LoggingContext; import org.onap.aai.util.AAIConfig; import org.onap.aai.util.FormatDate; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.*; + /** * Base class for AAI REST API classes. * Provides method to validate header information * TODO should authenticate caller and authorize them for the API they are calling * TODO should store the transaction * - * + * */ public class RESTAPI { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(RESTAPI.class); - - protected final String COMPONENT = "aairest"; + private static final Logger LOGGER = LoggerFactory.getLogger(RESTAPI.class); /** * The Enum Action. */ public enum Action { GET, PUT, POST, DELETE - }; + } /** * Gets the from app id. @@ -101,8 +84,6 @@ public class RESTAPI { throw new AAIException("AAI_4009"); } - LoggingContext.partnerName(fromAppId); - return fromAppId; } @@ -128,8 +109,6 @@ public class RESTAPI { throw new AAIException("AAI_4010"); } - LoggingContext.requestId(transId); - return transId; } @@ -173,7 +152,7 @@ public class RESTAPI { int depth = AAIProperties.MAXIMUM_DEPTH; // default if (depthParam != null && depthParam.length() > 0 && !depthParam.equals("all")) { try { - depth = Integer.valueOf(depthParam); + depth = Integer.parseInt(depthParam); } catch (Exception e) { throw new AAIException("AAI_4016"); } @@ -192,9 +171,9 @@ public class RESTAPI { */ protected Response consumerExceptionResponseGenerator(HttpHeaders headers, UriInfo info, HttpMethod templateAction, AAIException e) { - ArrayList<String> templateVars = new ArrayList<String>(); + ArrayList<String> templateVars = new ArrayList<>(); templateVars.add(templateAction.toString()); // GET, PUT, etc - templateVars.add(info.getPath().toString()); + templateVars.add(info.getPath()); templateVars.addAll(e.getTemplateVars()); ErrorLogHelper.logException(e); @@ -236,7 +215,7 @@ public class RESTAPI { messages.add(issue.getDetail()); } } - String errors = Joiner.on(",").join(messages); + String errors = String.join(",", messages); throw new AAIException("AAI_3000", errors); } // check that key in payload and key in request uri are the same @@ -249,22 +228,6 @@ public class RESTAPI { } } - protected DBConnectionType determineConnectionType(String fromAppId, String realTime) throws AAIException { - if (fromAppId == null) { - throw new AAIException("AAI_4009", "X-FromAppId is not set"); - } - - DBConnectionType type = DBConnectionType.REALTIME; - boolean isRealTimeClient = AAIConfig.get("aai.realtime.clients", "").contains(fromAppId); - if (isRealTimeClient || realTime != null) { - type = DBConnectionType.REALTIME; - } else { - type = DBConnectionType.CACHED; - } - - return type; - } - /** * Gets the input media type. * @@ -272,10 +235,7 @@ public class RESTAPI { * @return the input media type */ protected String getInputMediaType(MediaType mediaType) { - String result = mediaType.getType() + "/" + mediaType.getSubtype(); - - return result; - + return mediaType.getType() + "/" + mediaType.getSubtype(); } /** @@ -288,25 +248,23 @@ public class RESTAPI { * @throws AAIException */ - public int getTimeoutLimit(String sot, String appTimeouts, String defaultTimeout) throws AAIException { + public int getTimeoutLimit(String sot, String appTimeouts, String defaultTimeout) { String[] ignoreAppIds = (appTimeouts).split("\\|"); int appLimit = Integer.parseInt(defaultTimeout); - final Map<String, Integer> m = new HashMap<String, Integer>(); - if (ignoreAppIds != null) { - for (int i = 0; i < ignoreAppIds.length; i++) { - String[] vals = ignoreAppIds[i].split(","); - m.put(vals[0], Integer.parseInt(vals[1])); - } - if (m.get(sot) != null) { - appLimit = m.get(sot); - } + final Map<String, Integer> m = new HashMap<>(); + for (int i = 0; i < ignoreAppIds.length; i++) { + String[] vals = ignoreAppIds[i].split(","); + m.put(vals[0], Integer.parseInt(vals[1])); + } + if (m.get(sot) != null) { + appLimit = m.get(sot); } return appLimit; } /** * Returns whether time out is enabled - * + * * @param sot * @param isEnabled * @param appTimeouts @@ -314,9 +272,8 @@ public class RESTAPI { * @return boolean of whether the timeout is enabled * @throws AAIException */ - public boolean isTimeoutEnabled(String sot, String isEnabled, String appTimeouts, String defaultTimeout) - throws AAIException { - Boolean isTimeoutEnabled = Boolean.parseBoolean(isEnabled); + public boolean isTimeoutEnabled(String sot, String isEnabled, String appTimeouts, String defaultTimeout) { + boolean isTimeoutEnabled = Boolean.parseBoolean(isEnabled); int ata = -1; if (isTimeoutEnabled) { ata = getTimeoutLimit(sot, appTimeouts, defaultTimeout); @@ -326,7 +283,7 @@ public class RESTAPI { /** * Executes the process thread and watches the future for the timeout - * + * * @param handler * @param sourceOfTruth * @param appTimeoutLimit @@ -358,7 +315,7 @@ public class RESTAPI { /** * runner sets up the timer logic and invokes it - * + * * @param toe * @param tba * @param tdl diff --git a/aai-core/src/main/java/org/onap/aai/restcore/search/AAIAbstractGroovyShell.java b/aai-core/src/main/java/org/onap/aai/restcore/search/AAIAbstractGroovyShell.java index b521a617..13f3f05e 100644 --- a/aai-core/src/main/java/org/onap/aai/restcore/search/AAIAbstractGroovyShell.java +++ b/aai-core/src/main/java/org/onap/aai/restcore/search/AAIAbstractGroovyShell.java @@ -28,13 +28,20 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.expr.ClassExpression; import org.codehaus.groovy.ast.expr.PropertyExpression; import org.codehaus.groovy.control.CompilerConfiguration; import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer; import org.codehaus.groovy.control.customizers.ImportCustomizer; +import org.onap.aai.config.SpringContextAware; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.LoaderFactory; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.setup.SchemaVersions; public abstract class AAIAbstractGroovyShell { @@ -76,4 +83,20 @@ public abstract class AAIAbstractGroovyShell { * @return result of graph traversal */ public abstract GraphTraversal<?, ?> executeTraversal(String traversal, Map<String, Object> params); + + /** + * + * @param engine + * @param traversal + * @param params + * @return result of graph traversal + */ + public abstract String executeTraversal(TransactionalGraphEngine engine, String traversal, + Map<String, Object> params, QueryStyle style, GraphTraversalSource source); + + protected Loader getLoader(){ + SchemaVersions schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); + return SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(ModelType.MOXY, + schemaVersions.getDefaultVersion()); + } } diff --git a/aai-core/src/main/java/org/onap/aai/restcore/search/GremlinGroovyShell.java b/aai-core/src/main/java/org/onap/aai/restcore/search/GremlinGroovyShell.java index 2b39af43..85e47223 100644 --- a/aai-core/src/main/java/org/onap/aai/restcore/search/GremlinGroovyShell.java +++ b/aai-core/src/main/java/org/onap/aai/restcore/search/GremlinGroovyShell.java @@ -26,6 +26,8 @@ import groovy.lang.Script; import java.util.Map; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; /** @@ -57,4 +59,9 @@ public class GremlinGroovyShell extends AAIAbstractGroovyShell { public String executeTraversal(TransactionalGraphEngine engine, String traversal, Map<String, Object> params) { throw new UnsupportedOperationException(); } + + @Override + public String executeTraversal(TransactionalGraphEngine engine, String traversal, Map<String, Object> params, QueryStyle style, GraphTraversalSource source) { + throw new UnsupportedOperationException(); + } } diff --git a/aai-core/src/main/java/org/onap/aai/restcore/search/GroovyQueryBuilder.java b/aai-core/src/main/java/org/onap/aai/restcore/search/GroovyQueryBuilder.java index ba6acb66..fbaa7465 100644 --- a/aai-core/src/main/java/org/onap/aai/restcore/search/GroovyQueryBuilder.java +++ b/aai-core/src/main/java/org/onap/aai/restcore/search/GroovyQueryBuilder.java @@ -26,6 +26,7 @@ import groovy.lang.Script; import java.util.Map; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.onap.aai.config.SpringContextAware; import org.onap.aai.introspection.Loader; @@ -53,11 +54,8 @@ public class GroovyQueryBuilder extends AAIAbstractGroovyShell { @Override public String executeTraversal(TransactionalGraphEngine engine, String traversal, Map<String, Object> params) { QueryBuilder<Vertex> builder = engine.getQueryBuilder(QueryStyle.GREMLIN_TRAVERSAL); - SchemaVersions schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); - Loader loader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(ModelType.MOXY, - schemaVersions.getDefaultVersion()); - builder.changeLoader(loader); + builder.changeLoader(getLoader()); Binding binding = new Binding(params); binding.setVariable("builder", builder); Script script = shell.parse(traversal); @@ -74,4 +72,17 @@ public class GroovyQueryBuilder extends AAIAbstractGroovyShell { public GraphTraversal<?, ?> executeTraversal(String traversal, Map<String, Object> params) { throw new UnsupportedOperationException(); } + + @Override + public String executeTraversal(TransactionalGraphEngine engine, String traversal, Map<String, Object> params, QueryStyle style, GraphTraversalSource traversalSource) { + QueryBuilder<Vertex> builder = engine.getQueryBuilder(style, traversalSource); + builder.changeLoader(getLoader()); + Binding binding = new Binding(params); + binding.setVariable("builder", builder); + Script script = shell.parse(traversal); + script.setBinding(binding); + script.run(); + + return builder.getQuery(); + } } diff --git a/aai-core/src/main/java/org/onap/aai/restcore/util/URITools.java b/aai-core/src/main/java/org/onap/aai/restcore/util/URITools.java index c3211fbe..a757d3db 100644 --- a/aai-core/src/main/java/org/onap/aai/restcore/util/URITools.java +++ b/aai-core/src/main/java/org/onap/aai/restcore/util/URITools.java @@ -47,22 +47,26 @@ public class URITools { MultivaluedMap<String, String> result = new MultivaluedHashMap<>(); String queryParams = uri.getRawQuery(); if (queryParams != null) { - String[] sections = queryParams.split("&"); - String[] query = null; - String key, value = ""; - for (String section : sections) { - query = section.split("="); - key = UriUtils.decode(query[0], "UTF-8"); - if (query[1] != null) { - query[1] = query[1].replaceAll("\\+", "%20"); + try { + String[] sections = queryParams.split("&"); + String[] query = null; + String key, value = ""; + for (String section : sections) { + query = section.split("="); + key = UriUtils.decode(query[0], "UTF-8"); + if (query[1] != null) { + query[1] = query[1].replaceAll("\\+", "%20"); + } + value = UriUtils.decode(query[1], "UTF-8"); + if (result.containsKey(key)) { + result.add(key, value); + } else { + result.putSingle(key, value); + } } - value = UriUtils.decode(query[1], "UTF-8"); - if (result.containsKey(key)) { - result.add(key, value); - } else { - result.putSingle(key, value); - } - } + } catch (UnsupportedEncodingException e) { + + } } return result; diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java b/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java index 3996c07d..14fb8cb5 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,29 +17,13 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - package org.onap.aai.serialization.db; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.CaseFormat; - -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.ws.rs.core.UriBuilder; - -import org.apache.commons.collections.IteratorUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.structure.Direction; @@ -47,14 +31,13 @@ import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.janusgraph.core.SchemaViolationException; -import org.javatuples.Triplet; +import org.javatuples.Pair; import org.onap.aai.concurrent.AaiCallable; import org.onap.aai.config.SpringContextAware; import org.onap.aai.db.props.AAIProperties; import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.edges.EdgeRule; import org.onap.aai.edges.EdgeRuleQuery; -import org.onap.aai.edges.TypeAlphabetizer; import org.onap.aai.edges.enums.AAIDirection; import org.onap.aai.edges.enums.EdgeField; import org.onap.aai.edges.enums.EdgeProperty; @@ -67,10 +50,11 @@ import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.onap.aai.introspection.sideeffect.*; import org.onap.aai.logging.ErrorLogHelper; import org.onap.aai.logging.LogFormatTools; -import org.onap.aai.logging.LoggingContext; import org.onap.aai.logging.StopWatch; import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.parsers.relationship.RelationshipToURI; import org.onap.aai.parsers.uri.URIParser; +import org.onap.aai.parsers.uri.URIToObject; import org.onap.aai.parsers.uri.URIToRelationshipObject; import org.onap.aai.query.builder.QueryBuilder; import org.onap.aai.schema.enums.ObjectMetadata; @@ -83,16 +67,32 @@ import org.onap.aai.setup.SchemaVersion; import org.onap.aai.setup.SchemaVersions; import org.onap.aai.util.AAIConfig; import org.onap.aai.util.AAIConstants; +import org.onap.aai.util.delta.*; import org.onap.aai.workarounds.NamingExceptions; import org.springframework.context.ApplicationContext; -public class DBSerializer { - - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DBSerializer.class); +import javax.ws.rs.core.UriBuilder; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.regex.Matcher; +import java.util.regex.Pattern; - private static final String IMPLICIT_DELETE = "Implicit DELETE"; +public class DBSerializer { - private static final String MISSING_REQUIRED_NODE_PROPERTY = "Vertex missing required aai-node-type property"; + private static final Logger LOGGER = LoggerFactory.getLogger(DBSerializer.class); + private static final String RELATIONSHIP_LABEL = "relationship-label"; + private static final String RELATIONSHIP = "relationship"; + public static final String FALSE = "false"; + public static final String AAI_6145 = "AAI_6145"; + public static final String AAI_6129 = "AAI_6129"; private final TransactionalGraphEngine engine; private final String sourceOfTruth; @@ -108,6 +108,12 @@ public class DBSerializer { private SchemaVersions schemaVersions; private Set<String> namedPropNodes; + private Map<String, ObjectDelta> objectDeltas = new LinkedHashMap<>(); + private Map<Vertex, Boolean> updatedVertexes = new LinkedHashMap<>(); + private Set<Vertex> edgeVertexes = new LinkedHashSet<>(); + private Map<String, Pair<Introspector, LinkedHashMap<String, Introspector>>> impliedDeleteUriObjectPair = new LinkedHashMap<>(); + private int notificationDepth; + private boolean isDeltaEventsEnabled; /** * Instantiates a new DB serializer. @@ -124,15 +130,39 @@ public class DBSerializer { this.sourceOfTruth = sourceOfTruth; this.introspectionType = introspectionType; this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); - SchemaVersion LATEST = schemaVersions.getDefaultVersion(); + SchemaVersion latestVersion = schemaVersions.getDefaultVersion(); this.latestLoader = - SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, LATEST); + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, latestVersion); this.version = version; this.loader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, version); this.namedPropNodes = this.latestLoader.getNamedPropNodes(); this.baseURL = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE); this.currentTimeMillis = System.currentTimeMillis(); + // If creating the DBSerializer the old way then set the notification depth to maximum + this.notificationDepth = AAIProperties.MAXIMUM_DEPTH; + initBeans(); + } + + public DBSerializer(SchemaVersion version, + TransactionalGraphEngine engine, + ModelType introspectionType, + String sourceOfTruth, + int notificationDepth) throws AAIException { + this.engine = engine; + this.sourceOfTruth = sourceOfTruth; + this.introspectionType = introspectionType; + this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); + SchemaVersion latestVersion = schemaVersions.getDefaultVersion(); + this.latestLoader = + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, latestVersion); + this.version = version; + this.loader = + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, version); + this.namedPropNodes = this.latestLoader.getNamedPropNodes(); + this.baseURL = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE); + this.currentTimeMillis = System.currentTimeMillis(); + this.notificationDepth = notificationDepth; initBeans(); } @@ -143,10 +173,7 @@ public class DBSerializer { setEdgeIngestor(ei); EdgeSerializer es = ctx.getBean(EdgeSerializer.class); setEdgeSerializer(es); - } - - private void backupESInit() { - setEdgeSerializer(new EdgeSerializer(this.edgeRules)); + isDeltaEventsEnabled = Boolean.parseBoolean(SpringContextAware.getApplicationContext().getEnvironment().getProperty("delta.events.enabled", FALSE)); } public void setEdgeSerializer(EdgeSerializer edgeSer) { @@ -165,31 +192,95 @@ public class DBSerializer { return this.edgeRules; } + public Map<Vertex, Boolean> getUpdatedVertexes() { + return updatedVertexes; + } + + public Map<String, Pair<Introspector, LinkedHashMap<String, Introspector>>> getImpliedDeleteUriObjectPair(){ + return impliedDeleteUriObjectPair; + } + /** * Touch standard vertex properties. - * - * @param v the v + * @param v the v * @param isNewVertex the is new vertex */ public void touchStandardVertexProperties(Vertex v, boolean isNewVertex) { String timeNowInSec = Long.toString(currentTimeMillis); - if (isNewVertex) { + String uuid = UUID.randomUUID().toString(); v.property(AAIProperties.SOURCE_OF_TRUTH, this.sourceOfTruth); - v.property(AAIProperties.CREATED_TS, timeNowInSec); - v.property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()); + v.property(AAIProperties.CREATED_TS, currentTimeMillis); + v.property(AAIProperties.AAI_UUID, uuid); + v.property(AAIProperties.RESOURCE_VERSION, timeNowInSec); + v.property(AAIProperties.LAST_MOD_TS, currentTimeMillis); + v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, this.sourceOfTruth); + } else { + if(isDeltaEventsEnabled) { + standardVertexPropsDeltas(v, timeNowInSec); + } + v.property(AAIProperties.RESOURCE_VERSION, timeNowInSec); + v.property(AAIProperties.LAST_MOD_TS, currentTimeMillis); + v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, this.sourceOfTruth); } - v.property(AAIProperties.RESOURCE_VERSION, timeNowInSec); - v.property(AAIProperties.LAST_MOD_TS, timeNowInSec); - v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, this.sourceOfTruth); + } + private void standardVertexPropsDeltas(Vertex v, String timeNowInSec) { + String uri = v.property(AAIProperties.AAI_URI).value().toString(); + long createdTs = (Long) v.property(AAIProperties.CREATED_TS).value(); + DeltaAction objDeltaAction = createdTs == currentTimeMillis ? DeltaAction.CREATE : DeltaAction.UPDATE; + if (getObjectDeltas().containsKey(uri)) { + getObjectDeltas().get(uri).setAction(objDeltaAction); + } + + addPropDelta(uri, AAIProperties.AAI_UUID, PropertyDeltaFactory.getDelta(DeltaAction.STATIC, v.property(AAIProperties.AAI_UUID).value()), objDeltaAction); + addPropDelta(uri, AAIProperties.NODE_TYPE, PropertyDeltaFactory.getDelta(DeltaAction.STATIC, v.property(AAIProperties.NODE_TYPE).value()), objDeltaAction); + addPropDelta(uri, AAIProperties.SOURCE_OF_TRUTH, PropertyDeltaFactory.getDelta(DeltaAction.STATIC, v.property(AAIProperties.SOURCE_OF_TRUTH).value()), objDeltaAction); + addPropDelta(uri, AAIProperties.CREATED_TS, PropertyDeltaFactory.getDelta(DeltaAction.STATIC, v.property(AAIProperties.CREATED_TS).value()), objDeltaAction); + + if (objDeltaAction.equals(DeltaAction.UPDATE)) { + addPropDelta( + uri, + AAIProperties.RESOURCE_VERSION, + PropertyDeltaFactory.getDelta(objDeltaAction, timeNowInSec, v.property(AAIProperties.RESOURCE_VERSION).value()), + objDeltaAction + ); + addPropDelta( + uri, + AAIProperties.LAST_MOD_TS, + PropertyDeltaFactory.getDelta(objDeltaAction, currentTimeMillis, v.property(AAIProperties.LAST_MOD_TS).value()), + objDeltaAction + ); + addPropDelta( + uri, + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, + PropertyDeltaFactory.getDelta(objDeltaAction, this.sourceOfTruth, v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value()), + objDeltaAction + ); + } else { + addPropDelta(uri, AAIProperties.RESOURCE_VERSION, PropertyDeltaFactory.getDelta(objDeltaAction, v.property(AAIProperties.RESOURCE_VERSION).value()), objDeltaAction); + addPropDelta(uri, AAIProperties.LAST_MOD_TS, PropertyDeltaFactory.getDelta(objDeltaAction, v.property(AAIProperties.LAST_MOD_TS).value()), objDeltaAction); + addPropDelta(uri, AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, PropertyDeltaFactory.getDelta(objDeltaAction, v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value()), objDeltaAction); + } } - private void touchStandardVertexProperties(String nodeType, Vertex v, boolean isNewVertex) { + public Map<String, ObjectDelta> getObjectDeltas() {return objectDeltas;} + + private void addPropDelta(String uri, String prop, PropertyDelta delta, DeltaAction objDeltaAction) { + ObjectDelta objectDelta = this.objectDeltas.getOrDefault(uri, new ObjectDelta(uri, objDeltaAction, this.sourceOfTruth, this.currentTimeMillis)); + objectDelta.addPropertyDelta(prop, delta); + objectDeltas.put(uri, objectDelta); + } + private void addRelationshipDelta(String uri, RelationshipDelta delta, DeltaAction objDeltaAction) { + ObjectDelta objectDelta = this.objectDeltas.getOrDefault(uri, new ObjectDelta(uri, objDeltaAction, this.sourceOfTruth, this.currentTimeMillis)); + objectDelta.addRelationshipDelta(delta); + objectDeltas.put(uri, objectDelta); + } + + private void touchStandardVertexProperties(String nodeType, Vertex v, boolean isNewVertex) { v.property(AAIProperties.NODE_TYPE, nodeType); touchStandardVertexProperties(v, isNewVertex); - } /** @@ -197,14 +288,12 @@ public class DBSerializer { * * @param wrappedObject the wrapped object * @return the vertex - * @throws UnsupportedEncodingException the unsupported encoding exception - * @throws AAIException the AAI exception */ public Vertex createNewVertex(Introspector wrappedObject) { Vertex v; try { StopWatch.conditionalStart(); - v = this.engine.tx().addVertex(); + v = this.engine.tx().addVertex(wrappedObject.getDbName()); touchStandardVertexProperties(wrappedObject.getDbName(), v, true); } finally { dbTimeMsecs += StopWatch.stopIfStarted(); @@ -227,7 +316,7 @@ public class DBSerializer { if (className.lastIndexOf('.') == -1) { return className; } - returnValue = className.substring(className.lastIndexOf('.') + 1, className.length()); + returnValue = className.substring(className.lastIndexOf('.') + 1); return returnValue; } @@ -240,15 +329,9 @@ public class DBSerializer { * @param uriQuery the uri query * @param identifier the identifier * @throws SecurityException the security exception - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws InstantiationException the instantiation exception - * @throws InterruptedException the interrupted exception - * @throws NoSuchMethodException the no such method exception * @throws AAIException the AAI exception * @throws UnsupportedEncodingException the unsupported encoding exception - * @throws AAIUnknownObjectException */ public void serializeToDb(Introspector obj, Vertex v, QueryParser uriQuery, String identifier, String requestContext) throws AAIException, UnsupportedEncodingException { @@ -284,8 +367,6 @@ public class DBSerializer { if (isTopLevel) { addUriIfNeeded(v, obj.getURI()); } - - processObject(obj, v, requestContext); if (!isTopLevel) { URI uri = this.getURIForVertex(v); URIParser parser = new URIParser(this.loader, uri); @@ -293,6 +374,7 @@ public class DBSerializer { addUriIfNeeded(v, uri.toString()); } } + processObject(obj, v, requestContext); } catch (SchemaViolationException e) { throw new AAIException("AAI_6117", e); } finally { @@ -302,7 +384,7 @@ public class DBSerializer { private void addUriIfNeeded(Vertex v, String uri) { VertexProperty<String> uriProp = v.property(AAIProperties.AAI_URI); - if (!uriProp.isPresent() || (uriProp.isPresent() && !uriProp.value().equals(uri))) { + if (!uriProp.isPresent() || !uriProp.value().equals(uri)) { v.property(AAIProperties.AAI_URI, uri); } } @@ -310,43 +392,42 @@ public class DBSerializer { /** * Process object. * - * @param <T> the generic type * @param obj the obj * @param v the v * @return the list - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws InstantiationException the instantiation exception - * @throws NoSuchMethodException the no such method exception * @throws SecurityException the security exception * @throws AAIException the AAI exception * @throws UnsupportedEncodingException the unsupported encoding exception - * @throws AAIUnknownObjectException */ /* * Helper method for reflectToDb * Handles all the property setting */ - private <T> List<Vertex> processObject(Introspector obj, Vertex v, String requestContext) + private List<Vertex> processObject(Introspector obj, Vertex v, String requestContext) throws UnsupportedEncodingException, AAIException { Set<String> properties = new LinkedHashSet<>(obj.getProperties()); properties.remove(AAIProperties.RESOURCE_VERSION); List<Vertex> dependentVertexes = new ArrayList<>(); List<Vertex> processedVertexes = new ArrayList<>(); - boolean isComplexType = false; - boolean isListType = false; - if (!obj.isContainer()) { - this.touchStandardVertexProperties(v, false); + + boolean isComplexType ; + boolean isListType; + + // If the notification depth is set to maximum + // this is the behavior of the expected clients + if(notificationDepth == AAIProperties.MAXIMUM_DEPTH) { + if (!obj.isContainer()) { + this.touchStandardVertexProperties(v, false); + } } this.executePreSideEffects(obj, v); for (String property : properties) { - Object value = null; final String propertyType; propertyType = obj.getType(property); isComplexType = obj.isComplexType(property); isListType = obj.isListType(property); - value = obj.getValue(property); + Object value = obj.getValue(property); if (!(isComplexType || isListType)) { boolean canModify = this.canModify(obj, property, requestContext); @@ -362,16 +443,28 @@ public class DBSerializer { // they are populated dynamically on GETs continue; } + Object oldValue = v.property(dbProperty).orElse(null); + String uri = getURIForVertex(v).toString(); if (value != null) { - if (!value.equals(v.property(dbProperty).orElse(null))) { + if (!value.equals(oldValue)) { if (propertyType.toLowerCase().contains(".long")) { v.property(dbProperty, new Integer(((Long) value).toString())); } else { v.property(dbProperty, value); } + if (isDeltaEventsEnabled) { + createDeltaProperty(uri, value, dbProperty, oldValue); + } + this.updatedVertexes.putIfAbsent(v, false); } } else { - v.property(dbProperty).remove(); + if (oldValue != null) { + v.property(dbProperty).remove(); + if (isDeltaEventsEnabled) { + addPropDelta(uri, dbProperty, PropertyDeltaFactory.getDelta(DeltaAction.DELETE, oldValue), DeltaAction.UPDATE); + } + this.updatedVertexes.putIfAbsent(v, false); + } } } } else if (isListType) { @@ -386,7 +479,21 @@ public class DBSerializer { } } else { // simple list case - engine.setListProperty(v, property, list); + if (isDeltaEventsEnabled) { + String uri = getURIForVertex(v).toString(); + List<Object> oldVal = engine.getListProperty(v, property); + engine.setListProperty(v, property, list); + if (list == null || list.isEmpty()) { // property delete scenario, there is no new value + if (oldVal != null && !oldVal.isEmpty()) { // and there is an old value + addPropDelta(uri, property, PropertyDeltaFactory.getDelta(DeltaAction.DELETE, oldVal), DeltaAction.UPDATE); + } + } else { // is either a create or update and is handled by the called method + createDeltaProperty(uri, list, property, oldVal); + } + } else { + engine.setListProperty(v, property, list); + } + this.updatedVertexes.putIfAbsent(v, false); } } else { // method.getReturnType() is not 'simple' then create a vertex and edge recursively returning an edge @@ -427,62 +534,192 @@ public class DBSerializer { } this.writeThroughDefaults(v, obj); /* handle those vertexes not touched */ - for (Vertex toBeRemoved : processedVertexes) { - dependentVertexes.remove(toBeRemoved); + for (Vertex toBeKept : processedVertexes) { + dependentVertexes.remove(toBeKept); } - // If the dependent vertices are not empty, then with - // the current behaviour, it should remove the vertices implicitly - // We are updating the code to properly log which call - // is doing this so the SE can work with the clients making the call to - // tell them not to call this API and can hopefully deprecate this - // functionality in the future releases - if (!dependentVertexes.isEmpty()) { + ImpliedDelete impliedDelete = new ImpliedDelete(engine, this); + List<Vertex> impliedDeleteVertices = impliedDelete.execute(v.id(), sourceOfTruth, obj.getName(), dependentVertexes); + + if(notificationDepth == AAIProperties.MINIMUM_DEPTH){ + for(Vertex curVertex : impliedDeleteVertices){ + if(!curVertex.property("aai-uri").isPresent()){ + LOGGER.debug("Encountered an vertex {} with missing aai-uri", curVertex.id()); + continue; + } + String curAaiUri = curVertex.<String>property(AAIProperties.AAI_URI).value(); + Introspector curObj = this.getLatestVersionView(curVertex, notificationDepth); - LoggingContext.responseDescription(IMPLICIT_DELETE); + LinkedHashMap<String, Introspector> curObjRelated = new LinkedHashMap<>(); - // Find all the deletable vertices from the dependent vertices that should be deleted - // So for each of the following dependent vertices, - // we will use the edge properties and do the cascade delete - List<Vertex> impliedDeleteVertices = this.engine.getQueryEngine().findDeletable(dependentVertexes); - int impliedDeleteCount = impliedDeleteVertices.size(); + if(!curObj.isTopLevel()){ + curObjRelated.putAll(this.getRelatedObjects(engine.getQueryEngine(), curVertex, curObj, this.loader)); + } - LOGGER.warn( - "For the vertex with id {}, doing an implicit delete on update will delete total of {} vertexes", - v.id(), impliedDeleteCount); + if(!impliedDeleteUriObjectPair.containsKey(curAaiUri)){ + impliedDeleteUriObjectPair.put(curAaiUri, new Pair<>(curObj, curObjRelated)); + } + } + } - String impliedDeleteLogEnabled = AAIConfig.get(AAIConstants.AAI_IMPLIED_DELETE_LOG_ENABLED, "true"); + impliedDelete.delete(impliedDeleteVertices); - int impliedDeleteLogLimit = AAIConfig.getInt(AAIConstants.AAI_IMPLIED_DELETE_LOG_LIMIT, "-1"); + // touch svp using vertex list for what changed + // if the notification depth is zero + if(notificationDepth == AAIProperties.MINIMUM_DEPTH){ + this.updatedVertexes.entrySet().stream() + .filter(e -> !e.getValue()) + .filter(e -> !edgeVertexes.contains(e.getKey())) + .forEach(e -> { + this.touchStandardVertexProperties(e.getKey(), false); + e.setValue(true); + }); + } + this.executePostSideEffects(obj, v); + return processedVertexes; + } - if (impliedDeleteLogLimit == -1) { - impliedDeleteLogLimit = Integer.MAX_VALUE; - } + private void createDeltaProperty(String uri, Object value, String dbProperty, Object oldValue) { + if (oldValue == null) { + addPropDelta(uri, dbProperty, PropertyDeltaFactory.getDelta(DeltaAction.CREATE, value), DeltaAction.UPDATE); + } else { + addPropDelta(uri, dbProperty, PropertyDeltaFactory.getDelta(DeltaAction.UPDATE, value, oldValue), DeltaAction.UPDATE); + } + } - // If the logging is enabled for implied delete - // then log the payload in the latest format - if ("true".equals(impliedDeleteLogEnabled) && impliedDeleteCount <= impliedDeleteLogLimit) { - for (Vertex vertex : impliedDeleteVertices) { - Introspector introspector = null; - try { - introspector = getLatestVersionView(vertex); - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Implied delete object in json format {}", introspector.marshal(false)); - } - } catch (Exception ex) { - LOGGER.warn( - "Encountered an exception during retrieval of vertex properties with vertex-id {} -> {}", - v.id(), LogFormatTools.getStackTop(ex)); - } + public HashMap<String, Introspector> getRelatedObjects(QueryEngine queryEngine, Vertex v, + Introspector obj, Loader loader) throws IllegalArgumentException, SecurityException, UnsupportedEncodingException, AAIException { + + HashMap<String, Introspector> relatedVertices = new HashMap<>(); + VertexProperty aaiUriProperty = v.property(AAIProperties.AAI_URI); + + if (!aaiUriProperty.isPresent()) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("For the given vertex {}, it seems aai-uri is not present so not getting related objects", + v.id().toString()); + } else { + LOGGER.info( + "It seems aai-uri is not present in vertex, so not getting related objects, for more info enable debug log"); + } + return relatedVertices; + } + + String aaiUri = aaiUriProperty.value().toString(); + + if (!obj.isTopLevel()) { + String[] uriList = convertIntrospectorToUriList(aaiUri, obj, loader); + List<Vertex> vertexChain; + // If the uriList is null then there is something wrong with converting the uri + // into a list of aai-uris so falling back to the old mechanism for finding parents + if (uriList == null) { + LOGGER.info( + "Falling back to the old mechanism due to unable to convert aai-uri to list of uris but this is not optimal"); + vertexChain = queryEngine.findParents(v); + } else if (uriList.length == 1) { + // If the uri list is size 1 the only uri in the list is the one represented by v thus no need to query + vertexChain = Collections.singletonList(v); + } else { + // the uriList at element 0 is the node in question and should not be included in the vertex chain lookup. + vertexChain = queryEngine.findParents(Arrays.copyOfRange(uriList, 1, uriList.length)); + // inject v into start of vertexChain + vertexChain.add(0, v); + } + for (Vertex vertex : vertexChain) { + try { + final Introspector vertexObj = this.getVertexProperties(vertex); + relatedVertices.put(vertexObj.getObjectId(), vertexObj); + } catch (AAIUnknownObjectException e) { + LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned"); } } + } else { + try { + final Introspector vertexObj = this.getVertexProperties(v); + relatedVertices.put(vertexObj.getObjectId(), vertexObj); + } catch (AAIUnknownObjectException e) { + LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned"); + } + } + + return relatedVertices; + } + + /** + * Given an uri, introspector object and loader object + * it will check if the obj is top level object if it is, + * it will return immediately returning the uri passed in + * If it isn't, it will go through, get the uriTemplate + * from the introspector object and get the count of "/"s + * and remove that part of the uri using substring + * and keep doing that until the current object is top level + * Also added the max depth just so worst case scenario + * Then keep adding aai-uri to the list include the aai-uri passed in + * Convert that list into an array and return it + * <p> + * + * Example: + * + * <blockquote> + * aai-uri -> + * /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1/vservers/vserver/v1 + * + * Given the uriTemplate vserver -> /vservers/vserver/{vserver-id} + * it converts to /vservers/vserver + * + * lastIndexOf /vservers/vserver in + * /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1/vservers/vserver/v1 + * ^ + * | + * | + * lastIndexOf + * Use substring to get the string from 0 to that lastIndexOf + * aai-uri -> /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1 + * + * From this new aai-uri, generate a introspector from the URITOObject class + * and keep doing this until you + * + * </blockquote> + * + * @param aaiUri - aai-uri of the vertex representating the unique id of a given vertex + * @param obj - introspector object of the given starting vertex + * @param loader - Type of loader which will always be MoxyLoader to support model driven + * @return an array of strings which can be used to get the vertexes of parent and grand parents from a given vertex + * @throws UnsupportedEncodingException + * @throws AAIException + */ + String[] convertIntrospectorToUriList(String aaiUri, Introspector obj, Loader loader) + throws UnsupportedEncodingException, AAIException { + + List<String> uriList = new ArrayList<>(); + String template; + String truncatedUri = aaiUri; + int depth = AAIProperties.MAXIMUM_DEPTH; + uriList.add(truncatedUri); + + while (depth >= 0 && !obj.isTopLevel()) { + template = obj.getMetadata(ObjectMetadata.URI_TEMPLATE); + + if (template == null) { + LOGGER.warn("Unable to find the uriTemplate for the object {}", obj.getDbName()); + return null; + } - // After all the appropriate logging, calling the delete to delete the affected vertices - this.delete(impliedDeleteVertices); + int templateCount = StringUtils.countMatches(template, "/"); + int truncatedUriCount = StringUtils.countMatches(truncatedUri, "/"); + + if (templateCount > truncatedUriCount) { + LOGGER.warn("Template uri {} contains more slashes than truncatedUri {}", template, truncatedUri); + return null; + } + + int cutIndex = StringUtils.ordinalIndexOf(truncatedUri, "/", truncatedUriCount - templateCount + 1); + truncatedUri = StringUtils.substring(truncatedUri, 0, cutIndex); + uriList.add(truncatedUri); + obj = new URIToObject(loader, UriBuilder.fromPath(truncatedUri).build()).getEntity(); + depth--; } - this.executePostSideEffects(obj, v); - return processedVertexes; + return uriList.toArray(new String[0]); } /** @@ -491,9 +728,7 @@ public class DBSerializer { * @param obj the obj * @param vertex the vertex * @throws SecurityException the security exception - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @@ -517,28 +752,141 @@ public class DBSerializer { * @throws AAIException the AAI exception */ private void processRelationshipList(Introspector wrapped, Vertex v) - throws UnsupportedEncodingException, AAIException { + throws UnsupportedEncodingException, AAIException { + + List<Object> relationships = wrapped.getValue("relationship"); + String mainUri = getURIForVertex(v).toString(); + String aNodeType = v.property(AAIProperties.NODE_TYPE).value().toString(); + EdgeRuleQuery.Builder cousinQueryBuilder = new EdgeRuleQuery.Builder(aNodeType) + .edgeType(EdgeType.COUSIN) + .version(wrapped.getVersion()); + EdgeRuleQuery.Builder treeQueryBuilder = new EdgeRuleQuery.Builder(aNodeType) + .edgeType(EdgeType.TREE) + .version(wrapped.getVersion()); - List<Object> relationships = (List<Object>) wrapped.getValue("relationship"); - - List<Triplet<Vertex, Vertex, String>> addEdges = new ArrayList<>(); - List<Edge> existingEdges = this.engine.getQueryEngine().findEdgesForVersion(v, wrapped.getLoader()); + EdgeIngestor edgeIngestor = SpringContextAware.getBean(EdgeIngestor.class); + Set<Pair<String, String>> cousinUriAndLabels = new LinkedHashSet<>(); for (Object relationship : relationships) { - Edge e = null; - Vertex cousinVertex = null; - String label = null; + + String label; Introspector wrappedRel = IntrospectorFactory.newInstance(this.introspectionType, relationship); - QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(wrappedRel); + String relUri = urlToUri(new RelationshipToURI(loader, wrappedRel).getUri().toString()); + + if (relUri.startsWith("/vnf/")) { + QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(wrappedRel); + List<Vertex> results = parser.getQueryBuilder().toList(); + if (results.isEmpty()) { + final AAIException ex = new AAIException(AAI_6129, + String.format("Node of type %s. Could not find object at: %s", parser.getResultType(), parser.getUri())); + ex.getTemplateVars().add(parser.getResultType()); + ex.getTemplateVars().add(parser.getUri().toString()); + throw ex; + } else { + // still an issue if there's more than one + if (results.get(0).property(AAIProperties.AAI_URI).isPresent()) { + relUri = results.get(0).value(AAIProperties.AAI_URI); + } else { + LOGGER.warn("Not processing the vertex {} because its missing required property aai-uri", results.get(0).id()); + continue; + } + } + } - if (wrappedRel.hasProperty("relationship-label")) { - label = wrappedRel.getValue("relationship-label"); + if (wrappedRel.getValue(RELATIONSHIP_LABEL) != null) { + label = wrappedRel.getValue(RELATIONSHIP_LABEL); + } else { + URIToObject uriToObject = new URIToObject(loader, URI.create(relUri)); + String bNodeType = uriToObject.getEntityName(); + EdgeRuleQuery ruleQuery = cousinQueryBuilder.to(bNodeType).build(); + if (!edgeIngestor.hasRule(ruleQuery)) { + EdgeRuleQuery treeQuery = treeQueryBuilder.to(bNodeType).build(); + if (edgeIngestor.hasRule(treeQuery)) { + throw new AAIException(AAI_6145); //attempted to create cousin edge for a parent-child edge rule + } + throw new AAIException("AAI_6120", String.format( + "No EdgeRule found for passed nodeTypes: %s, %s.", + aNodeType, bNodeType)); + } else { + try { + final List<EdgeRule> rules = new ArrayList<>(edgeIngestor.getRules(ruleQuery).values()); + if (rules.size() == 1) { + label = rules.get(0).getLabel(); + } else { + Optional<EdgeRule> defaultRule = rules.stream().filter(EdgeRule::isDefault).findFirst(); + if (defaultRule.isPresent()) { + label = defaultRule.get().getLabel(); + } else { + throw new AAIException(AAI_6145); + } + } + } catch (EdgeRuleNotFoundException ea) { + throw new AAIException(AAI_6145, ea); + } + } } + cousinUriAndLabels.add(Pair.with(relUri, label)); + } + + List<Path> paths = this.engine.getQueryEngine().findCousinsAsPath(v); + Set<Path> toRemove = new HashSet<>(); + + + // for each path 3 things can happen: + // 1. The edge rule that created it is not in this version no action is to be taken on that edge + // 2. The edge rule exits in this version it's included in the request the edge is left alone + // 3. The edge rule exits in this version and is not included in the request it is marked for removal + for (Path path : paths) { + if (path.size() < 3) { + continue; + } + + // Path represents + // v ----related-to--> otherV + // In the above case, + // path objects get(0) returns vertex v + // path objects.get(1) returns edge related-to + // path objects.get(2) returns vertex otherV + Vertex otherV = path.get(2); + + String bUri; + if (otherV.property(AAIProperties.AAI_URI).isPresent()) { + bUri = otherV.value(AAIProperties.AAI_URI); + } else { + continue; + } + String edgeLabel = path.<Edge>get(1).label(); + + Pair<String, String> key = Pair.with(bUri, edgeLabel); + if (cousinUriAndLabels.contains(key)) { + cousinUriAndLabels.remove(key); + } else { + String bNodeType; + if (otherV.property(AAIProperties.NODE_TYPE).isPresent()) { + bNodeType = otherV.property(AAIProperties.NODE_TYPE).value().toString(); + } else { + continue; + } + EdgeRuleQuery ruleQuery = cousinQueryBuilder.to(bNodeType).label(edgeLabel).build(); + if (edgeIngestor.hasRule(ruleQuery)) { + toRemove.add(path); + } + } + + } + + Set<Pair<Vertex, String>> toBeCreated = new HashSet<>(); + for (Pair<String, String> cousinUriAndLabel : cousinUriAndLabels) { + Edge e; + Vertex cousinVertex; + String label = cousinUriAndLabel.getValue1(); + String cousinUri = cousinUriAndLabel.getValue0(); + QueryParser parser = engine.getQueryBuilder().createQueryFromURI(URI.create(cousinUri)); List<Vertex> results = parser.getQueryBuilder().toList(); if (results.isEmpty()) { - final AAIException ex = new AAIException("AAI_6129", - "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri()); + final AAIException ex = new AAIException(AAI_6129, + "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri()); ex.getTemplateVars().add(parser.getResultType()); ex.getTemplateVars().add(parser.getUri().toString()); throw ex; @@ -553,38 +901,56 @@ public class DBSerializer { EdgeRuleQuery.Builder baseQ = new EdgeRuleQuery.Builder(vType, cousinType).label(label); if (!edgeRules.hasRule(baseQ.build())) { - throw new AAIException("AAI_6120", - "No EdgeRule found for passed nodeTypes: " - + v.property(AAIProperties.NODE_TYPE).value().toString() + ", " - + cousinVertex.property(AAIProperties.NODE_TYPE).value().toString() - + (label != null ? (" with label " + label) : "") + "."); + throw new AAIException("AAI_6120", String.format( + "No EdgeRule found for passed nodeTypes: %s, %s%s.", + aNodeType, cousinType, label != null ? (" with label " + label) : "")); } else if (edgeRules.hasRule(baseQ.edgeType(EdgeType.TREE).build()) - && !edgeRules.hasRule(baseQ.edgeType(EdgeType.COUSIN).build())) { - throw new AAIException("AAI_6145"); + && !edgeRules.hasRule(baseQ.edgeType(EdgeType.COUSIN).build())) { + throw new AAIException(AAI_6145); } e = this.getEdgeBetween(EdgeType.COUSIN, v, cousinVertex, label); if (e == null) { - addEdges.add(new Triplet<>(v, cousinVertex, label)); - } else { - existingEdges.remove(e); + toBeCreated.add(Pair.with(cousinVertex, label)); } } } - for (Edge edge : existingEdges) { - edge.remove(); + for (Path path : toRemove) { + if(isDeltaEventsEnabled) { + deltaForEdge(mainUri, path.get(1), DeltaAction.DELETE_REL, DeltaAction.UPDATE); + } + this.updatedVertexes.putIfAbsent(v, false); + this.edgeVertexes.add(path.get(2)); + path.<Edge>get(1).remove(); } - for (Triplet<Vertex, Vertex, String> triplet : addEdges) { + + for (Pair<Vertex, String> create : toBeCreated) { try { - edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), triplet.getValue0(), triplet.getValue1(), - triplet.getValue2()); - } catch (NoEdgeRuleFoundException e) { - throw new AAIException("AAI_6129", e); + Edge e = edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), v, create.getValue0(), create.getValue1()); + if (isDeltaEventsEnabled) { + deltaForEdge(mainUri, e, DeltaAction.CREATE_REL, DeltaAction.UPDATE); + } + this.updatedVertexes.putIfAbsent(v, false); + this.edgeVertexes.add(create.getValue0()); + } catch (NoEdgeRuleFoundException ex) { + throw new AAIException(AAI_6129, ex); } } + } + + private void deltaForEdge(String mainUri, Edge edge, DeltaAction edgeAction, DeltaAction mainAction) { + RelationshipDelta relationshipDelta = new RelationshipDelta( + edgeAction, + edge.inVertex().property(AAIProperties.AAI_UUID).value().toString(), + edge.outVertex().property(AAIProperties.AAI_UUID).value().toString(), + edge.inVertex().property(AAIProperties.AAI_URI).value().toString(), + edge.outVertex().property(AAIProperties.AAI_URI).value().toString(), + edge.label()); + edge.properties().forEachRemaining(p -> relationshipDelta.addProp(p.key(), p.value().toString())); + addRelationshipDelta(mainUri, relationshipDelta, mainAction); } /** @@ -600,11 +966,9 @@ public class DBSerializer { Set<String> required = latest.getRequiredProperties(); for (String field : required) { - String defaultValue = null; - Object vertexProp = null; - defaultValue = latest.getPropertyMetadata(field).get(PropertyMetadata.DEFAULT_VALUE); + String defaultValue = latest.getPropertyMetadata(field).get(PropertyMetadata.DEFAULT_VALUE); if (defaultValue != null) { - vertexProp = v.<Object>property(field).orElse(null); + Object vertexProp = v.property(field).orElse(null); if (vertexProp == null) { v.property(field, defaultValue); } @@ -620,11 +984,7 @@ public class DBSerializer { * @param v the v * @param dependentObj the dependent obj * @return the vertex - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws InstantiationException the instantiation exception - * @throws NoSuchMethodException the no such method exception * @throws SecurityException the security exception * @throws AAIException the AAI exception * @throws UnsupportedEncodingException the unsupported encoding exception @@ -633,23 +993,21 @@ public class DBSerializer { private Vertex reflectDependentVertex(Vertex v, Introspector dependentObj, String requestContext) throws AAIException, UnsupportedEncodingException { - // QueryParser p = this.engine.getQueryBuilder().createQueryFromURI(obj.getURI()); - // List<Vertex> items = p.getQuery().toList(); QueryBuilder<Vertex> query = this.engine.getQueryBuilder(v); query.createEdgeTraversal(EdgeType.TREE, v, dependentObj); query.createKeyQuery(dependentObj); List<Vertex> items = query.toList(); - Vertex dependentVertex = null; + Vertex dependentVertex; if (items.size() == 1) { dependentVertex = items.get(0); this.verifyResourceVersion("update", dependentObj.getDbName(), dependentVertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), - (String) dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String) dependentObj.getURI()); + dependentObj.getValue(AAIProperties.RESOURCE_VERSION), dependentObj.getURI()); } else { this.verifyResourceVersion("create", dependentObj.getDbName(), "", - (String) dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String) dependentObj.getURI()); + dependentObj.getValue(AAIProperties.RESOURCE_VERSION), dependentObj.getURI()); dependentVertex = createNewVertex(dependentObj); } @@ -664,11 +1022,7 @@ public class DBSerializer { * @param child the child * @param obj the obj * @return the vertex - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws InstantiationException the instantiation exception - * @throws NoSuchMethodException the no such method exception * @throws SecurityException the security exception * @throws AAIException the AAI exception * @throws UnsupportedEncodingException the unsupported encoding exception @@ -699,7 +1053,10 @@ public class DBSerializer { child.property(AAIProperties.LINKED, true); } } - edgeSer.addTreeEdge(this.engine.asAdmin().getTraversalSource(), parent, child); + e = edgeSer.addTreeEdge(this.engine.asAdmin().getTraversalSource(), parent, child); + if(isDeltaEventsEnabled) { + deltaForEdge(child.property(AAIProperties.AAI_URI).value().toString(), e, DeltaAction.CREATE_REL, DeltaAction.CREATE); + } } return child; @@ -724,19 +1081,14 @@ public class DBSerializer { * @param cleanUp the clean up * @return the introspector * @throws AAIException the AAI exception - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception * @throws SecurityException the security exception - * @throws InstantiationException the instantiation exception - * @throws NoSuchMethodException the no such method exception * @throws UnsupportedEncodingException the unsupported encoding exception - * @throws MalformedURLException the malformed URL exception * @throws AAIUnknownObjectException * @throws URISyntaxException */ public Introspector dbToObject(List<Vertex> vertices, final Introspector obj, int depth, boolean nodeOnly, - String cleanUp) throws UnsupportedEncodingException, AAIException { + String cleanUp, boolean isSkipRelatedTo) throws UnsupportedEncodingException, AAIException { final int internalDepth; if (depth == Integer.MAX_VALUE) { internalDepth = depth--; @@ -747,7 +1099,7 @@ public class DBSerializer { if (vertices.size() > 1 && !obj.isContainer()) { dbTimeMsecs += StopWatch.stopIfStarted(); throw new AAIException("AAI_6136", - "query object mismatch: this object cannot hold multiple items." + obj.getDbName()); + "query object mismatch: this object cannot hold multiple items." + obj.getDbName()); } else if (obj.isContainer()) { final List getList; String listProperty = null; @@ -758,7 +1110,7 @@ public class DBSerializer { } } final String propertyName = listProperty; - getList = (List) obj.getValue(listProperty); + getList = obj.getValue(listProperty); /* * This is an experimental multithreading experiment @@ -768,28 +1120,15 @@ public class DBSerializer { List<Future<Object>> futures = new ArrayList<>(); - QueryEngine tgEngine = this.engine.getQueryEngine(); for (Vertex v : vertices) { - AaiCallable<Object> task = new AaiCallable<Object>() { @Override public Object process() throws UnsupportedEncodingException, AAIException { Set<Vertex> seen = new HashSet<>(); Introspector childObject; - try { - childObject = obj.newIntrospectorInstanceOfNestedProperty(propertyName); - } catch (AAIUnknownObjectException e) { - throw e; - } - try { - dbToObject(childObject, v, seen, internalDepth, nodeOnly, cleanUp); - } catch (UnsupportedEncodingException e) { - throw e; - } catch (AAIException e) { - throw e; - } + childObject = obj.newIntrospectorInstanceOfNestedProperty(propertyName); + dbToObject(childObject, v, seen, internalDepth, nodeOnly, cleanUp, isSkipRelatedTo); return childObject.getUnderlyingObject(); - // getList.add(childObject.getUnderlyingObject()); } }; futures.add(pool.submit(task)); @@ -798,17 +1137,14 @@ public class DBSerializer { for (Future<Object> future : futures) { try { getList.add(future.get()); - } catch (ExecutionException e) { - dbTimeMsecs += StopWatch.stopIfStarted(); - throw new AAIException("AAI_4000", e); - } catch (InterruptedException e) { + } catch (ExecutionException | InterruptedException e) { dbTimeMsecs += StopWatch.stopIfStarted(); throw new AAIException("AAI_4000", e); } } } else if (vertices.size() == 1) { Set<Vertex> seen = new HashSet<>(); - dbToObject(obj, vertices.get(0), seen, depth, nodeOnly, cleanUp); + dbToObject(obj, vertices.get(0), seen, depth, nodeOnly, cleanUp, isSkipRelatedTo); } else { // obj = null; } @@ -820,26 +1156,62 @@ public class DBSerializer { /** * Db to object. * + * @param vertices the vertices + * @param obj the obj + * @param depth the depth + * @param cleanUp the clean up + * @return the introspector + * @throws AAIException the AAI exception + * @throws IllegalArgumentException the illegal argument exception + * @throws SecurityException the security exception + * @throws UnsupportedEncodingException the unsupported encoding exception + * @throws AAIUnknownObjectException + * @throws URISyntaxException + */ + public Introspector dbToObject(List<Vertex> vertices, final Introspector obj, int depth, boolean nodeOnly, + String cleanUp) throws UnsupportedEncodingException, AAIException { + return dbToObject(vertices, obj, depth, nodeOnly, cleanUp, false); + } + + /** + * Db to object. + * * @param obj the obj * @param v the v * @param seen the seen * @param depth the depth * @param cleanUp the clean up * @return the introspector - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception * @throws SecurityException the security exception - * @throws InstantiationException the instantiation exception - * @throws NoSuchMethodException the no such method exception * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception - * @throws MalformedURLException the malformed URL exception * @throws AAIUnknownObjectException * @throws URISyntaxException */ private Introspector dbToObject(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, String cleanUp) throws AAIException, UnsupportedEncodingException { + return dbToObject(obj, v, seen, depth, nodeOnly, cleanUp, false); + } + + /** + * Db to object. + * + * @param obj the obj + * @param v the v + * @param seen the seen + * @param depth the depth + * @param cleanUp the clean up + * @return the introspector + * @throws IllegalArgumentException the illegal argument exception + * @throws SecurityException the security exception + * @throws UnsupportedEncodingException the unsupported encoding exception + * @throws AAIException the AAI exception + * @throws AAIUnknownObjectException + * @throws URISyntaxException + */ + private Introspector dbToObject(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, + String cleanUp, boolean isSkipRelatedTo) throws AAIException, UnsupportedEncodingException { if (depth < 0) { return null; @@ -850,7 +1222,6 @@ public class DBSerializer { boolean modified = false; for (String property : obj.getProperties(PropertyPredicates.isVisible())) { List<Object> getList = null; - Vertex[] vertices = null; if (!(obj.isComplexType(property) || obj.isListType(property))) { this.copySimpleProperty(property, obj, v); @@ -869,9 +1240,8 @@ public class DBSerializer { } else if (property.equals("relationship-list") && !nodeOnly) { /* relationships need to be handled correctly */ Introspector relationshipList = obj.newIntrospectorInstanceOfProperty(property); - relationshipList = createRelationshipList(v, relationshipList, cleanUp); + relationshipList = createRelationshipList(v, relationshipList, cleanUp, isSkipRelatedTo); if (relationshipList != null) { - modified = true; obj.setValue(property, relationshipList.getUnderlyingObject()); modified = true; } @@ -890,42 +1260,39 @@ public class DBSerializer { try { rule = edgeRules.getRule( - new EdgeRuleQuery.Builder(vType, childDbName).edgeType(EdgeType.TREE).build()); + new EdgeRuleQuery.Builder(vType, childDbName).edgeType(EdgeType.TREE).build()); } catch (EdgeRuleNotFoundException e) { throw new NoEdgeRuleFoundException(e); } catch (AmbiguousRuleChoiceException e) { throw new MultipleEdgeRuleFoundException(e); } if (!rule.getContains().equals(AAIDirection.NONE.toString())) { - // vertices = this.queryEngine.findRelatedVertices(v, Direction.OUT, rule.getLabel(), - // childDbName); + Direction ruleDirection = rule.getDirection(); - Iterator<Vertex> itr = v.vertices(ruleDirection, rule.getLabel()); - List<Vertex> verticesList = (List<Vertex>) IteratorUtils.toList(itr); - itr = verticesList.stream().filter(item -> { - return item.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName); - }).iterator(); - if (itr.hasNext()) { - getList = (List<Object>) obj.getValue(property); + List<Vertex> verticesList = new ArrayList<>(); + v.vertices(ruleDirection, rule.getLabel()).forEachRemaining(vertex -> { + if (vertex.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName)) { + verticesList.add(vertex); + } + }); + if (!verticesList.isEmpty()) { + getList = obj.getValue(property); } int processed = 0; - int removed = 0; - while (itr.hasNext()) { - Vertex childVertex = itr.next(); + for (Vertex childVertex : verticesList) { if (!seen.contains(childVertex)) { Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property); Object result = - dbToObject(argumentObject, childVertex, seen, depth, nodeOnly, cleanUp); + dbToObject(argumentObject, childVertex, seen, depth, nodeOnly, cleanUp, isSkipRelatedTo); if (result != null) { getList.add(argumentObject.getUnderlyingObject()); } processed++; } else { - removed++; LOGGER.warn("Cycle found while serializing vertex id={}", - childVertex.id().toString()); + childVertex.id().toString()); } } if (processed == 0) { @@ -943,11 +1310,8 @@ public class DBSerializer { getList.addAll(temp); modified = true; } - } - } - } } @@ -969,27 +1333,26 @@ public class DBSerializer { Introspector obj = this.latestLoader.introspectorFromName(nodeType); Set<Vertex> seen = new HashSet<>(); int depth = 0; - String cleanUp = "false"; - boolean nodeOnly = true; StopWatch.conditionalStart(); - this.dbToObject(obj, v, seen, depth, nodeOnly, cleanUp); + this.dbToObject(obj, v, seen, depth, false, FALSE); dbTimeMsecs += StopWatch.stopIfStarted(); return obj; } public Introspector getLatestVersionView(Vertex v) throws AAIException, UnsupportedEncodingException { + return getLatestVersionView(v, AAIProperties.MAXIMUM_DEPTH); + } + + public Introspector getLatestVersionView(Vertex v, int depth) throws AAIException, UnsupportedEncodingException { String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null); if (nodeType == null) { throw new AAIException("AAI_6143"); } Introspector obj = this.latestLoader.introspectorFromName(nodeType); Set<Vertex> seen = new HashSet<>(); - int depth = AAIProperties.MAXIMUM_DEPTH; - String cleanUp = "false"; - boolean nodeOnly = false; StopWatch.conditionalStart(); - this.dbToObject(obj, v, seen, depth, nodeOnly, cleanUp); + this.dbToObject(obj, v, seen, depth, false, FALSE); dbTimeMsecs += StopWatch.stopIfStarted(); return obj; } @@ -1000,11 +1363,7 @@ public class DBSerializer { * @param property the property * @param obj the obj * @param v the v - * @throws InstantiationException the instantiation exception - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws NoSuchMethodException the no such method exception * @throws SecurityException the security exception */ private void copySimpleProperty(String property, Introspector obj, Vertex v) { @@ -1014,65 +1373,22 @@ public class DBSerializer { } } - /** - * Load the introspector from the hashmap for the given property key - * - * @param property - vertex property - * @param obj - introspector object representing the vertex - * @param hashMap - Containing a list of pre-fetched properties for a given vertex - */ - private void copySimplePropertyFromHashMap(String property, Introspector obj, Map<String, Object> hashMap) { - - final Map<PropertyMetadata, String> metadata = obj.getPropertyMetadata(property); - String dbPropertyName = property; - - if (metadata.containsKey(PropertyMetadata.DB_ALIAS)) { - dbPropertyName = metadata.get(PropertyMetadata.DB_ALIAS); - } - - final Object temp = hashMap.getOrDefault(dbPropertyName, null); - - if (temp != null) { - obj.setValue(property, temp); - } - } - - /** - * Simple db to object. - * - * @param obj the obj - * @param v the v - * @throws InstantiationException the instantiation exception - * @throws IllegalAccessException the illegal access exception - * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws NoSuchMethodException the no such method exception - * @throws SecurityException the security exception - */ - private void simpleDbToObject(Introspector obj, Vertex v) { - for (String key : obj.getProperties()) { - this.copySimpleProperty(key, obj, v); - } - } - public Map<String, Object> convertVertexToHashMap(Introspector obj, Vertex v) { - long startTime = System.currentTimeMillis(); - Set<String> simpleProperties = obj.getSimpleProperties(PropertyPredicates.isVisible()); String[] simplePropsArray = new String[simpleProperties.size()]; simplePropsArray = simpleProperties.toArray(simplePropsArray); Map<String, Object> simplePropsHashMap = new HashMap<>(simplePropsArray.length * 2); - v.properties(simplePropsArray).forEachRemaining((vp) -> simplePropsHashMap.put(vp.key(), vp.value())); + v.properties(simplePropsArray).forEachRemaining(vp -> simplePropsHashMap.put(vp.key(), vp.value())); return simplePropsHashMap; } - public Introspector dbToRelationshipObject(Vertex v) throws UnsupportedEncodingException, AAIException { + public Introspector dbToRelationshipObject(Vertex v, boolean isSkipRelatedTo) throws UnsupportedEncodingException, AAIException { Introspector relationshipList = this.latestLoader.introspectorFromName("relationship-list"); - relationshipList = createRelationshipList(v, relationshipList, "false"); + relationshipList = createRelationshipList(v, relationshipList, FALSE, isSkipRelatedTo); return relationshipList; } @@ -1083,136 +1399,96 @@ public class DBSerializer { * @param obj the obj * @param cleanUp the clean up * @return the object - * @throws InstantiationException the instantiation exception - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws NoSuchMethodException the no such method exception * @throws SecurityException the security exception * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception - * @throws MalformedURLException the malformed URL exception * @throws URISyntaxException */ private Introspector createRelationshipList(Vertex v, Introspector obj, String cleanUp) throws UnsupportedEncodingException, AAIException { + // default boolean value for isSkipRelatedTo is false + return createRelationshipList(v, obj, cleanUp, false); + } - String[] cousinRules = new String[0]; - - try { - cousinRules = edgeRules.retrieveCachedCousinLabels(obj.getDbName()); - } catch (ExecutionException e) { - LOGGER.warn("Encountered an execution exception while retrieving labels for the node type {} using cached", - obj.getDbName(), e); - } - - List<Vertex> cousins = null; - if (cousinRules != null && cousinRules.length != 0) { - cousins = this.engine.getQueryEngine().findCousinVertices(v, cousinRules); - } else { - cousins = this.engine.getQueryEngine().findCousinVertices(v); - } + /** + * Creates the relationship list. + * + * @param v the v + * @param obj the obj + * @param cleanUp the clean up + * @param isSkipRelatedTo to determine adding related-to-property in response + * @return the object + * @throws IllegalArgumentException the illegal argument exception + * @throws SecurityException the security exception + * @throws UnsupportedEncodingException the unsupported encoding exception + * @throws AAIException the AAI exception + * @throws URISyntaxException + */ + private Introspector createRelationshipList(Vertex v, Introspector obj, String cleanUp, boolean isSkipRelatedTo) + throws UnsupportedEncodingException, AAIException { - List<Object> relationshipObjList = obj.getValue("relationship"); + List<Object> relationshipObjList = obj.getValue(RELATIONSHIP); VertexProperty nodeTypeProperty = v.property(AAIProperties.NODE_TYPE); if (!nodeTypeProperty.isPresent()) { - LoggingContext.responseDescription(MISSING_REQUIRED_NODE_PROPERTY); LOGGER.warn("Not processing the vertex {} because its missing required property aai-node-type", v.id()); - LoggingContext.remove(LoggingContext.LoggingField.RESPONSE_DESCRIPTION.toString()); return null; } - String aNodeType = nodeTypeProperty.value().toString(); + List<Path> paths = this.engine.getQueryEngine().findCousinsAsPath(v); - TypeAlphabetizer alphabetizer = new TypeAlphabetizer(); + String aNodeType = v.property(AAIProperties.NODE_TYPE).value().toString(); EdgeIngestor edgeIngestor = SpringContextAware.getBean(EdgeIngestor.class); - Set<String> keysWithMultipleLabels = edgeIngestor.getMultipleLabelKeys(); - - // For the given vertex, find all the cousins - // For each cousin retrieve the node type and then - // check if the version is greater than the edge label version - // meaning is the current version equal to greater than the version - // where we introduced the edge labels into the relationship payload - // If it is, then we check if the edge key there are multiple labels - // If there are multiple labels, then we need to go to the database - // to retrieve the labels between itself and cousin vertex - // If there is only single label between the edge a and b, then - // we can retrieve what that is without going to the database - // from using the edge rules json and get the edge rule out of it - EdgeRuleQuery.Builder queryBuilder = new EdgeRuleQuery.Builder(aNodeType); - for (Vertex cousin : cousins) { - VertexProperty vertexProperty = cousin.property(AAIProperties.NODE_TYPE); - String bNodeType = null; - if (vertexProperty.isPresent()) { - bNodeType = cousin.property(AAIProperties.NODE_TYPE).value().toString(); - } else { - // If the vertex is missing the aai-node-type - // Then its either a bad vertex or its in the process - // of getting deleted so we should ignore these vertexes - LoggingContext.responseDescription(MISSING_REQUIRED_NODE_PROPERTY); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("For the vertex {}, unable to retrieve the aai-node-type", v.id().toString()); - } else { - LOGGER.info("Unable to retrieve the aai-node-type for vertex, for more info enable debug log"); - } - LoggingContext.remove(LoggingContext.LoggingField.RESPONSE_DESCRIPTION.toString()); + + EdgeRuleQuery.Builder queryBuilder = new EdgeRuleQuery.Builder(aNodeType) + .edgeType(EdgeType.COUSIN) + .version(obj.getVersion()); + + for (Path path : paths){ + if(path.size() < 3){ continue; } - if (obj.getVersion().compareTo(schemaVersions.getEdgeLabelVersion()) >= 0) { - String edgeKey = alphabetizer.buildAlphabetizedKey(aNodeType, bNodeType); - if (keysWithMultipleLabels.contains(edgeKey)) { - List<String> edgeLabels = this.getEdgeLabelsBetween(EdgeType.COUSIN, v, cousin); - for (String edgeLabel : edgeLabels) { - Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship"); - Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, edgeLabel); - if (result != null) { - relationshipObjList.add(result); - } - } - } else { - EdgeRule edgeRule = null; + // Path represents + // v ----related-to--> otherV + // In the above case, + // path objects get(0) returns vertex v + // path objects.get(1) returns edge related-to + // path objects.get(2) returns vertex otherV + Edge edge = path.get(1); + Vertex otherV= path.get(2); + + // TODO: Come back and revisit this code + // Create a query based on the a nodetype and b nodetype + // which is also a cousin edge and ensure the version + // is used properly so for example in order to be backwards + // compatible if we had allowed a edge between a and b + // in a previous release and we decided to remove it from + // the edge rules in the future we can display the edge + // only for the older apis and the new apis if the edge rule + // is removed will not be seen in the newer version of the API - // Create a query based on the a nodetype and b nodetype - // which is also a cousin edge and ensure the version - // is used properly so for example in order to be backwards - // compatible if we had allowed a edge between a and b - // in a previous release and we decided to remove it from - // the edge rules in the future we can display the edge - // only for the older apis and the new apis if the edge rule - // is removed will not be seen in the newer version of the API + String bNodeType = null; + if (otherV.property(AAIProperties.NODE_TYPE).isPresent()) { + bNodeType = otherV.property(AAIProperties.NODE_TYPE).value().toString(); + } else { + continue; + } - EdgeRuleQuery ruleQuery = - queryBuilder.to(bNodeType).edgeType(EdgeType.COUSIN).version(obj.getVersion()).build(); + String edgeLabel = edge.label(); + EdgeRuleQuery ruleQuery = queryBuilder.to(bNodeType).label(edgeLabel).build(); - try { - edgeRule = edgeIngestor.getRule(ruleQuery); - } catch (EdgeRuleNotFoundException e) { - LOGGER.warn( - "Caught an edge rule not found exception for query {}, {}," - + " it could be the edge rule is no longer valid for the existing edge in db", - ruleQuery, LogFormatTools.getStackTop(e)); - continue; - } catch (AmbiguousRuleChoiceException e) { - LOGGER.error("Caught an ambiguous rule not found exception for query {}, {}", ruleQuery, - LogFormatTools.getStackTop(e)); - continue; - } + if(!edgeIngestor.hasRule(ruleQuery)){ + LOGGER.debug( "Caught an edge rule not found for query {}", ruleQuery); + continue; + } - Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship"); - Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, edgeRule.getLabel()); - if (result != null) { - relationshipObjList.add(result); - } - } - } else { - Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship"); - Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null); - if (result != null) { - relationshipObjList.add(result); - } + Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty(RELATIONSHIP); + Object result = processEdgeRelationship(relationshipObj, otherV, cleanUp, edgeLabel, isSkipRelatedTo); + if (result != null) { + relationshipObjList.add(result); } } @@ -1228,23 +1504,17 @@ public class DBSerializer { * Process edge relationship. * * @param relationshipObj the relationship obj - * @param edge the edge + * @param edgeLabel the edge's label * @param cleanUp the clean up * @return the object - * @throws InstantiationException the instantiation exception - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws NoSuchMethodException the no such method exception * @throws SecurityException the security exception * @throws UnsupportedEncodingException the unsupported encoding exception - * @throws AAIException the AAI exception - * @throws MalformedURLException the malformed URL exception * @throws AAIUnknownObjectException * @throws URISyntaxException */ private Object processEdgeRelationship(Introspector relationshipObj, Vertex cousin, String cleanUp, - String edgeLabel) throws UnsupportedEncodingException, AAIUnknownObjectException { + String edgeLabel, boolean isSkipRelatedTo) throws UnsupportedEncodingException, AAIUnknownObjectException { VertexProperty aaiUriProperty = cousin.property("aai-uri"); @@ -1254,8 +1524,8 @@ public class DBSerializer { URI uri = UriBuilder.fromUri(aaiUriProperty.value().toString()).build(); - URIToRelationshipObject uriParser = null; - Introspector result = null; + URIToRelationshipObject uriParser; + Introspector result; try { uriParser = new URIToRelationshipObject(relationshipObj.getLoader(), uri, this.baseURL); result = uriParser.getResult(); @@ -1269,13 +1539,13 @@ public class DBSerializer { if (cousinVertexNodeType.isPresent()) { String cousinType = cousinVertexNodeType.value().toString(); - if (namedPropNodes.contains(cousinType)) { + if (namedPropNodes.contains(cousinType) && !isSkipRelatedTo) { this.addRelatedToProperty(result, cousin, cousinType); } } - if (edgeLabel != null && result.hasProperty("relationship-label")) { - result.setValue("relationship-label", edgeLabel); + if (edgeLabel != null && result.hasProperty(RELATIONSHIP_LABEL)) { + result.setValue(RELATIONSHIP_LABEL, edgeLabel); } return result.getUnderlyingObject(); @@ -1286,11 +1556,7 @@ public class DBSerializer { * * @param v the v * @return the URI for vertex - * @throws InstantiationException the instantiation exception - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws NoSuchMethodException the no such method exception * @throws SecurityException the security exception * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIUnknownObjectException @@ -1300,7 +1566,7 @@ public class DBSerializer { return getURIForVertex(v, false); } - public URI getURIForVertex(Vertex v, boolean overwrite) throws UnsupportedEncodingException { + public URI getURIForVertex(Vertex v, boolean overwrite) { URI uri = UriBuilder.fromPath("/unknown-uri").build(); String aaiUri = v.<String>property(AAIProperties.AAI_URI).orElse(null); @@ -1312,28 +1578,11 @@ public class DBSerializer { return uri; } - /** - * Gets the URI from list. - * - * @param list the list - * @return the URI from list - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - private URI getURIFromList(List<Introspector> list) throws UnsupportedEncodingException { - String uri = ""; - StringBuilder sb = new StringBuilder(); - for (Introspector i : list) { - sb.insert(0, i.getURI()); - } - - uri = sb.toString(); - return UriBuilder.fromPath(uri).build(); - } public void addRelatedToProperty(Introspector relationship, Vertex cousinVertex, String cousinType) throws AAIUnknownObjectException { - Introspector obj = null; + Introspector obj; try { obj = this.loader.introspectorFromName(cousinType); @@ -1360,7 +1609,7 @@ public class DBSerializer { } if (!relatedToProperties.isEmpty()) { - List relatedToList = (List) relationship.getValue("related-to-property"); + List<Object> relatedToList = relationship.getValue("related-to-property"); for (Introspector introspector : relatedToProperties) { relatedToList.add(introspector.getUnderlyingObject()); } @@ -1389,22 +1638,22 @@ public class DBSerializer { * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ - public boolean createEdge(Introspector relationship, Vertex inputVertex) + public Vertex createEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException { - Vertex relatedVertex = null; + Vertex relatedVertex; StopWatch.conditionalStart(); QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship); String label = null; - if (relationship.hasProperty("relationship-label")) { - label = relationship.getValue("relationship-label"); + if (relationship.hasProperty(RELATIONSHIP_LABEL)) { + label = relationship.getValue(RELATIONSHIP_LABEL); } List<Vertex> results = parser.getQueryBuilder().toList(); if (results.isEmpty()) { dbTimeMsecs += StopWatch.stopIfStarted(); - AAIException e = new AAIException("AAI_6129", + AAIException e = new AAIException(AAI_6129, "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri()); e.getTemplateVars().add(parser.getResultType()); e.getTemplateVars().add(parser.getUri().toString()); @@ -1420,7 +1669,10 @@ public class DBSerializer { try { e = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label); if (e == null) { - edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), inputVertex, relatedVertex, label); + e = edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), inputVertex, relatedVertex, label); + if(isDeltaEventsEnabled) { + deltaForEdge(inputVertex.property(AAIProperties.AAI_URI).value().toString(), e, DeltaAction.CREATE_REL, DeltaAction.UPDATE); + } } else { // attempted to link two vertexes already linked } @@ -1430,7 +1682,7 @@ public class DBSerializer { } dbTimeMsecs += StopWatch.stopIfStarted(); - return true; + return relatedVertex; } /** @@ -1439,8 +1691,6 @@ public class DBSerializer { * @param aVertex the out vertex * @param bVertex the in vertex * @return the edges between - * @throws AAIException the AAI exception - * @throws NoEdgeRuleFoundException */ private Edge getEdgeBetweenWithLabel(EdgeType type, Vertex aVertex, Vertex bVertex, EdgeRule edgeRule) { @@ -1476,42 +1726,11 @@ public class DBSerializer { } /** - * Gets all the edges between of the type. - * - * @param aVertex the out vertex - * @param bVertex the in vertex - * @return the edges between - * @throws AAIException the AAI exception - * @throws NoEdgeRuleFoundException - */ - private List<Edge> getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex) { - - List<Edge> result = new ArrayList<>(); - - if (bVertex != null) { - GraphTraversal<Vertex, Edge> findEdgesBetween = null; - findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE(); - if (EdgeType.TREE.equals(type)) { - findEdgesBetween = findEdgesBetween.not(__.or(__.has(EdgeProperty.CONTAINS.toString(), "NONE"), - __.has(EdgeField.PRIVATE.toString(), true))); - } else { - findEdgesBetween = findEdgesBetween.has(EdgeProperty.CONTAINS.toString(), "NONE") - .not(__.has(EdgeField.PRIVATE.toString(), true)); - } - findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id())); - result = findEdgesBetween.toList(); - } - - return result; - } - - /** * Gets all the edges string between of the type. * * @param aVertex the out vertex * @param bVertex the in vertex * @return the edges between - * @throws AAIException the AAI exception * @throws NoEdgeRuleFoundException */ private List<String> getEdgeLabelsBetween(EdgeType type, Vertex aVertex, Vertex bVertex) { @@ -1535,30 +1754,6 @@ public class DBSerializer { } /** - * Gets all the edges string between of the type. - * - * @param aVertex the out vertex - * @param bVertex the in vertex - * @return the edges between - * @throws AAIException the AAI exception - * @throws NoEdgeRuleFoundException - */ - private Long getEdgeLabelsCount(Vertex aVertex, Vertex bVertex) { - - Long result = null; - - if (bVertex != null) { - GraphTraversal<Vertex, Edge> findEdgesBetween = null; - findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE(); - findEdgesBetween = findEdgesBetween.has(EdgeProperty.CONTAINS.toString(), "NONE") - .not(__.has(EdgeField.PRIVATE.toString(), true)); - findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id())); - result = findEdgesBetween.count().next(); - } - return result; - } - - /** * Gets all the edges between the vertexes with the label and type. * * @param aVertex the out vertex @@ -1628,23 +1823,23 @@ public class DBSerializer { * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ - public boolean deleteEdge(Introspector relationship, Vertex inputVertex) + public Optional<Vertex> deleteEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException { - Vertex relatedVertex = null; + Vertex relatedVertex; StopWatch.conditionalStart(); QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship); List<Vertex> results = parser.getQueryBuilder().toList(); String label = null; - if (relationship.hasProperty("relationship-label")) { - label = relationship.getValue("relationship-label"); + if (relationship.hasProperty(RELATIONSHIP_LABEL)) { + label = relationship.getValue(RELATIONSHIP_LABEL); } if (results.isEmpty()) { dbTimeMsecs += StopWatch.stopIfStarted(); - return false; + return Optional.empty(); } relatedVertex = results.get(0); @@ -1653,29 +1848,19 @@ public class DBSerializer { edge = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label); } catch (NoEdgeRuleFoundException e) { dbTimeMsecs += StopWatch.stopIfStarted(); - throw new AAIException("AAI_6129", e); + throw new AAIException(AAI_6129, e); } if (edge != null) { + if(isDeltaEventsEnabled) { + String mainUri = inputVertex.property(AAIProperties.AAI_URI).value().toString(); + deltaForEdge(mainUri, edge, DeltaAction.DELETE_REL, DeltaAction.UPDATE); + } edge.remove(); dbTimeMsecs += StopWatch.stopIfStarted(); - return true; + return Optional.of(relatedVertex); } else { dbTimeMsecs += StopWatch.stopIfStarted(); - return false; - } - - } - - /** - * Delete items with traversal. - * - * @param vertexes the vertexes - * @throws IllegalStateException the illegal state exception - */ - public void deleteItemsWithTraversal(List<Vertex> vertexes) throws IllegalStateException { - - for (Vertex v : vertexes) { - deleteWithTraversal(v); + return Optional.empty(); } } @@ -1688,12 +1873,7 @@ public class DBSerializer { public void deleteWithTraversal(Vertex startVertex) { StopWatch.conditionalStart(); List<Vertex> results = this.engine.getQueryEngine().findDeletable(startVertex); - - for (Vertex v : results) { - LOGGER.debug("Removing vertex {} with label {}", v.id(), v.label()); - v.remove(); - } - dbTimeMsecs += StopWatch.stopIfStarted(); + this.delete(results); } /** @@ -1720,12 +1900,47 @@ public class DBSerializer { for (Vertex v : vertices) { LOGGER.debug("Removing vertex {} with label {}", v.id(), v.label()); + if(isDeltaEventsEnabled) { + deltaForVertexDelete(v); + } + //add the cousin vertexes of v to have their resource-version updated and notified on. + v.edges(Direction.BOTH) + .forEachRemaining(e -> { + if (e.property(EdgeProperty.CONTAINS.toString()).isPresent() + && AAIDirection.NONE.toString().equals(e.<String>value(EdgeProperty.CONTAINS.toString()))) { + e.bothVertices().forEachRemaining(cousinV -> { + if (!v.equals(cousinV)) { + edgeVertexes.add(cousinV); + } + }); + } + }); + + //if somewhere along the way v was added to the sets tracking the what is to be updated/notified on + // it should be removed from them as v is to be deleted + edgeVertexes.remove(v); + updatedVertexes.remove(v); v.remove(); } dbTimeMsecs += StopWatch.stopIfStarted(); } + private void deltaForVertexDelete(Vertex v) { + String aaiUri = v.property(AAIProperties.AAI_URI).value().toString(); + v.keys().forEach(k -> { + List<Object> list = new ArrayList<>(); + v.properties(k).forEachRemaining(vp -> list.add(vp.value())); + if (list.size() == 1) { + addPropDelta(aaiUri, k, PropertyDeltaFactory.getDelta(DeltaAction.DELETE, list.get(0)), DeltaAction.DELETE); + } else { + addPropDelta(aaiUri, k, PropertyDeltaFactory.getDelta(DeltaAction.DELETE, list), DeltaAction.DELETE); + } + + }); + v.edges(Direction.BOTH).forEachRemaining(e -> deltaForEdge(aaiUri, e, DeltaAction.DELETE, DeltaAction.DELETE)); + } + /** * Delete. * @@ -1741,7 +1956,7 @@ public class DBSerializer { boolean result = verifyDeleteSemantics(v, resourceVersion, enableResourceVersion); /* * The reason why I want to call PreventDeleteSemantics second time is to catch the prevent-deletes in a chain - * These are far-fewer than seeing a prevnt-delete on the vertex to be deleted + * These are far-fewer than seeing a prevent-delete on the vertex to be deleted * So its better to make these in 2 steps */ if (result && !deletableVertices.isEmpty()) { @@ -1756,7 +1971,6 @@ public class DBSerializer { } } - } /** @@ -1782,7 +1996,6 @@ public class DBSerializer { } } - } /** @@ -1795,15 +2008,14 @@ public class DBSerializer { */ private boolean verifyDeleteSemantics(Vertex vertex, String resourceVersion, boolean enableResourceVersion) throws AAIException { - boolean result = true; - String nodeType = ""; - String errorDetail = " unknown delete semantic found"; - String aaiExceptionCode = ""; + boolean result; + String nodeType; nodeType = vertex.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if (enableResourceVersion && !this.verifyResourceVersion("delete", nodeType, - vertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), resourceVersion, nodeType)) { + if (enableResourceVersion) { + this.verifyResourceVersion("delete", nodeType, + vertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), resourceVersion, nodeType); } - List<Vertex> vertices = new ArrayList<Vertex>(); + List<Vertex> vertices = new ArrayList<>(); vertices.add(vertex); result = verifyPreventDeleteSemantics(vertices); @@ -1819,7 +2031,6 @@ public class DBSerializer { */ private boolean verifyPreventDeleteSemantics(List<Vertex> vertices) throws AAIException { boolean result = true; - String nodeType = ""; String errorDetail = " unknown delete semantic found"; String aaiExceptionCode = ""; @@ -1987,6 +2198,35 @@ public class DBSerializer { /** * Db to object With Filters * This is for a one-time run with Tenant Isloation to only filter relationships + * + * @param obj the obj + * @param v the vertex from the graph + * @param depth the depth + * @param nodeOnly specify if to exclude relationships or not + * @param filterCousinNodes + * @return the introspector + * @throws AAIException the AAI exception + * @throws IllegalAccessException the illegal access exception + * @throws IllegalArgumentException the illegal argument exception + * @throws InvocationTargetException the invocation target exception + * @throws SecurityException the security exception + * @throws InstantiationException the instantiation exception + * @throws NoSuchMethodException the no such method exception + * @throws UnsupportedEncodingException the unsupported encoding exception + * @throws MalformedURLException the malformed URL exception + * @throws AAIUnknownObjectException + * @throws URISyntaxException + */ + public Introspector dbToObjectWithFilters(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, + List<String> filterCousinNodes, List<String> filterParentNodes) + throws AAIException, UnsupportedEncodingException { + return dbToObjectWithFilters(obj, v, seen, depth, nodeOnly, + filterCousinNodes, filterParentNodes, false); + } + + /** + * Db to object With Filters + * This is for a one-time run with Tenant Isloation to only filter relationships * TODO: Chnage the original dbToObject to take filter parent/cousins * * @param obj the obj @@ -1994,6 +2234,7 @@ public class DBSerializer { * @param depth the depth * @param nodeOnly specify if to exclude relationships or not * @param filterCousinNodes + * @param isSkipRelatedTo determine to incorporated related-to-property data * @return the introspector * @throws AAIException the AAI exception * @throws IllegalAccessException the illegal access exception @@ -2009,9 +2250,9 @@ public class DBSerializer { */ // TODO - See if you can merge the 2 dbToObjectWithFilters public Introspector dbToObjectWithFilters(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, - List<String> filterCousinNodes, List<String> filterParentNodes) + List<String> filterCousinNodes, List<String> filterParentNodes, boolean isSkipRelatedTo) throws AAIException, UnsupportedEncodingException { - String cleanUp = "false"; + String cleanUp = FALSE; if (depth < 0) { return null; } @@ -2020,7 +2261,6 @@ public class DBSerializer { boolean modified = false; for (String property : obj.getProperties(PropertyPredicates.isVisible())) { List<Object> getList = null; - Vertex[] vertices = null; if (!(obj.isComplexType(property) || obj.isListType(property))) { this.copySimpleProperty(property, obj, v); @@ -2032,7 +2272,7 @@ public class DBSerializer { if (!property.equals("relationship-list") && depth >= 0) { Introspector argumentObject = obj.newIntrospectorInstanceOfProperty(property); Object result = dbToObjectWithFilters(argumentObject, v, seen, depth + 1, nodeOnly, - filterCousinNodes, filterParentNodes); + filterCousinNodes, filterParentNodes, isSkipRelatedTo); if (result != null) { obj.setValue(property, argumentObject.getUnderlyingObject()); modified = true; @@ -2041,9 +2281,8 @@ public class DBSerializer { /* relationships need to be handled correctly */ Introspector relationshipList = obj.newIntrospectorInstanceOfProperty(property); relationshipList = - createFilteredRelationshipList(v, relationshipList, cleanUp, filterCousinNodes); + createFilteredRelationshipList(v, relationshipList, cleanUp, filterCousinNodes, isSkipRelatedTo); if (relationshipList != null) { - modified = true; obj.setValue(property, relationshipList.getUnderlyingObject()); modified = true; } @@ -2060,7 +2299,7 @@ public class DBSerializer { String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null); EdgeRule rule; - boolean isthisParentRequired = + boolean isThisParentRequired = filterParentNodes.parallelStream().anyMatch(childDbName::contains); EdgeRuleQuery q = new EdgeRuleQuery.Builder(vType, childDbName).edgeType(EdgeType.TREE).build(); @@ -2072,34 +2311,30 @@ public class DBSerializer { } catch (AmbiguousRuleChoiceException e) { throw new MultipleEdgeRuleFoundException(e); } - if (!rule.getContains().equals(AAIDirection.NONE.toString()) && isthisParentRequired) { - // vertices = this.queryEngine.findRelatedVertices(v, Direction.OUT, rule.getLabel(), - // childDbName); + if (!rule.getContains().equals(AAIDirection.NONE.toString()) && isThisParentRequired) { Direction ruleDirection = rule.getDirection(); - Iterator<Vertex> itr = v.vertices(ruleDirection, rule.getLabel()); - List<Vertex> verticesList = (List<Vertex>) IteratorUtils.toList(itr); - itr = verticesList.stream().filter(item -> { - return item.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName); - }).iterator(); - if (itr.hasNext()) { - getList = (List<Object>) obj.getValue(property); + List<Vertex> verticesList = new ArrayList<>(); + v.vertices(ruleDirection, rule.getLabel()).forEachRemaining(vertex -> { + if (vertex.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName)) { + verticesList.add(vertex); + } + }); + if (!verticesList.isEmpty()) { + getList = obj.getValue(property); } int processed = 0; - int removed = 0; - while (itr.hasNext()) { - Vertex childVertex = itr.next(); + for (Vertex childVertex : verticesList) { if (!seen.contains(childVertex)) { Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property); Object result = dbToObjectWithFilters(argumentObject, childVertex, seen, depth, - nodeOnly, filterCousinNodes, filterParentNodes); + nodeOnly, filterCousinNodes, filterParentNodes, isSkipRelatedTo); if (result != null) { getList.add(argumentObject.getUnderlyingObject()); } processed++; } else { - removed++; LOGGER.warn("Cycle found while serializing vertex id={}", childVertex.id().toString()); } @@ -2115,7 +2350,7 @@ public class DBSerializer { } else if (obj.isSimpleGenericType(property)) { List<Object> temp = this.engine.getListProperty(v, property); if (temp != null) { - getList = (List<Object>) obj.getValue(property); + getList = obj.getValue(property); getList.addAll(temp); modified = true; } @@ -2143,19 +2378,13 @@ public class DBSerializer { * @param obj the obj * @param cleanUp the clean up * @return the object - * @throws InstantiationException the instantiation exception - * @throws IllegalAccessException the illegal access exception * @throws IllegalArgumentException the illegal argument exception - * @throws InvocationTargetException the invocation target exception - * @throws NoSuchMethodException the no such method exception * @throws SecurityException the security exception * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception - * @throws MalformedURLException the malformed URL exception - * @throws URISyntaxException */ private Introspector createFilteredRelationshipList(Vertex v, Introspector obj, String cleanUp, - List<String> filterNodes) throws UnsupportedEncodingException, AAIException { + List<String> filterNodes, boolean isSkipRelatedTo) throws UnsupportedEncodingException, AAIException { List<Vertex> allCousins = this.engine.getQueryEngine().findCousinVertices(v); Iterator<Vertex> cousinVertices = allCousins.stream().filter(item -> { @@ -2163,14 +2392,14 @@ public class DBSerializer { return filterNodes.parallelStream().anyMatch(node::contains); }).iterator(); - List<Vertex> cousins = (List<Vertex>) IteratorUtils.toList(cousinVertices); + List<Object> relationshipObjList = obj.getValue(RELATIONSHIP); - // items.parallelStream().anyMatch(inputStr::contains) - List<Object> relationshipObjList = obj.getValue("relationship"); + List<Vertex> cousins = new ArrayList<>(); + cousinVertices.forEachRemaining(cousins::add); for (Vertex cousin : cousins) { - Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship"); - Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null); + Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty(RELATIONSHIP); + Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null, isSkipRelatedTo); if (result != null) { relationshipObjList.add(result); } @@ -2184,4 +2413,31 @@ public class DBSerializer { } } + public Set<Vertex> touchStandardVertexPropertiesForEdges() { + this.edgeVertexes.forEach(v -> this.touchStandardVertexProperties(v, false)); + return this.edgeVertexes; + } + + public void addVertexToEdgeVertexes(Vertex vertex){ + this.edgeVertexes.add(vertex); + } + + private String urlToUri(String url) { + if (url.startsWith("/")) { + url = url.substring(1); + } + + if (url.endsWith("/")) { + url = url.substring(0, url.length() - 1); + } + + // TODO - Check if this makes to do for model driven for base uri path + url = url.replaceFirst("[a-z][a-z]*/v\\d+/", ""); + if (url.charAt(0) != '/') { + url = '/' + url; + } + + return url; + } + } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/GraphSingleton.java b/aai-core/src/main/java/org/onap/aai/serialization/db/GraphSingleton.java index cb713d56..3a7c6d2d 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/db/GraphSingleton.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/db/GraphSingleton.java @@ -20,11 +20,10 @@ package org.onap.aai.serialization.db; -import java.util.concurrent.atomic.AtomicInteger; - import org.janusgraph.core.JanusGraph; import org.onap.aai.dbmap.AAIGraph; -import org.onap.aai.dbmap.DBConnectionType; + +import java.util.concurrent.atomic.AtomicInteger; /* This class simply calls AAIGraph under the covers for now */ public class GraphSingleton { @@ -63,7 +62,4 @@ public class GraphSingleton { return AAIGraph.getInstance().getGraph(); } - public JanusGraph getTxGraph(DBConnectionType connectionType) { - return AAIGraph.getInstance().getGraph(connectionType); - } } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/ImpliedDelete.java b/aai-core/src/main/java/org/onap/aai/serialization/db/ImpliedDelete.java new file mode 100644 index 00000000..437f1634 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/serialization/db/ImpliedDelete.java @@ -0,0 +1,205 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.serialization.db; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.commons.lang.StringUtils; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.logging.LogFormatTools; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.serialization.engines.query.QueryEngine; +import org.onap.aai.util.AAIConfigProxy; +import org.onap.aai.util.AAIConstants; + +import java.util.List; +import java.util.Objects; + +/** + * <b>ImpliedDelete</b> class is responsible for deleting children + * of a parent vertex if the client explicitly asks to remove them + * It will check if they are allowed and based on that information + * it will decide whether to proceed with the deletion or + * throw an exception back to the requester if they are not allowed + * + * It implements the AAIProxy Interface and any calls to the + * AAIConfig should be using the proxy methods and any new + * methods that needs to be invoked should be added there first + * + * @see org.onap.aai.util.AAIConfigProxy + */ +public class ImpliedDelete implements AAIConfigProxy { + + private static final Logger LOGGER = LoggerFactory.getLogger(ImpliedDelete.class); + + private static final String IMPLICIT_DELETE = "Implicit DELETE"; + private static final String STAR = "*"; + + private TransactionalGraphEngine engine; + private DBSerializer serializer; + + public ImpliedDelete(TransactionalGraphEngine engine, DBSerializer serializer){ + this.engine = engine; + this.serializer = serializer; + } + + /** + * Checks if the user is allowed to execute implied delete + * If they are allowed to do the delete, then for all the dependent vertices + * it will identify all the deletable vertices to them + * and log them based on the following aaiconfig properties: + * + * aai.implied.delete.log.enabled=true + * aai.implied.delete.log.limit=-1 + * + * Above properties are the default assumption of the code if they are not overwritten + * So the code will log for every vertex it is about to delete + * If there are thousands of vertexes that get implicitly deleted, + * its preferable that the operation timeout rather than + * someone accidentally deleting thousands of children + * + * @param id - Identifier of the vertex whose children could be potentially deleted + * @param sot - source of truth of who the requester who is making the request + * @param objectType - type of the parent object whose children are being deleted + * @param dependentVertexes - list of children vertexes + * @throws AAIException if the user is not allowed to implicitly delete children + */ + public List<Vertex> execute(Object id, String sot, String objectType, List<Vertex> dependentVertexes) throws AAIException { + if(dependentVertexes != null && !dependentVertexes.isEmpty()){ + // Find all the deletable vertices from the dependent vertices that should be deleted + // So for each of the following dependent vertices, + // we will use the edge properties and do the cascade delete + QueryEngine queryEngine = this.engine.getQueryEngine(); + List<Vertex> impliedDeleteVertices = queryEngine.findDeletable(dependentVertexes); + if(this.allow(sot, objectType)){ + + int impliedDeleteCount = impliedDeleteVertices.size(); + + LOGGER.warn( + "For the vertex with id {}, doing an implicit delete on update will delete total of {} vertexes", + id, + impliedDeleteCount + ); + + String impliedDeleteLogEnabled = get(AAIConstants.AAI_IMPLIED_DELETE_LOG_ENABLED, "true"); + + int impliedDeleteLogLimit = getInt(AAIConstants.AAI_IMPLIED_DELETE_LOG_LIMIT, "-1"); + + if (impliedDeleteLogLimit == -1) { + impliedDeleteLogLimit = Integer.MAX_VALUE; + } + + // If the logging is enabled for implied delete + // then log the payload in the latest format + if ("true".equals(impliedDeleteLogEnabled) && impliedDeleteCount <= impliedDeleteLogLimit) { + for (Vertex vertex : impliedDeleteVertices) { + Introspector introspector = null; + try { + introspector = serializer.getLatestVersionView(vertex); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Implied delete object in json format {}", introspector.marshal(false)); + } + } catch (Exception ex) { + LOGGER.warn( + "Encountered an exception during retrieval of vertex properties with vertex-id {} -> {}", + id, LogFormatTools.getStackTop(ex)); + } + } + } + } else { + LOGGER.error("User {} is not allowed to implicit delete on parent object {}", sot, objectType); + throw new AAIException("AAI_9109"); + } + return impliedDeleteVertices; + } else { + // Return null or an empty list back to the user based on input + return dependentVertexes; + } + } + + public void delete(List<Vertex> vertices){ + // After all the appropriate logging, calling the serializer delete to delete the affected vertices + if(vertices != null && !vertices.isEmpty()){ + serializer.delete(vertices); + } + } + + /** + * Checks the property in the aaiconfig properties + * to see if the user is allowed to do implicit delete + * + * Expecting the aaiconfig.properties to have following type of properties + * + * <code> + * aai.implied.delete.whitelist.sdnc=* + * aai.implied.delete.whitelist.sdc='pserver','vserver' + * </code> + * + * So in the above code, the expectation is for any of the following user: + * + * <ul> + * <li>SDC</li> + * <li>SDc</li> + * <li>Sdc</li> + * <li>sDc</li> + * <li>SdC</li> + * <li>sdC</li> + * <li>sdc</li> + * </ul> + * + * They are allowed to delete the children of pserver and vserver by implicit delete + * + * Note: The reason the property values are placed inside the single quotes is + * so if there is an object called volume and there is another object called volume-group + * when doing an contains it can falsely allow volume-group children to be implicitly deleted + * and the cost of turning the string into an array and then searching if its inside it + * or loading into an set which is unnecessary and it could potentially be done for every request + * + * @param sourceOfTruth - the original requester that the request is coming from, + * derived from HTTP Header X-FromAppId + * @param parentObjectType - parent object in which they are trying to do the implicit delete against + * + * @return true - if the requester is allowed to implicit delete against the object type + * false - if they are not allowed + */ + private boolean allow(String sourceOfTruth, String parentObjectType){ + Objects.requireNonNull(sourceOfTruth); + Objects.requireNonNull(parentObjectType); + + String propertyName = AAIConstants.AAI_IMPLIED_DELETE_WHITELIST + sourceOfTruth.toLowerCase(); + String whitelist = get(propertyName, StringUtils.EMPTY); + + if(whitelist.isEmpty()){ + return false; + } + + if(STAR.equals(whitelist)){ + return true; + } + + if(whitelist.contains("'" + parentObjectType + "'")){ + return true; + } + + return false; + } +} diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/InMemoryGraphSingleton.java b/aai-core/src/main/java/org/onap/aai/serialization/db/InMemoryGraphSingleton.java index 90f71db5..2ca96b5b 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/db/InMemoryGraphSingleton.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/db/InMemoryGraphSingleton.java @@ -21,7 +21,6 @@ package org.onap.aai.serialization.db; import org.janusgraph.core.JanusGraph; -import org.onap.aai.dbmap.DBConnectionType; public class InMemoryGraphSingleton extends GraphSingleton { @@ -51,8 +50,4 @@ public class InMemoryGraphSingleton extends GraphSingleton { return inMemgraph; } - @Override - public JanusGraph getTxGraph(DBConnectionType connectionType) { - return inMemgraph; - } } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/engines/InMemoryDBEngine.java b/aai-core/src/main/java/org/onap/aai/serialization/engines/InMemoryDBEngine.java index 86c32f4a..66509c97 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/engines/InMemoryDBEngine.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/engines/InMemoryDBEngine.java @@ -20,23 +20,22 @@ package org.onap.aai.serialization.engines; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.janusgraph.core.JanusGraph; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.introspection.Loader; import org.onap.aai.query.builder.*; import org.onap.aai.serialization.db.InMemoryGraphSingleton; import org.onap.aai.serialization.engines.query.GraphTraversalQueryEngine; import org.onap.aai.serialization.engines.query.QueryEngine; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + public class InMemoryDBEngine extends TransactionalGraphEngine { /** @@ -49,10 +48,8 @@ public class InMemoryDBEngine extends TransactionalGraphEngine { */ private JanusGraph graph = null; - private static final TransactionalGraphEngine.Admin admin = null; - - public InMemoryDBEngine(QueryStyle style, DBConnectionType connectionType, Loader loader, JanusGraph graph) { - super(style, loader, connectionType, InMemoryGraphSingleton.getInstance(graph)); + public InMemoryDBEngine(QueryStyle style, Loader loader, JanusGraph graph) { + super(style, loader, InMemoryGraphSingleton.getInstance(graph)); this.graph = graph; } @@ -195,8 +192,7 @@ public class InMemoryDBEngine extends TransactionalGraphEngine { if (this.tx() == null) { this.currentTx = graph.newTransaction(); this.currentTraversal = this.tx().traversal(); - this.readOnlyTraversal = - this.tx().traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance())); + this.readOnlyTraversal = this.tx().traversal().withStrategies(ReadOnlyStrategy.instance()); } return currentTx; } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/engines/JanusGraphDBEngine.java b/aai-core/src/main/java/org/onap/aai/serialization/engines/JanusGraphDBEngine.java index 346cf026..2a4511d0 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/engines/JanusGraphDBEngine.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/engines/JanusGraphDBEngine.java @@ -20,16 +20,15 @@ package org.onap.aai.serialization.engines; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.introspection.Loader; import org.onap.aai.serialization.db.JanusGraphSingleton; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + public class JanusGraphDBEngine extends TransactionalGraphEngine { /** @@ -38,8 +37,8 @@ public class JanusGraphDBEngine extends TransactionalGraphEngine { * @param style the style * @param loader the loader */ - public JanusGraphDBEngine(QueryStyle style, DBConnectionType connectionType, Loader loader) { - super(style, loader, connectionType, JanusGraphSingleton.getInstance()); + public JanusGraphDBEngine(QueryStyle style, Loader loader) { + super(style, loader, JanusGraphSingleton.getInstance()); } /** @@ -82,7 +81,7 @@ public class JanusGraphDBEngine extends TransactionalGraphEngine { @Override public List<Object> getListProperty(Vertex v, String name) { - List<Object> result = new ArrayList<Object>(); + List<Object> result = new ArrayList<>(); Iterator<VertexProperty<Object>> iterator = v.properties(name); @@ -90,7 +89,7 @@ public class JanusGraphDBEngine extends TransactionalGraphEngine { result.add(iterator.next().value()); } - if (result.size() == 0) { + if (result.isEmpty()) { result = null; } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/engines/QueryStyle.java b/aai-core/src/main/java/org/onap/aai/serialization/engines/QueryStyle.java index c291fbcb..f69e4d34 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/engines/QueryStyle.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/engines/QueryStyle.java @@ -21,5 +21,5 @@ package org.onap.aai.serialization.engines; public enum QueryStyle { - GREMLIN_TRAVERSAL, GREMLIN_UNIQUE, GREMLINPIPELINE_TRAVERSAL, TRAVERSAL, TRAVERSAL_URI + GREMLIN_TRAVERSAL, GREMLIN_UNIQUE, GREMLINPIPELINE_TRAVERSAL, TRAVERSAL, TRAVERSAL_URI, HISTORY_TRAVERSAL, HISTORY_GREMLIN_TRAVERSAL } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/engines/TransactionalGraphEngine.java b/aai-core/src/main/java/org/onap/aai/serialization/engines/TransactionalGraphEngine.java index 731d6c23..b945db05 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/engines/TransactionalGraphEngine.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/engines/TransactionalGraphEngine.java @@ -20,29 +20,26 @@ package org.onap.aai.serialization.engines; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.janusgraph.core.JanusGraph; import org.janusgraph.core.schema.JanusGraphManagement; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.introspection.Loader; import org.onap.aai.query.builder.*; import org.onap.aai.serialization.db.GraphSingleton; import org.onap.aai.serialization.engines.query.GraphTraversalQueryEngine; import org.onap.aai.serialization.engines.query.QueryEngine; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + public abstract class TransactionalGraphEngine { protected GraphSingleton singleton = null; - protected QueryEngine queryEngine = null; protected QueryBuilder<Vertex> queryBuilder = null; - protected QueryStyle style = null; - protected final DBConnectionType connectionType; + protected QueryStyle style; protected final Loader loader; protected Graph currentTx = null; protected GraphTraversalSource currentTraversal = null; @@ -55,19 +52,16 @@ public abstract class TransactionalGraphEngine { * @param style the style * @param loader the loader */ - public TransactionalGraphEngine(QueryStyle style, Loader loader, DBConnectionType connectionType, - GraphSingleton singleton) { + public TransactionalGraphEngine(QueryStyle style, Loader loader, GraphSingleton singleton) { this.loader = loader; this.style = style; this.singleton = singleton; - this.connectionType = connectionType; admin = new Admin(); } public TransactionalGraphEngine(QueryStyle style, Loader loader) { this.loader = loader; this.style = style; - this.connectionType = DBConnectionType.REALTIME; admin = new Admin(); } @@ -97,7 +91,7 @@ public abstract class TransactionalGraphEngine { * @return the graph */ private JanusGraph getGraph() { - return singleton.getTxGraph(this.connectionType); + return singleton.getTxGraph(); } /** @@ -150,6 +144,10 @@ public abstract class TransactionalGraphEngine { return getQueryBuilder(this.style, loader); } + public QueryBuilder<Vertex> getQueryBuilder(QueryStyle style, GraphTraversalSource source) { + return getQueryBuilder(style, this.loader, source); + } + public QueryBuilder<Vertex> getQueryBuilder(QueryStyle style, Loader loader) { if (style.equals(QueryStyle.GREMLIN_TRAVERSAL)) { return new GremlinTraversal<>(loader, this.asAdmin().getTraversalSource()); @@ -161,7 +159,32 @@ public abstract class TransactionalGraphEngine { return new TraversalQuery<>(loader, this.asAdmin().getTraversalSource()); } else if (style.equals(QueryStyle.TRAVERSAL_URI)) { return new TraversalURIOptimizedQuery<>(loader, this.asAdmin().getTraversalSource()); - } else { + } else if (style.equals(QueryStyle.HISTORY_TRAVERSAL)) { + throw new IllegalArgumentException("History Traversal needs history traversal source"); + } else if (style.equals(QueryStyle.HISTORY_GREMLIN_TRAVERSAL)) { + throw new IllegalArgumentException("History Gremlin Traversal needs history traversal source"); + }else { + throw new IllegalArgumentException("Query Builder type not recognized"); + } + return queryBuilder; + } + + public QueryBuilder<Vertex> getQueryBuilder(QueryStyle style, Loader loader, GraphTraversalSource source) { + if (style.equals(QueryStyle.GREMLIN_TRAVERSAL)) { + return new GremlinTraversal<>(loader, source); + } else if (style.equals(QueryStyle.GREMLIN_UNIQUE)) { + return new GremlinUnique<>(loader, source); + } else if (style.equals(QueryStyle.GREMLINPIPELINE_TRAVERSAL)) { + // return new GremlinPipelineTraversal(loader); + } else if (style.equals(QueryStyle.TRAVERSAL)) { + return new TraversalQuery<>(loader, source); + } else if (style.equals(QueryStyle.TRAVERSAL_URI)) { + return new TraversalURIOptimizedQuery<>(loader, source); + } else if (style.equals(QueryStyle.HISTORY_TRAVERSAL)) { + return new HistoryTraversalURIOptimizedQuery<>(loader, source); + }else if (style.equals(QueryStyle.HISTORY_GREMLIN_TRAVERSAL)) { + return new HistoryGremlinTraversal<>(loader, source); + }else { throw new IllegalArgumentException("Query Builder type not recognized"); } return queryBuilder; @@ -202,8 +225,7 @@ public abstract class TransactionalGraphEngine { if (this.tx() == null) { this.currentTx = this.getGraph().newTransaction(); this.currentTraversal = this.tx().traversal(); - this.readOnlyTraversal = - this.tx().traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance())); + this.readOnlyTraversal =this.tx().traversal().withStrategies(ReadOnlyStrategy.instance()); } return currentTx; } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngine.java b/aai-core/src/main/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngine.java index e012aef3..376a2798 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngine.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngine.java @@ -20,18 +20,9 @@ package org.onap.aai.serialization.engines.query; -import static org.onap.aai.edges.enums.AAIDirection.IN; -import static org.onap.aai.edges.enums.AAIDirection.NONE; -import static org.onap.aai.edges.enums.AAIDirection.OUT; -import static org.onap.aai.edges.enums.EdgeField.PRIVATE; -import static org.onap.aai.edges.enums.EdgeProperty.CONTAINS; -import static org.onap.aai.edges.enums.EdgeProperty.DELETE_OTHER_V; - -import java.util.List; -import java.util.Set; - import org.apache.tinkerpop.gremlin.process.traversal.Order; import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.Path; 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.process.traversal.dsl.graph.__; @@ -41,9 +32,19 @@ import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Element; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.edges.enums.EdgeField; +import org.onap.aai.edges.enums.EdgeProperty; import org.onap.aai.introspection.Loader; import org.onap.aai.logging.StopWatch; +import java.util.List; +import java.util.Set; + +import static org.onap.aai.edges.enums.AAIDirection.*; +import static org.onap.aai.edges.enums.EdgeField.PRIVATE; +import static org.onap.aai.edges.enums.EdgeProperty.CONTAINS; +import static org.onap.aai.edges.enums.EdgeProperty.DELETE_OTHER_V; + /* * This class needs some big explanation despite its compact size. * This controls all the queries performed by the CRUD API in A&AI. @@ -256,6 +257,15 @@ public class GraphTraversalQueryEngine extends QueryEngine { return pipeline.toList(); } + public List<Path> findCousinsAsPath(Vertex start){ + return this.g.V(start).bothE().where( + __.and( + __.has(EdgeProperty.CONTAINS.toString(), NONE.toString()), + __.not(__.has(EdgeField.PRIVATE.toString(), true)) + ) + ).otherV().path().toList(); + } + public double getDBTimeMsecs() { return (dbTimeMsecs); } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/engines/query/QueryEngine.java b/aai-core/src/main/java/org/onap/aai/serialization/engines/query/QueryEngine.java index 4f30b564..b250d8f3 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/engines/query/QueryEngine.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/engines/query/QueryEngine.java @@ -22,6 +22,7 @@ package org.onap.aai.serialization.engines.query; import java.util.List; +import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; import org.apache.tinkerpop.gremlin.structure.Direction; @@ -81,7 +82,7 @@ public abstract class QueryEngine { /** * Finds all immediate children of start (no grandchildren or so forth) of the given type - * + * * @param start - the start vertex * @param type - the desired aai-node-type * @return the list of immediate child vertices of given type @@ -90,7 +91,7 @@ public abstract class QueryEngine { /** * Finds all immediate children of start (no grandchildren or so forth) - * + * * @param start - the start vertex * @return the list of immediate child vertices */ @@ -173,6 +174,8 @@ public abstract class QueryEngine { */ public abstract List<Vertex> findCousinVertices(Vertex start, String... labels); + public abstract List<Path> findCousinsAsPath(Vertex start); + public abstract double getDBTimeMsecs(); } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Aggregate.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Aggregate.java new file mode 100644 index 00000000..4c37aaa1 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Aggregate.java @@ -0,0 +1,313 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.queryformats; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.gson.*; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.introspection.Loader; +import org.onap.aai.logging.LogFormatTools; +import org.onap.aai.serialization.db.DBSerializer; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.onap.aai.serialization.queryformats.params.AsTree; +import org.onap.aai.serialization.queryformats.params.Depth; +import org.onap.aai.serialization.queryformats.params.NodesOnly; +import org.onap.aai.serialization.queryformats.utils.UrlBuilder; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Aggregate extends MultiFormatMapper { + private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleFormat.class); + protected JsonParser parser = new JsonParser(); + protected final DBSerializer serializer; + protected final Loader loader; + protected final UrlBuilder urlBuilder; + protected final int depth; + protected final boolean nodesOnly; + + protected Aggregate(Builder builder) { + this.urlBuilder = builder.getUrlBuilder(); + this.loader = builder.getLoader(); + this.serializer = builder.getSerializer(); + this.depth = builder.getDepth(); + this.nodesOnly = builder.isNodesOnly(); + this.isTree = builder.isTree(); + } + + @Override + public Optional<JsonObject> getJsonFromVertex(Vertex v, Map<String, List<String>> selectedProps) throws AAIFormatVertexException{ + JsonObject json = new JsonObject(); + JsonObject outer = new JsonObject(); + Optional<JsonObject> properties = this.createSelectedPropertiesObject(v,selectedProps); + if (properties.isPresent()) { + json.add("properties", properties.get()); + outer.add(this.urlBuilder.pathed(v),json.getAsJsonObject()); + } else { + return Optional.empty(); + } + return Optional.of(outer); + } + + @Override + public int parallelThreshold() { + return 100; + } + + public Optional<JsonObject> createPropertiesObject(Vertex v) throws AAIFormatVertexException { + JsonObject json = new JsonObject(); + Iterator<VertexProperty<Object>> iter = v.properties(); + + while (iter.hasNext()) { + VertexProperty<Object> prop = iter.next(); + if (prop.value() instanceof String) { + json.addProperty(prop.key(), (String) prop.value()); + } else if (prop.value() instanceof Boolean) { + json.addProperty(prop.key(), (Boolean) prop.value()); + } else if (prop.value() instanceof Number) { + json.addProperty(prop.key(), (Number) prop.value()); + } else if (prop.value() instanceof List) { + Gson gson = new Gson(); + String list = gson.toJson(prop.value()); + + json.addProperty(prop.key(), list); + } else { + // throw exception? + return null; + } + } + + return Optional.of(json); + } + + public Optional<JsonObject> createSelectedPropertiesObject(Vertex v, Map<String, List<String>> selectedProps) throws AAIFormatVertexException { + JsonObject json = new JsonObject(); + Set<String> propList = null; + String nodeType = v.<String>value(AAIProperties.NODE_TYPE); + if (selectedProps != null && !selectedProps.isEmpty() && selectedProps.containsKey(nodeType)) { + propList = removeSingleQuotesForProperties(selectedProps.get(nodeType)); + } + Iterator<VertexProperty<Object>> iter = v.properties(); + + Gson gson = new Gson(); + while (iter.hasNext()) { + VertexProperty<Object> prop = iter.next(); + if (propList != null && !propList.isEmpty()) { + if (propList.contains(prop.label())) { + if (prop.value() instanceof String) { + json.addProperty(prop.key(), (String) prop.value()); + } else if (prop.value() instanceof Boolean) { + json.addProperty(prop.key(), (Boolean) prop.value()); + } else if (prop.value() instanceof Number) { + json.addProperty(prop.key(), (Number) prop.value()); + } else if (prop.value() instanceof List) { + json.addProperty(prop.key(), gson.toJson(prop.value())); + } else { + // throw exception? + return null; + } + } + } else { + return this.createPropertiesObject(v); + } + } + + return Optional.of(json); + } + + private Set<String> removeSingleQuotesForProperties(List<String> props){ + if (props != null && !props.isEmpty()) { + return props.stream().map( + e -> e.substring(1, e.length()-1)).collect(Collectors.toSet()); + } else { + return Collections.emptySet(); + } + } + + public JsonArray process(List<Object> queryResults, Map<String, List<String>> properties) { + JsonArray body = new JsonArray(); + Stream<Object> stream; + if (queryResults.size() >= this.parallelThreshold()) { + stream = queryResults.parallelStream(); + } else { + stream = queryResults.stream(); + } + final boolean isParallel = stream.isParallel(); + + stream.map(o -> { + try { + return this.formatObject(o, properties); + } catch (AAIFormatVertexException e) { + LOGGER.warn("Failed to format vertex, returning a partial list " + LogFormatTools.getStackTop(e)); + } catch (AAIFormatQueryResultFormatNotSupported e) { + LOGGER.warn("Failed to format result type of the query " + LogFormatTools.getStackTop(e)); + } + + return Optional.<JsonObject>empty(); + }).filter(Optional::isPresent) + .map(Optional::get) + .forEach(json -> { + if (isParallel) { + synchronized (body) { + body.add(json); + } + } else { + body.add(json); + } + }); + return body; + } + + @Override + public Optional<JsonObject> formatObject(Object input, Map<String, List<String>> properties) + throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported { + JsonObject json = new JsonObject(); + if (input instanceof ArrayList) { + Optional<JsonArray> ja = processInput(input, properties); + json.add("results", ja.get()); + } else { + throw new AAIFormatQueryResultFormatNotSupported(); + } + return Optional.of(json); + } + + private Optional<JsonArray> processInput(Object input, Map properties) throws AAIFormatVertexException { + JsonArray json = new JsonArray(); + for (Object l : (ArrayList) input) { + if (l instanceof ArrayList) { + JsonArray inner = new JsonArray(); + for (Vertex o : (ArrayList<Vertex>) l) { + if (o instanceof Vertex) { + Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) o, properties); + if (obj.isPresent()) { + inner.add(obj.get()); + } else { + continue; + } + } + } + json.add(inner); + } else { + Optional<JsonObject> obj = this.getJsonFromVertex((Vertex)l, properties); + json.add(obj.get()); + } + } + return Optional.of(json); + } + + public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> { + + protected final Loader loader; + protected final DBSerializer serializer; + protected final UrlBuilder urlBuilder; + protected boolean includeUrl = false; + protected boolean nodesOnly = false; + protected int depth = 1; + protected boolean modelDriven = false; + private boolean tree = false; + + public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { + this.loader = loader; + this.serializer = serializer; + this.urlBuilder = urlBuilder; + } + + protected boolean isTree() { return this.tree; } + + public Builder isTree(Boolean tree) { + this.tree = tree; + return this; + } + + protected Loader getLoader() { + return this.loader; + } + + protected DBSerializer getSerializer() { + return this.serializer; + } + + protected UrlBuilder getUrlBuilder() { + return this.urlBuilder; + } + + public Builder includeUrl() { + this.includeUrl = true; + return this; + } + + public Builder nodesOnly(Boolean nodesOnly) { + this.nodesOnly = nodesOnly; + return this; + } + + public boolean isNodesOnly() { + return this.nodesOnly; + } + + public Builder depth(Integer depth) { + this.depth = depth; + return this; + } + + public int getDepth() { + return this.depth; + } + + public boolean isIncludeUrl() { + return this.includeUrl; + } + + public Builder modelDriven() { + this.modelDriven = true; + return this; + } + + public boolean getModelDriven() { + return this.modelDriven; + } + + public Aggregate build() { + return new Aggregate(this); + } + } + + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException { + + JsonObject json = new JsonObject(); + json.addProperty("url", this.urlBuilder.pathed(v)); + Optional<JsonObject> properties = this.createPropertiesObject(v); + if (properties.isPresent()) { + json.add("properties", properties.get()); + } else { + return Optional.empty(); + } + return Optional.of(json); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ChangesFormat.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ChangesFormat.java new file mode 100644 index 00000000..bbaed360 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ChangesFormat.java @@ -0,0 +1,95 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.queryformats; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.onap.aai.config.SpringContextAware; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +public class ChangesFormat extends MultiFormatMapper { + + private Long startTs = 0L; + + public void startTs(String startTime) { + /* + * StartTs = truncate time + */ + if (startTime == null || startTime.isEmpty() || "now".equals(startTime) || "0".equals(startTime) || "-1".equals(startTime)){ + String historyTruncateDays = SpringContextAware.getApplicationContext().getEnvironment().getProperty("history.truncate.window.days", "365"); + this.startTs = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(Long.parseLong(historyTruncateDays)); + } else { + this.startTs = Long.parseLong(startTime); + } + } + + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex v) { + JsonObject json = new JsonObject(); + if (!v.properties(AAIProperties.RESOURCE_VERSION).hasNext() || + !v.properties(AAIProperties.NODE_TYPE).hasNext() || + !v.properties(AAIProperties.AAI_URI).hasNext()) { + return Optional.empty(); + } + json.addProperty("node-type", v.<String>value(AAIProperties.NODE_TYPE)); + json.addProperty("uri", v.<String>value(AAIProperties.AAI_URI)); + + final Set<Long> changes = new HashSet<>(); + v.properties(AAIProperties.RESOURCE_VERSION).forEachRemaining(o-> + o.properties(AAIProperties.START_TS, AAIProperties.END_TS) + .forEachRemaining(p -> { + Long val = (Long) p.value(); + if(val >= startTs) { + changes.add(val); + } + } + )); + v.edges(Direction.BOTH).forEachRemaining(e -> { + if(e.property(AAIProperties.START_TS).isPresent() && (Long)e.property(AAIProperties.START_TS).value() >= startTs) { + changes.add((Long) e.property(AAIProperties.START_TS).value()); + } + if(e.property(AAIProperties.END_TS).isPresent() && (Long)e.property(AAIProperties.END_TS).value() >= startTs) { + changes.add((Long) e.property(AAIProperties.END_TS).value()); + } + }); + + List<Long> sortedList = new ArrayList<>(changes); + sortedList.sort(Comparator.naturalOrder()); + JsonArray jsonArray = new JsonArray(); + sortedList.forEach(jsonArray::add); + + json.add("changes", jsonArray); + + return Optional.of(json); + } + + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex input, Map<String, List<String>> properties) throws AAIFormatVertexException { + return Optional.empty(); + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Console.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Console.java index ba20c652..7e230c3a 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Console.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Console.java @@ -22,8 +22,11 @@ package org.onap.aai.serialization.queryformats; import com.google.gson.JsonObject; +import java.util.List; +import java.util.Map; import java.util.Optional; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; public class Console implements FormatMapper { @@ -38,6 +41,13 @@ public class Console implements FormatMapper { } @Override + public Optional<JsonObject> formatObject(Object o, Map<String, List<String>> properties) throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported { + JsonObject json = new JsonObject(); + json.addProperty("result", o.toString()); + return Optional.of(json); + } + + @Override public int parallelThreshold() { return 100; } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Count.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Count.java index 8ee4e3a4..60a10c51 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Count.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Count.java @@ -23,6 +23,7 @@ package org.onap.aai.serialization.queryformats; import com.google.gson.JsonObject; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @@ -37,8 +38,7 @@ import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexExcepti public class Count implements FormatMapper { @Override - public Optional<JsonObject> formatObject(Object o) - throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported { + public Optional<JsonObject> formatObject(Object o) { @SuppressWarnings("unchecked") List<Object> list = (List<Object>) o; @@ -46,12 +46,17 @@ public class Count implements FormatMapper { list.stream().map(this::getCount).filter(Optional::isPresent).map(Optional::get) .collect(Collectors.toConcurrentMap(Pair::getValue0, Pair::getValue1, Long::sum)) - .forEach((k, v) -> countResult.addProperty(k, v)); + .forEach(countResult::addProperty); return Optional.of(countResult); } @Override + public Optional<JsonObject> formatObject(Object o, Map<String, List<String>> properties) throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported { + return Optional.empty(); + } + + @Override public int parallelThreshold() { return 20; } @@ -72,10 +77,10 @@ public class Count implements FormatMapper { } if (pair == null) { - return Optional.<Pair<String, Long>>empty(); + return Optional.empty(); } - return Optional.<Pair<String, Long>>of(pair); + return Optional.of(pair); } } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Format.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Format.java index 8de38117..f471b3c1 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Format.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Format.java @@ -23,7 +23,7 @@ package org.onap.aai.serialization.queryformats; import org.onap.aai.exceptions.AAIException; public enum Format { - graphson, pathed, pathed_resourceversion, id, resource, simple, resource_and_url, console, raw, count, resource_with_sot; + graphson, pathed, pathed_resourceversion, id, resource, simple, resource_and_url, console, raw, count, resource_with_sot, state, lifecycle, changes, aggregate; public static Format getFormat(String format) throws AAIException { try { diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatFactory.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatFactory.java index 854a20f4..0ae0c5fe 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatFactory.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatFactory.java @@ -20,9 +20,6 @@ package org.onap.aai.serialization.queryformats; -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.core.MultivaluedMap; - import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Loader; import org.onap.aai.serialization.db.DBSerializer; @@ -31,6 +28,9 @@ import org.onap.aai.serialization.queryformats.utils.QueryParamInjector; import org.onap.aai.serialization.queryformats.utils.UrlBuilder; import org.onap.aai.setup.SchemaVersions; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; + public class FormatFactory { private final Loader loader; @@ -47,7 +47,7 @@ public class FormatFactory { } public Formatter get(Format format) throws AAIException { - return get(format, new MultivaluedHashMap<String, String>()); + return get(format, new MultivaluedHashMap<>()); } public Formatter get(Format format, MultivaluedMap<String, String> params) throws AAIException { @@ -59,29 +59,34 @@ public class FormatFactory { formatter = new Formatter(inject(new GraphSON(), params)); break; case pathed: - formatter = new Formatter(inject(new PathedURL(loader, urlBuilder), params)); + formatter = new Formatter(inject(new PathedURL.Builder(loader, serializer, urlBuilder), params).build(), params); break; case pathed_resourceversion: - formatter = new Formatter(inject(new PathedURL(loader, urlBuilder).includeUrl(), params)); + formatter = new Formatter(inject(new PathedURL.Builder(loader, serializer, urlBuilder).includeUrl(), params).build(), params); break; case id: - formatter = new Formatter(inject(new IdURL(loader, urlBuilder), params)); + formatter = new Formatter(inject(new IdURL.Builder(loader, serializer, urlBuilder), params).build(), params); break; case resource: - formatter = new Formatter(inject(new Resource.Builder(loader, serializer, urlBuilder), params).build()); + formatter = new Formatter(inject(new Resource.Builder(loader, serializer, urlBuilder, params), params).build(), params); break; case resource_and_url: formatter = new Formatter( - inject(new Resource.Builder(loader, serializer, urlBuilder).includeUrl(), params).build()); + inject(new Resource.Builder(loader, serializer, urlBuilder, params).includeUrl(), params).build(), params); break; case raw: formatter = - new Formatter(inject(new RawFormat.Builder(loader, serializer, urlBuilder), params).build()); + new Formatter(inject(new RawFormat.Builder(loader, serializer, urlBuilder), params).build(), params); break; case simple: formatter = new Formatter( inject(new RawFormat.Builder(loader, serializer, urlBuilder).depth(0).modelDriven(), params) - .build()); + .build(), params); + break; + case aggregate: + formatter = new Formatter( + inject(new Aggregate.Builder(loader, serializer, urlBuilder).depth(0).modelDriven(), params) + .build(), params); break; case console: formatter = new Formatter(inject(new Console(), params)); @@ -91,7 +96,19 @@ public class FormatFactory { break; case resource_with_sot: formatter = new Formatter( - inject(new ResourceWithSoT.Builder(loader, serializer, urlBuilder), params).build()); + inject(new ResourceWithSoT.Builder(loader, serializer, urlBuilder), params).build(), params); + break; + case changes: + formatter = + new Formatter(inject(new ChangesFormat(), params)); + break; + case state: + formatter = + new Formatter(inject(new StateFormat.Builder(loader, serializer, urlBuilder), params).build(format)); + break; + case lifecycle: + formatter = + new Formatter(inject(new LifecycleFormat.Builder(loader, serializer, urlBuilder), params).build(format)); break; default: break; diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatMapper.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatMapper.java index 26af2e31..cf967f0f 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatMapper.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatMapper.java @@ -22,6 +22,8 @@ package org.onap.aai.serialization.queryformats; import com.google.gson.JsonObject; +import java.util.List; +import java.util.Map; import java.util.Optional; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; @@ -30,6 +32,7 @@ import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexExcepti public interface FormatMapper { Optional<JsonObject> formatObject(Object o) throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported; + Optional<JsonObject> formatObject(Object o, Map<String, List<String>> properties) throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported; int parallelThreshold(); } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Formatter.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Formatter.java index a19bd3f6..0e15173a 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Formatter.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Formatter.java @@ -20,46 +20,70 @@ package org.onap.aai.serialization.queryformats; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import org.json.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.onap.aai.logging.LogFormatTools; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import javax.ws.rs.core.MultivaluedMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Stream; -import org.onap.aai.logging.LogFormatTools; -import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; -import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; - public class Formatter { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(Formatter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(Formatter.class); - protected JsonParser parser = new JsonParser(); protected final FormatMapper format; + protected MultivaluedMap<String, String> params; public Formatter(FormatMapper format) { this.format = format; } - public JsonObject output(List<Object> queryResults) { + public Formatter(FormatMapper format, MultivaluedMap<String, String> params) { + this.format = format; + this.params = params; + } - Stream<Object> stream; - JsonObject result = new JsonObject(); - JsonArray body = new JsonArray(); + public JsonObject output(List<Object> queryResults, Map<String, List<String>> properties) { + + final JsonArray body; if (this.format instanceof Count) { JsonObject countResult; + body = new JsonArray(); try { countResult = format.formatObject(queryResults).orElseThrow(() -> new AAIFormatVertexException("")); body.add(countResult); } catch (Exception e) { LOGGER.warn("Failed to format result type of the query " + LogFormatTools.getStackTop(e)); } + } else if (this.format instanceof LifecycleFormat) { + LifecycleFormat lifecycleFormat = (LifecycleFormat) format; + body = lifecycleFormat.process(queryResults); + } else if (this.format instanceof Aggregate) { + Aggregate aggregateFormat = (Aggregate) format; + body = aggregateFormat.process(queryResults, properties); + JsonObject result = new JsonObject(); + if (body != null && body.size() > 0) { + result.add("results", (body.get(0)).getAsJsonObject().get("results")); + } + return result; } else { + + body = new JsonArray(); + Stream<Object> stream; if (queryResults.size() >= format.parallelThreshold()) { stream = queryResults.parallelStream(); } else { @@ -70,7 +94,11 @@ public class Formatter { stream.map(o -> { try { - return format.formatObject(o); + if (properties!= null && !properties.isEmpty()){ + return format.formatObject(o, properties); + } else { + return format.formatObject(o); + } } catch (AAIFormatVertexException e) { LOGGER.warn("Failed to format vertex, returning a partial list " + LogFormatTools.getStackTop(e)); } catch (AAIFormatQueryResultFormatNotSupported e) { @@ -78,19 +106,38 @@ public class Formatter { } return Optional.<JsonObject>empty(); - }).filter(Optional::isPresent).map(Optional::get).forEach(json -> { - if (isParallel) { - synchronized (body) { + }).filter(Optional::isPresent) + .map(Optional::get) + .forEach(json -> { + if (isParallel) { + synchronized (body) { + body.add(json); + } + } else { body.add(json); } - } else { - body.add(json); - } - }); + }); } + + if (params !=null && params.containsKey("as-tree")) { + String isAsTree = params.get("as-tree").get(0); + if (isAsTree != null && isAsTree.equalsIgnoreCase("true") + && body != null && body.size() != 0) { + JsonObject jsonObjectBody = body.get(0).getAsJsonObject(); + if (jsonObjectBody != null && jsonObjectBody.size() > 0) { + return body.get(0).getAsJsonObject(); + } + } + } + JsonObject result = new JsonObject(); result.add("results", body); return result.getAsJsonObject(); + + } + + public JsonObject output(List<Object> queryResults) { + return output(queryResults, null); } } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/GraphSON.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/GraphSON.java index eeac2195..609f6b0f 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/GraphSON.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/GraphSON.java @@ -28,16 +28,15 @@ import com.google.gson.JsonParser; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; +import java.util.*; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter; import org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; public class GraphSON implements FormatMapper { @@ -79,6 +78,11 @@ public class GraphSON implements FormatMapper { } + @Override + public Optional<JsonObject> formatObject(Object o, Map<String, List<String>> properties) throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported { + return Optional.empty(); + } + /** * Removes the private edges from the json object * diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/HistoryFormat.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/HistoryFormat.java new file mode 100644 index 00000000..b11f14aa --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/HistoryFormat.java @@ -0,0 +1,246 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.queryformats; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.tinkerpop.gremlin.structure.*; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.introspection.Loader; +import org.onap.aai.serialization.db.DBSerializer; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.onap.aai.serialization.queryformats.params.Depth; +import org.onap.aai.serialization.queryformats.params.EndTs; +import org.onap.aai.serialization.queryformats.params.NodesOnly; +import org.onap.aai.serialization.queryformats.params.StartTs; +import org.onap.aai.serialization.queryformats.utils.UrlBuilder; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public abstract class HistoryFormat extends MultiFormatMapper { + + private static final Logger LOGGER = LoggerFactory.getLogger(HistoryFormat.class); + + protected static final String KEY = "key"; + protected static final String VALUE = "value"; + protected static final String TIMESTAMP = "timestamp"; + protected static final String NODE_TYPE = "node-type"; + protected static final String END_TIMESTAMP = "end-timestamp"; + protected static final String SOT = "sot"; + protected static final String END_SOT = "end-sot"; + protected static final String TX_ID = "tx-id"; + protected static final String END_TX_ID = "end-tx-id"; + protected static final String PROPERTIES = "properties"; + protected static final String RELATED_TO = "related-to"; + protected static final String NODE_ACTIONS = "node-actions"; + + protected JsonParser parser = new JsonParser(); + protected final DBSerializer serializer; + protected final Loader loader; + protected final UrlBuilder urlBuilder; + protected final int depth; + protected final boolean nodesOnly; + protected long startTs; + protected long endTs; + protected static final Set<String> ignoredKeys = + Stream.of(AAIProperties.LAST_MOD_TS, AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, AAIProperties.CREATED_TS) + .collect(Collectors.toSet()); + + protected HistoryFormat(Builder builder) { + this.urlBuilder = builder.getUrlBuilder(); + this.loader = builder.getLoader(); + this.serializer = builder.getSerializer(); + this.depth = builder.getDepth(); + this.nodesOnly = builder.isNodesOnly(); + this.startTs = builder.getStartTs(); + this.endTs = builder.getEndTs(); + } + + @Override + public int parallelThreshold() { + return 100; + } + + protected JsonObject createMetaPropertiesObject(VertexProperty<Object> prop) { + JsonObject json = new JsonObject(); + Iterator iter = prop.properties(); + + while (iter.hasNext()) { + Property<Object> metaProp = (Property) iter.next(); + mapPropertyValues(json, metaProp.key(), metaProp.value()); + } + + return json; + } + + protected JsonObject mapPropertyValues(JsonObject json, String propertyKey, Object propertyValue) { + if (propertyValue instanceof String) { + json.addProperty(propertyKey, (String) propertyValue); + } else if (propertyValue instanceof Boolean) { + json.addProperty(propertyKey, (Boolean) propertyValue); + } else if (propertyValue instanceof Number) { + json.addProperty(propertyKey, (Number) propertyValue); + } else { + if (!(propertyValue instanceof List)) { + return json; + } + + Gson gson = new Gson(); + String list = gson.toJson(propertyValue); + json.addProperty(propertyKey, list); + } + return json; + } + + protected JsonArray createRelationshipObject(Vertex v) throws AAIFormatVertexException { + JsonArray relatedToList = new JsonArray(); + Iterator<Edge> inIter = v.edges(Direction.IN); + Iterator<Edge> outIter = v.edges(Direction.OUT); + + while (inIter.hasNext()) { + Edge e = inIter.next(); + if (isValidEdge(e)) { + relatedToList.add(getRelatedObject(e, e.outVertex())); + } + } + + while (outIter.hasNext()) { + Edge e = outIter.next(); + if (isValidEdge(e)) { + relatedToList.add(getRelatedObject(e, e.inVertex())); + } + } + + return relatedToList; + + } + + protected abstract boolean isValidEdge(Edge e); + + protected abstract JsonObject getRelatedObject(Edge e, Vertex related) throws AAIFormatVertexException; + + + + public static class Builder implements NodesOnly<Builder>, Depth<Builder>, StartTs<Builder>, EndTs<Builder> { + + protected final Loader loader; + protected final DBSerializer serializer; + protected final UrlBuilder urlBuilder; + protected boolean includeUrl = false; + protected boolean nodesOnly = false; + protected int depth = 1; + protected boolean modelDriven = false; + protected long startTs = -1; + protected long endTs = -1; + + public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { + this.loader = loader; + this.serializer = serializer; + this.urlBuilder = urlBuilder; + } + + protected Loader getLoader() { + return this.loader; + } + + protected DBSerializer getSerializer() { + return this.serializer; + } + + protected UrlBuilder getUrlBuilder() { + return this.urlBuilder; + } + + public Builder includeUrl() { + this.includeUrl = true; + return this; + } + + public Builder nodesOnly(Boolean nodesOnly) { + this.nodesOnly = nodesOnly; + return this; + } + + public Builder startTs(String startTs) { + this.startTs = Long.parseLong(startTs); + return this; + } + + public Builder endTs(String endTs) { + this.endTs = Long.parseLong(endTs); + return this; + } + + + public boolean isNodesOnly() { + return this.nodesOnly; + } + + public Builder depth(Integer depth) { + this.depth = depth; + return this; + } + + public int getDepth() { + return this.depth; + } + + public boolean isIncludeUrl() { + return this.includeUrl; + } + + public Builder modelDriven() { + this.modelDriven = true; + return this; + } + + public boolean getModelDriven() { + return this.modelDriven; + } + + public long getStartTs() { + return this.startTs; + } + + public long getEndTs() { + return this.endTs; + } + + public HistoryFormat build(Format format) { + + if(Format.state.equals(format)) { + return new StateFormat(this); + } else { + return new LifecycleFormat(this); + } + + } + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/IdURL.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/IdURL.java index c5cb9254..c2c252a2 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/IdURL.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/IdURL.java @@ -23,6 +23,8 @@ package org.onap.aai.serialization.queryformats; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import java.util.List; +import java.util.Map; import java.util.Optional; import org.apache.tinkerpop.gremlin.structure.Vertex; @@ -31,9 +33,15 @@ 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.serialization.db.DBSerializer; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.onap.aai.serialization.queryformats.params.AsTree; +import org.onap.aai.serialization.queryformats.params.Depth; +import org.onap.aai.serialization.queryformats.params.NodesOnly; import org.onap.aai.serialization.queryformats.utils.UrlBuilder; +import javax.ws.rs.core.MultivaluedMap; + public class IdURL extends MultiFormatMapper { private final UrlBuilder urlBuilder; @@ -46,6 +54,13 @@ public class IdURL extends MultiFormatMapper { this.loader = loader; } + public IdURL(Builder builder) throws AAIException { + this.urlBuilder = builder.getUrlBuilder(); + this.parser = new JsonParser(); + this.loader = builder.getLoader(); + this.isTree = builder.isTree(); + } + @Override public int parallelThreshold() { return 2500; @@ -69,4 +84,101 @@ public class IdURL extends MultiFormatMapper { } } + + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex input, Map<String, List<String>> properties) throws AAIFormatVertexException { + return Optional.empty(); + } + + public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> { + + private final Loader loader; + private final DBSerializer serializer; + private final UrlBuilder urlBuilder; + private boolean includeUrl = false; + private boolean nodesOnly = false; + private int depth = 1; + private MultivaluedMap<String, String> params; + private boolean tree = false; + + public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { + this.loader = loader; + this.serializer = serializer; + this.urlBuilder = urlBuilder; + } + + public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder, MultivaluedMap<String, String> params) { + this.loader = loader; + this.serializer = serializer; + this.urlBuilder = urlBuilder; + this.params = params; + } + + protected Loader getLoader() { + return this.loader; + } + + protected DBSerializer getSerializer() { + return this.serializer; + } + + protected UrlBuilder getUrlBuilder() { + return this.urlBuilder; + } + + protected MultivaluedMap<String, String> getParams() { return this.params; } + + public boolean isSkipRelatedTo() { + if (params != null) { + boolean isSkipRelatedTo = true; + if (params.containsKey("skip-related-to")) { + String skipRelatedTo = params.getFirst("skip-related-to"); + isSkipRelatedTo = !(skipRelatedTo != null && skipRelatedTo.equals("false")); + } else { + // if skip-related-to param is missing, then default it to false; + isSkipRelatedTo = false; + } + return isSkipRelatedTo; + } + return true; + } + + protected boolean isTree() { return this.tree; } + + public Builder isTree(Boolean tree) { + this.tree = tree; + return this; + } + + public Builder includeUrl() { + this.includeUrl = true; + return this; + } + + public Builder nodesOnly(Boolean nodesOnly) { + this.nodesOnly = nodesOnly; + return this; + } + + public boolean isNodesOnly() { + return this.nodesOnly; + } + + public Builder depth(Integer depth) { + this.depth = depth; + return this; + } + + public int getDepth() { + return this.depth; + } + + public boolean isIncludeUrl() { + return this.includeUrl; + } + + public IdURL build() throws AAIException { + return new IdURL(this); + } + } } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/LifecycleFormat.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/LifecycleFormat.java new file mode 100644 index 00000000..57bb17c2 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/LifecycleFormat.java @@ -0,0 +1,313 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.queryformats; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.logging.LogFormatTools; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + +public class LifecycleFormat extends HistoryFormat { + + private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleFormat.class); + + protected LifecycleFormat(Builder builder) { + super(builder); + } + + protected JsonArray createPropertiesObject(Vertex v) { + JsonArray jsonArray = new JsonArray(); + Iterator<VertexProperty<Object>> iter = v.properties(); + List<JsonObject> jsonList = new ArrayList<>(); + + Map<String, Set<Long>> propStartTimes = new HashMap<>(); //vertex end + while (iter.hasNext()) { + JsonObject json = new JsonObject(); + VertexProperty<Object> prop = iter.next(); + if(prop.key() != null && ignoredKeys.contains(prop.key())){ + continue; + } + if (!propStartTimes.containsKey(prop.key())) { + propStartTimes.put(prop.key(), new HashSet<>()); + if (v.property(AAIProperties.END_TS).isPresent()) { + propStartTimes.get(prop.key()).add(v.<Long>value(AAIProperties.END_TS)); + } + } + + json.addProperty(KEY, prop.key()); + json = mapPropertyValues(json, VALUE, prop.value()); + JsonObject metaProperties = createMetaPropertiesObject(prop); + if (isTsInRange(metaProperties.get(AAIProperties.START_TS).getAsLong())) { + JsonObject jo = new JsonObject(); + jo.add(KEY, json.get(KEY)); + jo.add(VALUE, json.get(VALUE)); + jo.add(TIMESTAMP, metaProperties.get(AAIProperties.START_TS)); + jo.add(SOT, metaProperties.get(AAIProperties.SOURCE_OF_TRUTH)); + jo.add(TX_ID, metaProperties.get(AAIProperties.START_TX_ID)); + jsonList.add(jo); + propStartTimes.get(prop.key()).add(metaProperties.get(AAIProperties.START_TS).getAsLong()); + } + if (!AAIProperties.RESOURCE_VERSION.equals(prop.key()) + && metaProperties.has(AAIProperties.END_TS) + && isTsInRange(metaProperties.get(AAIProperties.END_TS).getAsLong()) + && !propStartTimes.get(prop.key()).contains(metaProperties.get(AAIProperties.END_TS).getAsLong())) { + JsonObject jo = new JsonObject(); + jo.add(KEY, json.get(KEY)); + jo.add(VALUE, null); + jo.add(TIMESTAMP, metaProperties.get(AAIProperties.END_TS)); + jo.add(SOT, metaProperties.get(AAIProperties.END_SOT)); + jo.add(TX_ID, metaProperties.get(AAIProperties.END_TX_ID)); + jsonList.add(jo); + } + + } + jsonList.stream() + // remove all the null values that is the start time for another value + .filter(jo -> !jo.get(VALUE).isJsonNull() || !propStartTimes.get(jo.get(KEY).getAsString()).contains(jo.get(TIMESTAMP).getAsLong())) + // sort by ts in decreasing order + .sorted((o1, o2) -> { + if (o1.get(TIMESTAMP).getAsLong() == o2.get(TIMESTAMP).getAsLong()) { + return o1.get(KEY).getAsString().compareTo(o2.get(KEY).getAsString()); + } else { + return Long.compare(o2.get(TIMESTAMP).getAsLong(), o1.get(TIMESTAMP).getAsLong()); + } + }).forEach(jsonArray::add); + + return jsonArray; + } + + private boolean isTsInRange(long ts) { + return ts >= startTs && ts <= endTs; + } + + + @Override + protected boolean isValidEdge(Edge e) { + if (e.property(AAIProperties.END_TS).isPresent()) { + long edgeStartTs = e.<Long>value(AAIProperties.START_TS); + long edgeEndTs = e.<Long>value(AAIProperties.END_TS); + return isTsInRange(edgeStartTs) || isTsInRange(edgeEndTs); + } else { + long edgeStartTs = e.<Long>value(AAIProperties.START_TS); + return isTsInRange(edgeStartTs); + } + } + + @Override + protected JsonObject getRelatedObject(Edge e, Vertex related) throws AAIFormatVertexException { + + JsonObject json = new JsonObject(); + json.addProperty("relationship-label", e.label()); + json.addProperty("node-type", related.<String>value(AAIProperties.NODE_TYPE)); + json.addProperty("url", this.urlBuilder.pathed(related)); + if (related.property(AAIProperties.AAI_URI).isPresent()) { + json.addProperty("uri", related.<String>value(AAIProperties.AAI_URI)); + } else { + LOGGER.warn("Vertex {} is missing aai-uri", related.id()); + json.addProperty("uri", "NA"); + } + + if(e.property(AAIProperties.START_TS).isPresent()) { + long edgeStartTimestamp = e.<Long>value(AAIProperties.START_TS); + if (isTsInRange(edgeStartTimestamp)) { + json.addProperty(TIMESTAMP, e.property(AAIProperties.START_TS).isPresent()? e.<Long>value(AAIProperties.START_TS) : 0); + json.addProperty(SOT, e.property(AAIProperties.SOURCE_OF_TRUTH).isPresent()? e.value(AAIProperties.SOURCE_OF_TRUTH) : ""); + json.addProperty(TX_ID, e.property(AAIProperties.START_TX_ID).isPresent()? e.value(AAIProperties.START_TX_ID) : "N/A"); + } + } + + if(e.property(AAIProperties.END_TS).isPresent()) { + long edgeEndTimestamp = e.<Long>value(AAIProperties.END_TS); + if (isTsInRange(edgeEndTimestamp)) { + json.addProperty(END_TIMESTAMP, edgeEndTimestamp); + json.addProperty(END_SOT, e.property(AAIProperties.END_SOT).isPresent() ? e.value(AAIProperties.END_SOT) : ""); + json.addProperty(END_TX_ID, e.property(AAIProperties.END_TX_ID).isPresent() ? e.value(AAIProperties.END_TX_ID) : "N/A"); + } + } + + return json; + } + + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException { + JsonObject json = new JsonObject(); + json.addProperty(NODE_TYPE, v.<String>value(AAIProperties.NODE_TYPE)); + json.addProperty("url", this.urlBuilder.pathed(v)); + if (v.property(AAIProperties.AAI_URI).isPresent()) { + json.addProperty("uri", v.<String>value(AAIProperties.AAI_URI)); + } else { + LOGGER.warn("Vertex {} is missing aai-uri", v.id()); + json.addProperty("uri", "NA"); + } + json.addProperty(TIMESTAMP, v.<Long>value(AAIProperties.START_TS)); + + json.add(PROPERTIES, this.createPropertiesObject(v)); + + if (!nodesOnly) { + json.add(RELATED_TO, this.createRelationshipObject(v)); + } + + json.add(NODE_ACTIONS, getNodeActions(v, json)); + + if (json.getAsJsonObject().get(PROPERTIES).getAsJsonArray().size() == 0 + && json.getAsJsonObject().get(RELATED_TO).getAsJsonArray().size() == 0 + && json.getAsJsonObject().get(NODE_ACTIONS).getAsJsonArray().size() == 0) { + return Optional.empty(); + } else if (json.getAsJsonObject().get(PROPERTIES).getAsJsonArray().size() == 1 + && (json.getAsJsonObject().get(RELATED_TO).getAsJsonArray().size() > 0 + || json.getAsJsonObject().get(NODE_ACTIONS).getAsJsonArray().size() > 0)) { + if (json.getAsJsonObject().get(PROPERTIES).getAsJsonArray() + .get(0).getAsJsonObject().get("key").getAsString().equals(AAIProperties.END_TS)) { + json.getAsJsonObject().add(PROPERTIES, new JsonArray()); + } + } + + return Optional.of(json); + } + + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex input, Map<String, List<String>> properties) throws AAIFormatVertexException { + return Optional.empty(); + } + + private JsonArray getNodeActions(Vertex v, JsonObject json) { + JsonArray nodeActions = new JsonArray(); + JsonObject action; + if (v.property(AAIProperties.END_TS).isPresent()) { + long deletedTs = (Long) v.property(AAIProperties.END_TS).value(); + if (isTsInRange(deletedTs)) { + action = new JsonObject(); + action.addProperty("action", "DELETED"); + action.addProperty(TIMESTAMP, deletedTs); + if (v.property(AAIProperties.END_TS).property(AAIProperties.SOURCE_OF_TRUTH).isPresent()) { + action.addProperty(SOT, v.property(AAIProperties.END_TS).<String>value(AAIProperties.SOURCE_OF_TRUTH)); + } + if (v.property(AAIProperties.END_TS).property(AAIProperties.END_TX_ID).isPresent()) { + action.addProperty(TX_ID, v.property(AAIProperties.END_TS).<String>value(AAIProperties.END_TX_ID)); + } else { + action.addProperty(TX_ID, "N/A"); + } + nodeActions.add(action); + } + } + long createdTs = json.get(TIMESTAMP).getAsLong(); + if (isTsInRange(createdTs)) { + action = new JsonObject(); + action.addProperty("action", "CREATED"); + action.addProperty(TIMESTAMP, createdTs); + action.addProperty(SOT, v.<String>value(AAIProperties.SOURCE_OF_TRUTH)); + if (v.property(AAIProperties.SOURCE_OF_TRUTH).property(AAIProperties.START_TX_ID).isPresent()) { + action.addProperty(TX_ID, v.property(AAIProperties.SOURCE_OF_TRUTH).<String>value(AAIProperties.START_TX_ID)); + } else { + action.addProperty(TX_ID, "N/A"); + } + nodeActions.add(action); + } + return nodeActions; + } + + public JsonArray process(List<Object> queryResults) { + JsonArray body = new JsonArray(); + Stream<Object> stream; + if (queryResults.size() >= this.parallelThreshold()) { + stream = queryResults.parallelStream(); + } else { + stream = queryResults.stream(); + } + + final boolean isParallel = stream.isParallel(); + + stream.map(o -> { + try { + return this.formatObject(o); + } catch (AAIFormatVertexException e) { + LOGGER.warn("Failed to format vertex, returning a partial list " + LogFormatTools.getStackTop(e)); + } catch (AAIFormatQueryResultFormatNotSupported e) { + LOGGER.warn("Failed to format result type of the query " + LogFormatTools.getStackTop(e)); + } + + return Optional.<JsonObject>empty(); + }).filter(Optional::isPresent) + .map(Optional::get) + .forEach(json -> { + if (isParallel) { + synchronized (body) { + body.add(json); + } + } else { + body.add(json); + } + }); + JsonArray result = organizeBody(body); + result.forEach(jsonElement -> jsonElement.getAsJsonObject().remove(TIMESTAMP)); + return result; + } + + private JsonArray organizeBody(JsonArray body) { + + final MultiValueMap<String, Integer> toBeMerged = new LinkedMultiValueMap<>(); + for (int i = 0; i < body.size(); i++) { + toBeMerged.add(body.get(i).getAsJsonObject().get("uri").getAsString(), i); + } + + final List<List<Integer>> dupes = toBeMerged.values().stream().filter(l -> l.size() > 1).collect(Collectors.toList()); + if (dupes.isEmpty()) { + return body; + } else { + Set<Integer> remove = new HashSet<>(); + for (List<Integer> dupe : dupes) { + dupe.sort((a,b) -> Long.compare(body.get(b).getAsJsonObject().get(TIMESTAMP).getAsLong(), body.get(a).getAsJsonObject().get(TIMESTAMP).getAsLong())); + int keep = dupe.remove(0); + for (Integer idx : dupe) { + body.get(keep).getAsJsonObject().getAsJsonArray(NODE_ACTIONS) + .addAll(body.get(idx).getAsJsonObject().getAsJsonArray(NODE_ACTIONS)); + body.get(keep).getAsJsonObject().getAsJsonArray(PROPERTIES) + .addAll(body.get(idx).getAsJsonObject().getAsJsonArray(PROPERTIES)); + body.get(keep).getAsJsonObject().getAsJsonArray(RELATED_TO) + .addAll(body.get(idx).getAsJsonObject().getAsJsonArray(RELATED_TO)); + remove.add(idx); + } + } + final JsonArray newBody = new JsonArray(); + for (int i = 0; i < body.size(); i++) { + if (!remove.contains(i)) { + newBody.add(body.get(i)); + } + } + return newBody; + } + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/MultiFormatMapper.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/MultiFormatMapper.java index 21b666f2..b06ef7c3 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/MultiFormatMapper.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/MultiFormatMapper.java @@ -22,26 +22,49 @@ package org.onap.aai.serialization.queryformats; import com.google.gson.JsonArray; import com.google.gson.JsonObject; - -import java.util.Iterator; -import java.util.List; -import java.util.Optional; - import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import java.util.List; +import java.util.Map; +import java.util.Optional; + public abstract class MultiFormatMapper implements FormatMapper { + protected boolean isTree = false; + @Override public Optional<JsonObject> formatObject(Object input) throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported { if (input instanceof Vertex) { return this.getJsonFromVertex((Vertex) input); } else if (input instanceof Tree) { - return this.getJsonFomTree((Tree<?>) input); + if (isTree) { + return this.getRelatedNodesFromTree((Tree<?>) input); + } else { + return this.getJsonFomTree((Tree<?>) input); + } + } else if (input instanceof Path) { + return this.getJsonFromPath((Path) input); + } else { + throw new AAIFormatQueryResultFormatNotSupported(); + } + } + + @Override + public Optional<JsonObject> formatObject(Object input, Map<String, List<String>> properties) + throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported { + if (input instanceof Vertex) { + return this.getJsonFromVertex((Vertex) input, properties); + } else if (input instanceof Tree) { + if (isTree) { + return this.getRelatedNodesFromTree((Tree<?>) input); + } else { + return this.getJsonFomTree((Tree<?>) input); + } } else if (input instanceof Path) { return this.getJsonFromPath((Path) input); } else { @@ -50,6 +73,7 @@ public abstract class MultiFormatMapper implements FormatMapper { } protected abstract Optional<JsonObject> getJsonFromVertex(Vertex input) throws AAIFormatVertexException; + protected abstract Optional<JsonObject> getJsonFromVertex(Vertex input, Map<String, List<String>> properties) throws AAIFormatVertexException; protected Optional<JsonObject> getJsonFromPath(Path input) throws AAIFormatVertexException { List<Object> path = input.objects(); @@ -59,7 +83,8 @@ public abstract class MultiFormatMapper implements FormatMapper { for (Object o : path) { if (o instanceof Vertex) { - ja.add(this.getJsonFromVertex((Vertex) o).get()); + Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) o); + obj.ifPresent(ja::add); } } @@ -74,7 +99,7 @@ public abstract class MultiFormatMapper implements FormatMapper { } JsonObject t = new JsonObject(); - JsonArray ja = this.getNodesArray(tree); + JsonArray ja = this.getNodesArray(tree, "nodes"); if (ja.size() > 0) { t.add("nodes", ja); } @@ -82,20 +107,37 @@ public abstract class MultiFormatMapper implements FormatMapper { return Optional.of(t); } - private JsonArray getNodesArray(Tree<?> tree) throws AAIFormatVertexException { + protected Optional<JsonObject> getRelatedNodesFromTree(Tree<?> tree) throws AAIFormatVertexException { + if (tree.isEmpty()) { + return Optional.of(new JsonObject()); + } - JsonArray nodes = new JsonArray(); - Iterator<?> it = tree.keySet().iterator(); + JsonObject t = new JsonObject(); + JsonArray ja = this.getNodesArray(tree, "related-nodes"); + if (ja.size() > 0) { + t.add("results", ja); + return Optional.of(t); + } + + return Optional.empty(); + } + + protected JsonArray getNodesArray(Tree<?> tree, String nodeIdentifier) throws AAIFormatVertexException { - while (it.hasNext()) { - Object o = it.next(); + JsonArray nodes = new JsonArray(); + for (Map.Entry<?, ? extends Tree<?>> entry : tree.entrySet()) { JsonObject me = new JsonObject(); - if (o instanceof Vertex) { - me = this.getJsonFromVertex((Vertex) o).get(); + if (entry.getKey() instanceof Vertex) { + Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) entry.getKey()); + if (obj.isPresent()) { + me = obj.get(); + } else { + continue; + } } - JsonArray ja = this.getNodesArray((Tree<?>) tree.get(o)); + JsonArray ja = this.getNodesArray(entry.getValue(), nodeIdentifier); if (ja.size() > 0) { - me.add("nodes", ja); + me.add(nodeIdentifier, ja); } nodes.add(me); } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/PathedURL.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/PathedURL.java index a99ba7f4..417f73cd 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/PathedURL.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/PathedURL.java @@ -23,6 +23,8 @@ package org.onap.aai.serialization.queryformats; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import java.util.List; +import java.util.Map; import java.util.Optional; import org.apache.tinkerpop.gremlin.structure.Vertex; @@ -31,9 +33,15 @@ 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.serialization.db.DBSerializer; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.onap.aai.serialization.queryformats.params.AsTree; +import org.onap.aai.serialization.queryformats.params.Depth; +import org.onap.aai.serialization.queryformats.params.NodesOnly; import org.onap.aai.serialization.queryformats.utils.UrlBuilder; +import javax.ws.rs.core.MultivaluedMap; + public final class PathedURL extends MultiFormatMapper { private final UrlBuilder urlBuilder; @@ -47,6 +55,13 @@ public final class PathedURL extends MultiFormatMapper { this.loader = loader; } + public PathedURL(Builder builder) { + this.urlBuilder = builder.getUrlBuilder(); + this.parser = new JsonParser(); + this.loader = builder.getLoader(); + this.isTree = builder.isTree(); + } + @Override public int parallelThreshold() { return 20; @@ -79,4 +94,101 @@ public final class PathedURL extends MultiFormatMapper { } + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex input, Map<String, List<String>> properties) throws AAIFormatVertexException { + return Optional.empty(); + } + + public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> { + + private final Loader loader; + private final DBSerializer serializer; + private final UrlBuilder urlBuilder; + private boolean includeUrl = false; + private boolean nodesOnly = false; + private int depth = 1; + private MultivaluedMap<String, String> params; + private boolean tree = false; + + public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { + this.loader = loader; + this.serializer = serializer; + this.urlBuilder = urlBuilder; + } + + public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder, MultivaluedMap<String, String> params) { + this.loader = loader; + this.serializer = serializer; + this.urlBuilder = urlBuilder; + this.params = params; + } + + protected Loader getLoader() { + return this.loader; + } + + protected DBSerializer getSerializer() { + return this.serializer; + } + + protected UrlBuilder getUrlBuilder() { + return this.urlBuilder; + } + + protected MultivaluedMap<String, String> getParams() { return this.params; } + + public boolean isSkipRelatedTo() { + if (params != null) { + boolean isSkipRelatedTo = true; + if (params.containsKey("skip-related-to")) { + String skipRelatedTo = params.getFirst("skip-related-to"); + isSkipRelatedTo = !(skipRelatedTo != null && skipRelatedTo.equals("false")); + } else { + // if skip-related-to param is missing, then default it to false; + isSkipRelatedTo = false; + } + return isSkipRelatedTo; + } + return true; + } + + protected boolean isTree() { return this.tree; } + + public Builder isTree(Boolean tree) { + this.tree = tree; + return this; + } + + public Builder includeUrl() { + this.includeUrl = true; + return this; + } + + public Builder nodesOnly(Boolean nodesOnly) { + this.nodesOnly = nodesOnly; + return this; + } + + public boolean isNodesOnly() { + return this.nodesOnly; + } + + public Builder depth(Integer depth) { + this.depth = depth; + return this; + } + + public int getDepth() { + return this.depth; + } + + public boolean isIncludeUrl() { + return this.includeUrl; + } + + public PathedURL build() throws AAIException { + return new PathedURL(this); + } + } + } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/RawFormat.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/RawFormat.java index 8636ebfa..8dcd3a83 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/RawFormat.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/RawFormat.java @@ -25,9 +25,8 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; @@ -38,6 +37,7 @@ import org.onap.aai.introspection.Loader; import org.onap.aai.serialization.db.DBSerializer; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; import org.onap.aai.serialization.queryformats.params.Depth; +import org.onap.aai.serialization.queryformats.params.AsTree; import org.onap.aai.serialization.queryformats.params.NodesOnly; import org.onap.aai.serialization.queryformats.utils.UrlBuilder; @@ -55,6 +55,25 @@ public class RawFormat extends MultiFormatMapper { this.serializer = builder.getSerializer(); this.depth = builder.getDepth(); this.nodesOnly = builder.isNodesOnly(); + this.isTree = builder.isTree(); + } + + @Override + public Optional<JsonObject> getJsonFromVertex(Vertex v, Map<String, List<String>> selectedProps) throws AAIFormatVertexException { + JsonObject json = new JsonObject(); + json.addProperty("id", v.id().toString()); + json.addProperty("node-type", v.<String>value(AAIProperties.NODE_TYPE)); + json.addProperty("url", this.urlBuilder.pathed(v)); + Optional<JsonObject> properties = this.createSelectedPropertiesObject(v, selectedProps); + if (properties.isPresent()) { + json.add("properties", properties.get()); + } else { + return Optional.empty(); + } + if (!nodesOnly) { + json.add("related-to", this.createRelationshipObject(v)); + } + return Optional.of(json); } @Override @@ -88,6 +107,48 @@ public class RawFormat extends MultiFormatMapper { return Optional.of(json); } + public Optional<JsonObject> createSelectedPropertiesObject(Vertex v, Map<String, List<String>> selectedProps) throws AAIFormatVertexException { + JsonObject json = new JsonObject(); + String nodeType = v.<String>value(AAIProperties.NODE_TYPE); + Set<String> propList = removeSingleQuotesForProperties(selectedProps.get(nodeType)); + Iterator<VertexProperty<Object>> iter = v.properties(); + + Gson gson = new Gson(); + while (iter.hasNext()) { + VertexProperty<Object> prop = iter.next(); + if (propList != null && !propList.isEmpty()) { + if (propList.contains(prop.label())) { + if (prop.value() instanceof String) { + json.addProperty(prop.key(), (String) prop.value()); + } else if (prop.value() instanceof Boolean) { + json.addProperty(prop.key(), (Boolean) prop.value()); + } else if (prop.value() instanceof Number) { + json.addProperty(prop.key(), (Number) prop.value()); + } else if (prop.value() instanceof List) { + json.addProperty(prop.key(), gson.toJson(prop.value())); + } else { + // throw exception? + return null; + } + } + } else { + return this.createPropertiesObject(v); + } + } + + return Optional.of(json); + } + + private Set<String> removeSingleQuotesForProperties(List<String> props){ + if (props != null && !props.isEmpty()) { + return props.stream().map( + e -> e.substring(1, e.length()-1)).collect(Collectors.toSet()); + } else { + return Collections.emptySet(); + } + + } + protected JsonArray createRelationshipObject(Vertex v) throws AAIFormatVertexException { JsonArray jarray = new JsonArray(); Iterator<Edge> inIter = v.edges(Direction.IN); @@ -122,7 +183,7 @@ public class RawFormat extends MultiFormatMapper { return json; } - public static class Builder implements NodesOnly<Builder>, Depth<Builder> { + public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> { protected final Loader loader; protected final DBSerializer serializer; @@ -131,6 +192,7 @@ public class RawFormat extends MultiFormatMapper { protected boolean nodesOnly = false; protected int depth = 1; protected boolean modelDriven = false; + protected boolean tree = false; public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { this.loader = loader; @@ -150,6 +212,13 @@ public class RawFormat extends MultiFormatMapper { return this.urlBuilder; } + protected boolean isTree() { return this.tree; } + + public Builder isTree(Boolean tree) { + this.tree = tree; + return this; + } + public Builder includeUrl() { this.includeUrl = true; return this; diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Resource.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Resource.java index b92f5858..a53be6a3 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Resource.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Resource.java @@ -20,14 +20,17 @@ package org.onap.aai.serialization.queryformats; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; +import java.util.*; +import java.util.stream.Stream; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.onap.aai.db.props.AAIProperties; import org.onap.aai.exceptions.AAIException; @@ -37,9 +40,12 @@ import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.onap.aai.serialization.db.DBSerializer; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; import org.onap.aai.serialization.queryformats.params.Depth; +import org.onap.aai.serialization.queryformats.params.AsTree; import org.onap.aai.serialization.queryformats.params.NodesOnly; import org.onap.aai.serialization.queryformats.utils.UrlBuilder; +import javax.ws.rs.core.MultivaluedMap; + public class Resource extends MultiFormatMapper { private final Loader loader; @@ -49,8 +55,9 @@ public class Resource extends MultiFormatMapper { private final boolean includeUrl; private final boolean nodesOnly; private final int depth; + private final boolean isSkipRelatedTo; - private Resource(Builder builder) { + public Resource(Builder builder) { this.parser = new JsonParser(); this.loader = builder.getLoader(); this.serializer = builder.getSerializer(); @@ -58,6 +65,54 @@ public class Resource extends MultiFormatMapper { this.includeUrl = builder.isIncludeUrl(); this.nodesOnly = builder.isNodesOnly(); this.depth = builder.getDepth(); + this.isSkipRelatedTo = builder.isSkipRelatedTo(); + this.isTree = builder.isTree(); + } + + @Override + protected Optional<JsonObject> getRelatedNodesFromTree(Tree<?> tree) throws AAIFormatVertexException { + if (tree.isEmpty()) { + return Optional.of(new JsonObject()); + } + JsonObject t = new JsonObject(); + JsonArray ja = this.getRelatedNodesArray(tree, "related-nodes"); + if (ja.size() > 0) { + t.add("results", ja); + return Optional.of(t); + } + + return Optional.empty(); + } + + protected JsonArray getRelatedNodesArray(Tree<?> tree, String nodeIdentifier) throws AAIFormatVertexException { + JsonArray nodes = new JsonArray(); + if (tree.isEmpty()) { + return nodes; + } + for (Map.Entry<?, ? extends Tree<?>> entry : tree.entrySet()) { + JsonObject me = new JsonObject(); + if (entry.getKey() instanceof Vertex) { + Optional<JsonObject> obj = null; + if (entry.getKey() != null) { + obj = this.getJsonFromVertex((Vertex) entry.getKey()); + } + if (obj != null && obj.isPresent()) { + me = obj.get(); + } else { + continue; + } + } + JsonArray ja = this.getRelatedNodesArray(entry.getValue(), nodeIdentifier); + if (ja.size() > 0) { + try { + me.entrySet().stream().findFirst().get().getValue().getAsJsonObject().add(nodeIdentifier, ja); + } catch(Exception e) { + throw new AAIFormatVertexException("Failed to add related-nodes array: " + e.getMessage(), e); + } + } + nodes.add(me); + } + return nodes; } @Override @@ -77,7 +132,15 @@ public class Resource extends MultiFormatMapper { return Optional.of(json); } + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex input, Map<String, List<String>> properties) throws AAIFormatVertexException { + return Optional.empty(); + } + protected Optional<JsonObject> vertexToJsonObject(Vertex v) throws AAIFormatVertexException { + if (v == null) { + return Optional.empty(); + } try { final Introspector obj = getLoader().introspectorFromName(v.<String>property(AAIProperties.NODE_TYPE).orElse(null)); @@ -87,7 +150,7 @@ public class Resource extends MultiFormatMapper { wrapper.add(v); try { - getSerializer().dbToObject(wrapper, obj, this.depth, this.nodesOnly, "false"); + getSerializer().dbToObject(wrapper, obj, this.depth, this.nodesOnly, "false", isSkipRelatedTo); } catch (AAIException | UnsupportedEncodingException e) { throw new AAIFormatVertexException( "Failed to format vertex - error while serializing: " + e.getMessage(), e); @@ -118,7 +181,7 @@ public class Resource extends MultiFormatMapper { return parser; } - public static class Builder implements NodesOnly<Builder>, Depth<Builder> { + public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> { private final Loader loader; private final DBSerializer serializer; @@ -126,6 +189,8 @@ public class Resource extends MultiFormatMapper { private boolean includeUrl = false; private boolean nodesOnly = false; private int depth = 1; + private MultivaluedMap<String, String> params; + private boolean tree = false; public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { this.loader = loader; @@ -133,6 +198,13 @@ public class Resource extends MultiFormatMapper { this.urlBuilder = urlBuilder; } + public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder, MultivaluedMap<String, String> params) { + this.loader = loader; + this.serializer = serializer; + this.urlBuilder = urlBuilder; + this.params = params; + } + protected Loader getLoader() { return this.loader; } @@ -145,6 +217,31 @@ public class Resource extends MultiFormatMapper { return this.urlBuilder; } + protected MultivaluedMap<String, String> getParams() { return this.params; } + + public boolean isSkipRelatedTo() { + if (params != null) { + boolean isSkipRelatedTo = true; + if (params.containsKey("skip-related-to")) { + String skipRelatedTo = params.getFirst("skip-related-to"); + isSkipRelatedTo = !(skipRelatedTo != null && skipRelatedTo.equals("false")); + } else { + // if skip-related-to param is missing, then default it to false; + isSkipRelatedTo = false; + } + return isSkipRelatedTo; + } + return true; + } + + protected boolean isTree() { return this.tree; } + + public Builder isTree(Boolean tree) { + this.tree = tree; + return this; + } + + public Builder includeUrl() { this.includeUrl = true; return this; diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ResourceWithSoT.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ResourceWithSoT.java index e4107aa9..d70f5c8e 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ResourceWithSoT.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ResourceWithSoT.java @@ -23,6 +23,8 @@ package org.onap.aai.serialization.queryformats; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import java.util.List; +import java.util.Map; import java.util.Optional; import org.apache.tinkerpop.gremlin.structure.Vertex; @@ -30,11 +32,14 @@ import org.onap.aai.db.props.AAIProperties; import org.onap.aai.introspection.Loader; import org.onap.aai.serialization.db.DBSerializer; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.onap.aai.serialization.queryformats.params.AsTree; import org.onap.aai.serialization.queryformats.params.Depth; import org.onap.aai.serialization.queryformats.params.NodesOnly; import org.onap.aai.serialization.queryformats.utils.UrlBuilder; import org.onap.aai.util.AAIConfig; +import java.util.Optional; + public class ResourceWithSoT extends MultiFormatMapper { protected JsonParser parser = new JsonParser(); protected final DBSerializer serializer; @@ -49,6 +54,7 @@ public class ResourceWithSoT extends MultiFormatMapper { this.serializer = builder.getSerializer(); this.depth = builder.getDepth(); this.nodesOnly = builder.isNodesOnly(); + this.isTree = builder.isTree(); } @Override @@ -56,7 +62,7 @@ public class ResourceWithSoT extends MultiFormatMapper { return 100; } - public static class Builder implements NodesOnly<Builder>, Depth<Builder> { + public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> { protected final Loader loader; protected final DBSerializer serializer; @@ -65,6 +71,7 @@ public class ResourceWithSoT extends MultiFormatMapper { protected boolean nodesOnly = false; protected int depth = 1; protected boolean modelDriven = false; + protected boolean tree = false; public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { this.loader = loader; @@ -89,6 +96,13 @@ public class ResourceWithSoT extends MultiFormatMapper { return this; } + protected boolean isTree() { return this.tree; } + + public Builder isTree(Boolean tree) { + this.tree = tree; + return this; + } + public Builder nodesOnly(Boolean nodesOnly) { this.nodesOnly = nodesOnly; return this; @@ -139,8 +153,9 @@ public class ResourceWithSoT extends MultiFormatMapper { @Override protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException { // Null check - if (v == null) + if (v == null) { return null; + } JsonObject json = new JsonObject(); @@ -148,9 +163,9 @@ public class ResourceWithSoT extends MultiFormatMapper { Object lastModifiedTimestampObj = v.property(AAIProperties.LAST_MOD_TS).value(); Object sotObj = v.property(AAIProperties.SOURCE_OF_TRUTH).value(); Object lastModSotObj = v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value(); - long createdTimestamp = Long.valueOf(createdTimestampObj.toString()); - long lastModifiedTimestamp = Long.valueOf(lastModifiedTimestampObj.toString()); - long threshold = Long.valueOf(AAIConfig.get("aai.resource.format.threshold", "10")); + long createdTimestamp = Long.parseLong(createdTimestampObj.toString()); + long lastModifiedTimestamp = Long.parseLong(lastModifiedTimestampObj.toString()); + long threshold = Long.parseLong(AAIConfig.get("aai.resource.format.threshold", "10")); // Add to the property field of the JSON payload json.addProperty("aai-created-ts", createdTimestampObj.toString()); @@ -172,4 +187,9 @@ public class ResourceWithSoT extends MultiFormatMapper { return Optional.of(json); } + + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex input, Map<String, List<String>> properties) throws AAIFormatVertexException { + return Optional.empty(); + } } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/StateFormat.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/StateFormat.java new file mode 100644 index 00000000..b2813476 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/StateFormat.java @@ -0,0 +1,144 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.queryformats; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; + +import java.util.*; + +public class StateFormat extends HistoryFormat { + + private static final Logger LOGGER = LoggerFactory.getLogger(StateFormat.class); + + protected StateFormat(HistoryFormat.Builder builder) { + super(builder); + } + + protected JsonArray createPropertiesObject(Vertex v) { + Iterator<VertexProperty<Object>> iter = v.properties(); + List<JsonObject> jsonList = new ArrayList<>(); + while (iter.hasNext()) { + VertexProperty<Object> prop = iter.next(); + if (prop.key() != null && ignoredKeys.contains(prop.key())) { + continue; + } + + JsonObject metaProperties = createMetaPropertiesObject(prop); + if (isTsInRange(metaProperties)) { + JsonObject json = new JsonObject(); + json.addProperty(KEY, prop.key()); + json = mapPropertyValues(json, VALUE, prop.value()); + addMetaProperties(json, metaProperties); + jsonList.add(json); + } + } + + JsonArray jsonArray = new JsonArray(); + jsonList.stream().sorted(Comparator.comparingLong(o -> o.get(TIMESTAMP).getAsLong())).forEach(jsonArray::add); + return jsonArray; + } + + private boolean isTsInRange(JsonObject metaProperties) { + long sTs = metaProperties.get(AAIProperties.START_TS).getAsLong(); + long eTs = Long.MAX_VALUE; + if (metaProperties.has(AAIProperties.END_TS)) { + eTs = metaProperties.get(AAIProperties.END_TS).getAsLong(); + } + + return startTs >= sTs && eTs > startTs; + } + + @Override + protected boolean isValidEdge(Edge e) { + if (e.property(AAIProperties.END_TS).isPresent()) { + long edgeEndTs = e.value(AAIProperties.END_TS); + if (startTs >= edgeEndTs) { + return false; + } + } + if (e.property(AAIProperties.START_TS).isPresent()) { + long edgeStartTs = e.value(AAIProperties.START_TS); + return startTs >= edgeStartTs; + } + return true; + } + + @Override + protected JsonObject getRelatedObject(Edge e, Vertex related) throws AAIFormatVertexException { + + JsonObject json = new JsonObject(); + json.addProperty("relationship-label", e.label()); + json.addProperty(NODE_TYPE, related.<String>value(AAIProperties.NODE_TYPE)); + json.addProperty("url", this.urlBuilder.pathed(related)); + if (related.property(AAIProperties.AAI_URI).isPresent()) { + json.addProperty("uri", related.<String>value(AAIProperties.AAI_URI)); + } else { + LOGGER.warn("Vertex {} is missing aai-uri", related.id()); + json.addProperty("uri", "NA"); + } + json.addProperty(TIMESTAMP, e.property(AAIProperties.START_TS).isPresent()? e.value(AAIProperties.START_TS) : 0); + json.addProperty(SOT, e.property(AAIProperties.SOURCE_OF_TRUTH).isPresent()? e.value(AAIProperties.SOURCE_OF_TRUTH) : ""); + json.addProperty(TX_ID, e.property(AAIProperties.START_TX_ID).isPresent()? e.value(AAIProperties.START_TX_ID) : "N/A"); + + return json; + } + + + protected void addMetaProperties(JsonObject json, JsonObject metaProperties) { + json.addProperty(TIMESTAMP, metaProperties.get(AAIProperties.START_TS) != null ? metaProperties.get(AAIProperties.START_TS).getAsLong() : 0); + json.addProperty(SOT, metaProperties.get(AAIProperties.SOURCE_OF_TRUTH) != null ? metaProperties.get(AAIProperties.SOURCE_OF_TRUTH).getAsString() : ""); + json.addProperty(TX_ID, metaProperties.get(AAIProperties.START_TX_ID) != null ? metaProperties.get(AAIProperties.START_TX_ID).getAsString() : "N/A"); + } + + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException { + + JsonObject json = new JsonObject(); + json.addProperty(NODE_TYPE, v.<String>value(AAIProperties.NODE_TYPE)); + json.addProperty("url", this.urlBuilder.pathed(v)); + json.addProperty("uri", v.property(AAIProperties.AAI_URI).value().toString()); + JsonArray properties = this.createPropertiesObject(v); + + if (properties.size() > 0) { + json.add(PROPERTIES, properties); + } else { + return Optional.empty(); + } + if (!nodesOnly) { + json.add(RELATED_TO, this.createRelationshipObject(v)); + } + return Optional.of(json); + } + + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex input, Map<String, List<String>> properties) throws AAIFormatVertexException { + return Optional.empty(); + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/logging/LoggingContextNotExistsException.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/params/AsTree.java index f1d4c59c..c7479147 100644 --- a/aai-core/src/main/java/org/onap/aai/logging/LoggingContextNotExistsException.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/params/AsTree.java @@ -18,9 +18,11 @@ * ============LICENSE_END========================================================= */ -package org.onap.aai.logging; +package org.onap.aai.serialization.queryformats.params; -public class LoggingContextNotExistsException extends RuntimeException { +@Inject(name = "as-tree") +public interface AsTree<T> { - private static final long serialVersionUID = -4965807709525739623L; + @Setter + public T isTree(Boolean tree); } diff --git a/aai-core/src/main/java/org/onap/aai/logging/ErrorObjectFormatException.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/params/EndTs.java index 8d53f2e3..937d87f2 100644 --- a/aai-core/src/main/java/org/onap/aai/logging/ErrorObjectFormatException.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/params/EndTs.java @@ -18,13 +18,11 @@ * ============LICENSE_END========================================================= */ -package org.onap.aai.logging; +package org.onap.aai.serialization.queryformats.params; -public class ErrorObjectFormatException extends Exception { +@Inject(name = "endTs") +public interface EndTs<T> { - private static final long serialVersionUID = 3732705544448553685L; - - public ErrorObjectFormatException() { - super(); - } + @Setter + public T endTs(String endTs); } diff --git a/aai-core/src/main/java/org/onap/aai/logging/CustomLogPatternLayout.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/params/StartTs.java index 63cc49f7..e94b893d 100644 --- a/aai-core/src/main/java/org/onap/aai/logging/CustomLogPatternLayout.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/params/StartTs.java @@ -18,11 +18,11 @@ * ============LICENSE_END========================================================= */ -package org.onap.aai.logging; +package org.onap.aai.serialization.queryformats.params; -public class CustomLogPatternLayout extends ch.qos.logback.access.PatternLayout { - static { - defaultConverterMap.put("z", CNName.class.getName()); - defaultConverterMap.put("y", DME2RestFlag.class.getName()); - } +@Inject(name = "startTs") +public interface StartTs<T> { + + @Setter + public T startTs(String startTs); } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/utils/QueryParamInjector.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/utils/QueryParamInjector.java index 1b51088e..f90907e2 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/utils/QueryParamInjector.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/utils/QueryParamInjector.java @@ -20,25 +20,23 @@ package org.onap.aai.serialization.queryformats.utils; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Set; +import org.onap.aai.serialization.queryformats.exceptions.QueryParamInjectionException; +import org.onap.aai.serialization.queryformats.params.*; import javax.ws.rs.core.MultivaluedMap; - -import org.onap.aai.serialization.queryformats.exceptions.QueryParamInjectionException; -import org.onap.aai.serialization.queryformats.params.Inject; -import org.onap.aai.serialization.queryformats.params.Setter; -import org.reflections.Reflections; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; public class QueryParamInjector { - private final Set<Class<?>> results; - - private QueryParamInjector() { - Reflections reflections = new Reflections("org.onap.aai.serialization.queryformats.params"); - results = reflections.getTypesAnnotatedWith(Inject.class); - } + //TODO reimplement this using reflections. + private static final Class<?>[] PARAM_CLASSES = new Class[] { + AsTree.class, + Depth.class, + EndTs.class, + NodesOnly.class, + StartTs.class + }; private static class Helper { private static final QueryParamInjector INSTANCE = new QueryParamInjector(); @@ -50,7 +48,7 @@ public class QueryParamInjector { public <T> T injectParams(T obj, MultivaluedMap<String, String> params) throws QueryParamInjectionException { try { - for (Class<?> item : results) { + for (Class<?> item : PARAM_CLASSES) { if (item.isAssignableFrom(obj.getClass())) { String name = item.getAnnotation(Inject.class).name(); diff --git a/aai-core/src/main/java/org/onap/aai/service/NodeValidationService.java b/aai-core/src/main/java/org/onap/aai/service/NodeValidationService.java index 316e3017..6c57616e 100644 --- a/aai-core/src/main/java/org/onap/aai/service/NodeValidationService.java +++ b/aai-core/src/main/java/org/onap/aai/service/NodeValidationService.java @@ -20,8 +20,8 @@ package org.onap.aai.service; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.annotation.PostConstruct; @@ -37,7 +37,7 @@ import org.springframework.stereotype.Service; @PropertySource(value = "file:${schema.ingest.file}", ignoreResourceNotFound = true) public class NodeValidationService { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(NodeValidationService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(NodeValidationService.class); @Autowired(required = false) private NodeValidator nodeValidator; diff --git a/aai-core/src/main/java/org/onap/aai/tasks/ScheduledTasks.java b/aai-core/src/main/java/org/onap/aai/tasks/ScheduledTasks.java index 911603d2..16c41166 100644 --- a/aai-core/src/main/java/org/onap/aai/tasks/ScheduledTasks.java +++ b/aai-core/src/main/java/org/onap/aai/tasks/ScheduledTasks.java @@ -20,32 +20,30 @@ package org.onap.aai.tasks; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -import java.io.File; -import java.util.Arrays; -import java.util.Date; -import java.util.UUID; - import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.comparator.LastModifiedFileComparator; -import org.onap.aai.logging.LoggingContext; -import org.onap.aai.logging.LoggingContext.StatusCode; +import org.onap.aai.aailog.logs.AaiScheduledTaskAuditLog; import org.onap.aai.util.AAIConfig; import org.onap.aai.util.AAIConstants; +import org.onap.logging.filter.base.ONAPComponents; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import java.io.File; +import java.util.Arrays; +import java.util.Date; + @Component public class ScheduledTasks { - private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(ScheduledTasks.class); + @Autowired + private AaiScheduledTaskAuditLog auditLog; - private static final String COMPONENT = "Scheduler"; - private static final String FROM_APP_ID = "CronApp"; + private static Logger LOGGER = LoggerFactory.getLogger(ScheduledTasks.class); private static final long PROPERTY_READ_INTERVAL = 60000; // every minute - private String GlobalPropFileName = AAIConstants.AAI_CONFIG_FILENAME; // for read and possibly reloading aaiconfig.properties and other @@ -55,19 +53,7 @@ public class ScheduledTasks { // configuration properties files @Scheduled(fixedRate = PROPERTY_READ_INTERVAL) public void loadAAIProperties() { - final UUID transId = UUID.randomUUID(); - - // LoggingContext.init(); - LoggingContext.save(); - LoggingContext.requestId(transId); - LoggingContext.partnerName(FROM_APP_ID); - LoggingContext.component(COMPONENT); - LoggingContext.targetEntity("AAI"); - LoggingContext.targetServiceName("loadAAIProperties"); - LoggingContext.serviceName("AAI"); - LoggingContext.statusCode(StatusCode.COMPLETE); - LoggingContext.responseCode(LoggingContext.SUCCESS); - + auditLog.logBefore("LoadAaiPropertiesTask", ONAPComponents.AAI.toString() ); String dir = FilenameUtils.getFullPathNoEndSeparator(GlobalPropFileName); if (dir == null || dir.length() < 3) { dir = "/opt/aai/etc"; @@ -94,6 +80,6 @@ public class ScheduledTasks { break; } } - LoggingContext.restoreIfPossible(); + auditLog.logAfter(); } } diff --git a/aai-core/src/main/java/org/onap/aai/transforms/XmlFormatTransformer.java b/aai-core/src/main/java/org/onap/aai/transforms/XmlFormatTransformer.java new file mode 100644 index 00000000..ce7ead4f --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/transforms/XmlFormatTransformer.java @@ -0,0 +1,70 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.transforms; + +import com.bazaarvoice.jolt.Chainr; +import com.bazaarvoice.jolt.JsonUtils; +import org.json.JSONObject; +import org.json.XML; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class XmlFormatTransformer { + + private static final Logger LOGGER = LoggerFactory.getLogger(XmlFormatTransformer.class); + + private static final String RESULT_WITH_QUOTES = "\"result\""; + private static final String RESULTS_STRING = "results"; + + private Chainr chainr; + + public XmlFormatTransformer() { + List<Object> spec = JsonUtils.classpathToList("/specs/transform-related-to-node.json"); + this.chainr = Chainr.fromSpec(spec); + } + + public String transform(String input) { + + Object transformedOutput; + + if(!input.contains(RESULT_WITH_QUOTES)){ + Object inputMap = JsonUtils.jsonToMap(input); + transformedOutput = chainr.transform(inputMap); + + JSONObject jsonObject; + if(transformedOutput == null){ + LOGGER.debug("For the input {}, unable to transform it so returning null", input); + jsonObject = new JSONObject(); + } else { + jsonObject = new JSONObject(JsonUtils.toJsonString(transformedOutput)); + } + + return XML.toString(jsonObject, RESULTS_STRING); + } else { + // If the json is already conforming to the following format + // {"results":[{"results":"v[2]"}]} + // Then no transformation is required + return XML.toString(new JSONObject(input)); + } + + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/AAIConfig.java b/aai-core/src/main/java/org/onap/aai/util/AAIConfig.java deleted file mode 100644 index c2103071..00000000 --- a/aai-core/src/main/java/org/onap/aai/util/AAIConfig.java +++ /dev/null @@ -1,232 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.util; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.util.Properties; -import java.util.UUID; - -import org.eclipse.jetty.util.security.Password; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.logging.LoggingContext; -import org.onap.aai.logging.LoggingContext.StatusCode; - -public class AAIConfig { - - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIConfig.class); - private static final String GLOBAL_PROP_FILE_NAME = AAIConstants.AAI_CONFIG_FILENAME; - private static Properties serverProps; - private static boolean propsInitialized = false; - - /** - * Instantiates a new AAI config. - */ - // Don't instantiate - private AAIConfig() { - } - - /** - * Inits the. - * - * @throws AAIException the AAI exception - */ - public synchronized static void init() throws AAIException { - - LoggingContext.save(); - LoggingContext.component("config"); - LoggingContext.partnerName("NA"); - LoggingContext.targetEntity("AAI"); - LoggingContext.requestId(UUID.randomUUID().toString()); - LoggingContext.serviceName("AAI"); - LoggingContext.targetServiceName("init"); - LoggingContext.statusCode(StatusCode.COMPLETE); - - LOGGER.info("Initializing AAIConfig"); - - AAIConfig.getConfigFile(); - AAIConfig.reloadConfig(); - - if (AAIConstants.AAI_NODENAME == null || AAIConstants.AAI_NODENAME == "") { - ErrorLogHelper.logError("AAI_4005", " AAI_NODENAME is not defined"); - } else { - LOGGER.info("A&AI Server Node Name = " + AAIConstants.AAI_NODENAME); - } - LoggingContext.restore(); - } - - /** - * Gets the config file. - * - * @return the config file - */ - public static String getConfigFile() { - return GLOBAL_PROP_FILE_NAME; - } - - /** - * Reload config. - */ - public synchronized static void reloadConfig() { - - String propFileName = GLOBAL_PROP_FILE_NAME; - Properties newServerProps = null; - - LOGGER.debug("Reloading config from " + propFileName); - - try (InputStream is = new FileInputStream(propFileName)) { - newServerProps = new Properties(); - newServerProps.load(is); - propsInitialized = true; - serverProps = newServerProps; - } catch (FileNotFoundException fnfe) { - ErrorLogHelper.logError("AAI_4001", " " + propFileName + ". Exception: " + fnfe.getMessage()); - } catch (IOException e) { - ErrorLogHelper.logError("AAI_4002", " " + propFileName + ". IOException: " + e.getMessage()); - } - } - - /** - * Gets the. - * - * @param key the key - * @param defaultValue the default value - * @return the string - */ - public static String get(String key, String defaultValue) { - String result = defaultValue; - try { - result = get(key); - } catch (AAIException a) { - } - if (result == null || result.isEmpty()) { - result = defaultValue; - } - return (result); - } - - /** - * Gets the. - * - * @param key the key - * @return the string - * @throws AAIException the AAI exception - */ - public static String get(String key) throws AAIException { - String response = null; - - if (key.equals(AAIConstants.AAI_NODENAME)) { - // Get this from InetAddress rather than the properties file - String nodeName = getNodeName(); - if (nodeName != null) { - return nodeName; - } - // else get from property file - } - - if (!propsInitialized || (serverProps == null)) { - reloadConfig(); - } - - if ((key.endsWith("password") || key.endsWith("passwd") || key.endsWith("apisecret")) - && serverProps.containsKey(key + ".x")) { - String valx = serverProps.getProperty(key + ".x"); - return Password.deobfuscate(valx); - } - - if (!serverProps.containsKey(key)) { - throw new AAIException("AAI_4005", "Property key " + key + " cannot be found"); - } else { - response = serverProps.getProperty(key); - if (response == null || response.isEmpty()) { - throw new AAIException("AAI_4005", "Property key " + key + " is null or empty"); - } - } - return response; - } - - /** - * Gets the int. - * - * @param key the key - * @return the int - * @throws AAIException the AAI exception - */ - public static int getInt(String key) throws AAIException { - return Integer.parseInt(AAIConfig.get(key)); - } - - /** - * Gets the int. - * - * @param key the key - * @return the int - */ - public static int getInt(String key, String value) { - return Integer.parseInt(AAIConfig.get(key, value)); - } - - /** - * Gets the server props. - * - * @return the server props - */ - public static Properties getServerProps() { - return serverProps; - } - - /** - * Gets the node name. - * - * @return the node name - */ - public static String getNodeName() { - try { - InetAddress ip = InetAddress.getLocalHost(); - if (ip != null) { - String hostname = ip.getHostName(); - if (hostname != null) { - return hostname; - } - } - } catch (Exception e) { - return null; - } - return null; - } - - /** - * Check if a null or an Empty string is passed in. - * - * @param s the s - * @return boolean - */ - public static boolean isEmpty(String s) { - return (s == null || s.length() == 0); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/util/AAIConstants.java b/aai-core/src/main/java/org/onap/aai/util/AAIConstants.java deleted file mode 100644 index e906c280..00000000 --- a/aai-core/src/main/java/org/onap/aai/util/AAIConstants.java +++ /dev/null @@ -1,129 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Modifications Copyright © 2018 IBM. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.util; - -public final class AAIConstants { - private static final String AJSC_HOME = "AJSC_HOME"; - // - // - /** Default to unix file separator if system property file.separator is null */ - public static final String AAI_FILESEP = - (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); - // - /** Default to opt aai if system property aai.home is null, using file.separator */ - public static final String AAI_HOME = - (System.getProperty(AJSC_HOME) == null) ? AAI_FILESEP + "opt" + AAI_FILESEP + "app" + AAI_FILESEP + "aai" - : System.getProperty(AJSC_HOME); - public static final String AAI_BUNDLECONFIG_NAME = - (System.getProperty("BUNDLECONFIG_DIR") == null) ? "bundleconfig" : System.getProperty("BUNDLECONFIG_DIR"); - public static final String AAI_HOME_BUNDLECONFIG = (System.getProperty(AJSC_HOME) == null) - ? AAI_FILESEP + "opt" + AAI_FILESEP + "app" + AAI_FILESEP + "aai" + AAI_FILESEP + AAI_BUNDLECONFIG_NAME - : System.getProperty(AJSC_HOME) + AAI_FILESEP + AAI_BUNDLECONFIG_NAME; - - /** etc directory, relative to AAI_HOME */ - public static final String AAI_HOME_ETC = AAI_HOME_BUNDLECONFIG + AAI_FILESEP + "etc" + AAI_FILESEP; - public static final String AAI_HOME_ETC_APP_PROPERTIES = AAI_HOME_ETC + "appprops" + AAI_FILESEP; - public static final String AAI_HOME_ETC_AUTH = AAI_HOME_ETC + "auth" + AAI_FILESEP; - public static final String AAI_CONFIG_FILENAME = AAI_HOME_ETC_APP_PROPERTIES + "aaiconfig.properties"; - public static final String AAI_AUTH_CONFIG_FILENAME = AAI_HOME_ETC_AUTH + "aai_policy.json"; - public static final String REALTIME_DB_CONFIG = AAI_HOME_ETC_APP_PROPERTIES + "janusgraph-realtime.properties"; - public static final String CACHED_DB_CONFIG = AAI_HOME_ETC_APP_PROPERTIES + "janusgraph-cached.properties"; - public static final String AAI_HOME_ETC_OXM = AAI_HOME_ETC + "oxm" + AAI_FILESEP; - public static final String AAI_EVENT_DMAAP_PROPS = - AAI_HOME_ETC_APP_PROPERTIES + "aaiEventDMaaPPublisher.properties"; - public static final String AAI_HOME_ETC_SCRIPT = AAI_HOME_ETC + AAI_FILESEP + "scriptdata" + AAI_FILESEP; - - public static final String AAI_LOGBACK_PROPS = "logback.xml"; - public static final String AAI_SCHEMA_MOD_LOGBACK_PROPS = "schemaMod-logback.xml"; - public static final String AAI_FORCE_DELETE_LOGBACK_PROPS = "forceDelete-logback.xml"; - - public static final String AAI_TRUSTSTORE_FILENAME = "aai.truststore.filename"; - public static final String AAI_TRUSTSTORE_PASSWD = "aai.truststore.passwd"; - public static final String AAI_KEYSTORE_FILENAME = "aai.keystore.filename"; - public static final String AAI_KEYSTORE_PASSWD = "aai.keystore.passwd"; - - public static final String AAI_SERVER_URL_BASE = "aai.server.url.base"; - public static final String AAI_SERVER_URL = "aai.server.url"; - public static final String AAI_OLDSERVER_URL = "aai.oldserver.url"; - public static final String AAI_LOCAL_REST = "https://localhost:%d/aai/%s/"; - public static final String AAI_LOCAL_OVERRIDE = "aai.server.localhost.override.url"; - public static final String AAI_LOCAL_OVERRIDE_DEFAULT = "NA"; - public static final String AAI_LOCAL_REST_OVERRIDE = "%s/aai/%s/"; - - public static final int AAI_RESOURCES_PORT = 8447; - public static final int AAI_QUERY_PORT = 8446; - public static final int AAI_LEGACY_PORT = 8443; - - public static final String AAI_DEFAULT_API_VERSION = "v10"; - public static final String AAI_DEFAULT_API_VERSION_PROP = "aai.default.api.version"; - public static final String AAI_NOTIFICATION_CURRENT_VERSION = "aai.notification.current.version"; - - public static final String AAI_NODENAME = "aai.config.nodename"; - - /* - * Logs the objects being deleted when an client deletes objects via implied delete during PUT operation - */ - public static final String AAI_IMPLIED_DELETE_LOG_ENABLED = "aai.implied.delete.log.enabled"; - /* - * Specifies how many objects maximum to log - */ - public static final String AAI_IMPLIED_DELETE_LOG_LIMIT = "aai.implied.delete.log.limit"; - - public static final String AAI_BULKCONSUMER_LIMIT = "aai.bulkconsumer.payloadlimit"; - public static final String AAI_BULKCONSUMER_OVERRIDE_LIMIT = "aai.bulkconsumer.payloadoverride"; - - 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_GRAPHADMIN_TIMEOUT_LIMIT = "aai.graphadmin.timeoutlimit"; - public static final String AAI_GRAPHADMIN_TIMEOUT_ENABLED = "aai.graphadmin.timeoutenabled"; - public static final String AAI_GRAPHADMIN_TIMEOUT_APP = "aai.graphadmin.timeout.appspecific"; - - public static final String AAI_CRUD_TIMEOUT_LIMIT = "aai.crud.timeoutlimit"; - public static final String AAI_CRUD_TIMEOUT_ENABLED = "aai.crud.timeoutenabled"; - public static final String AAI_CRUD_TIMEOUT_APP = "aai.crud.timeout.appspecific"; - - public static final String AAI_RESVERSION_ENABLEFLAG = "aai.resourceversion.enableflag"; - public static final String AAI_RESVERSION_DISABLED_UUID = "aai.resourceversion.disabled.uuid"; - public static final String AAI_RESVERSION_DISABLED_UUID_DEFAULT = "38cf3090-6a0c-4e9d-8142-4332a7352846"; - - public static final long HISTORY_MAX_HOURS = 192; - - public static final String LOGGING_MAX_STACK_TRACE_ENTRIES = "aai.logging.maxStackTraceEntries"; - - /*** UEB ***/ - public static final String UEB_PUB_PARTITION_AAI = "AAI"; - - /** Micro-service Names */ - public static final String AAI_TRAVERSAL_MS = "aai-traversal"; - public static final String AAI_RESOURCES_MS = "aai-resources"; - - /** - * Instantiates a new AAI constants. - */ - private AAIConstants() { - // prevent instantiation - } - -} diff --git a/aai-core/src/main/java/org/onap/aai/util/FileWatcher.java b/aai-core/src/main/java/org/onap/aai/util/FileWatcher.java deleted file mode 100644 index 07ac2642..00000000 --- a/aai-core/src/main/java/org/onap/aai/util/FileWatcher.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.util; - -import java.io.*; -import java.util.*; - -public abstract class FileWatcher extends TimerTask { - private long timeStamp; - private File file; - - /** - * Instantiates a new file watcher. - * - * @param file the file - */ - public FileWatcher(File file) { - this.file = file; - this.timeStamp = file.lastModified(); - } - - /** - * runs a timer task - * - * @see TimerTask.run - */ - public final void run() { - long timeStamp = file.lastModified(); - - if ((timeStamp - this.timeStamp) > 500) { - this.timeStamp = timeStamp; - onChange(file); - } - } - - /** - * On change. - * - * @param file the file - */ - protected abstract void onChange(File file); -} diff --git a/aai-core/src/main/java/org/onap/aai/util/FormatDate.java b/aai-core/src/main/java/org/onap/aai/util/FormatDate.java deleted file mode 100644 index 9ee2b71d..00000000 --- a/aai-core/src/main/java/org/onap/aai/util/FormatDate.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.util; - -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; - -public class FormatDate { - - private final String timeZone; - private final String pattern; - - public FormatDate(String pattern) { - this.pattern = pattern; - this.timeZone = "GMT"; - } - - public FormatDate(String pattern, String timeZone) { - this.pattern = pattern; - this.timeZone = timeZone; - } - - public String getDateTime() { - - final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); - return formatter.format(ZonedDateTime.now(ZoneId.of(timeZone))); - } -} diff --git a/aai-core/src/main/java/org/onap/aai/util/HbaseSaltPrefixer.java b/aai-core/src/main/java/org/onap/aai/util/HbaseSaltPrefixer.java deleted file mode 100644 index a41ad27b..00000000 --- a/aai-core/src/main/java/org/onap/aai/util/HbaseSaltPrefixer.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.util; - -/* - * logging to hbase encountered hotspotting issues, so per - * http://archive.cloudera.com/cdh5/cdh/5/hbase-0.98.6-cdh5.3.8/book/rowkey.design.html - * we decided to salt the rowkeys - * as these keys are generated in a couple places, I made a class to contain that logic - */ -public class HbaseSaltPrefixer { - private int NUM_REGION_BUCKETS = 3; // the number of hbase region servers per cluster - - private static class SingletonHolder { - private static final HbaseSaltPrefixer INSTANCE = new HbaseSaltPrefixer(); - } - - /** - * Instantiates a new hbase salt prefixer. - */ - private HbaseSaltPrefixer() { - } - - /** - * Gets the single instance of HbaseSaltPrefixer. - * - * @return single instance of HbaseSaltPrefixer - */ - public static HbaseSaltPrefixer getInstance() { - return SingletonHolder.INSTANCE; - } - - /** - * Prepend salt. - * - * @param key the key - * @return the string - */ - public String prependSalt(String key) { - int salt = key.hashCode() % NUM_REGION_BUCKETS; - return salt + "-" + key; - } -} diff --git a/aai-core/src/main/java/org/onap/aai/util/HttpsAuthClient.java b/aai-core/src/main/java/org/onap/aai/util/HttpsAuthClient.java index 133c26a7..c2bfabf4 100644 --- a/aai-core/src/main/java/org/onap/aai/util/HttpsAuthClient.java +++ b/aai-core/src/main/java/org/onap/aai/util/HttpsAuthClient.java @@ -27,10 +27,13 @@ import com.sun.jersey.api.client.config.DefaultClientConfig; import com.sun.jersey.api.client.filter.LoggingFilter; import com.sun.jersey.api.json.JSONConfiguration; import com.sun.jersey.client.urlconnection.HTTPSProperties; +import org.onap.aai.aailog.filter.RestControllerClientLoggingInterceptor; +import org.onap.aai.exceptions.AAIException; import java.io.FileInputStream; -import java.security.KeyManagementException; -import java.security.KeyStore; +import java.io.IOException; +import java.security.*; +import java.security.cert.CertificateException; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; @@ -63,29 +66,25 @@ public class HttpsAuthClient { e.printStackTrace(); } } - /** * Gets the client. * + * @param truststorePath the truststore path + * @param truststorePassword the truststore password + * @param keystorePath the keystore path + * @param keystorePassword the keystore password * @return the client * @throws KeyManagementException the key management exception */ - public static Client getClient() throws KeyManagementException { + public static Client getClient(String truststorePath, String truststorePassword, String keystorePath, String keystorePassword) throws KeyManagementException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { ClientConfig config = new DefaultClientConfig(); config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); config.getClasses().add(org.onap.aai.restcore.CustomJacksonJaxBJsonProvider.class); - SSLContext ctx = null; try { - String truststore_path = - AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_FILENAME); - String truststore_password = AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_PASSWD); - String keystore_path = AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_KEYSTORE_FILENAME); - String keystore_password = AAIConfig.get(AAIConstants.AAI_KEYSTORE_PASSWD); - - System.setProperty("javax.net.ssl.trustStore", truststore_path); - System.setProperty("javax.net.ssl.trustStorePassword", truststore_password); + System.setProperty("javax.net.ssl.trustStore", truststorePath); + System.setProperty("javax.net.ssl.trustStorePassword", truststorePassword); HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String string, SSLSession ssls) { return true; @@ -96,36 +95,62 @@ public class HttpsAuthClient { KeyManagerFactory kmf = null; try { kmf = KeyManagerFactory.getInstance("SunX509"); - FileInputStream fin = new FileInputStream(keystore_path); + FileInputStream fin = new FileInputStream(keystorePath); KeyStore ks = KeyStore.getInstance("PKCS12"); - char[] pwd = keystore_password.toCharArray(); + char[] pwd = keystorePassword.toCharArray(); ks.load(fin, pwd); kmf.init(ks, pwd); } catch (Exception e) { System.out.println("Error setting up kmf: exiting"); e.printStackTrace(); - System.exit(1); + throw e; + //System.exit(1); } ctx.init(kmf.getKeyManagers(), null, null); config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, - new HTTPSProperties(new HostnameVerifier() { - @Override - public boolean verify(String s, SSLSession sslSession) { - return true; - } - }, ctx)); + new HTTPSProperties(new HostnameVerifier() { + @Override + public boolean verify(String s, SSLSession sslSession) { + return true; + } + }, ctx)); } catch (Exception e) { System.out.println("Error setting up config: exiting"); e.printStackTrace(); - System.exit(1); + throw e; + //System.exit(1); } Client client = Client.create(config); + client.addFilter(new RestControllerClientLoggingInterceptor()); // uncomment this line to get more logging for the request/response // client.addFilter(new LoggingFilter(System.out)); return client; } + /** + * Gets the client. + * + * @return the client + * @throws KeyManagementException the key management exception + */ + public static Client getClient() throws KeyManagementException, AAIException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { + String truststore_path = null; + String truststore_password = null; + String keystore_path = null; + String keystore_password = null; + try { + truststore_path = + AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_FILENAME); + truststore_password = AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_PASSWD); + keystore_path = AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_KEYSTORE_FILENAME); + keystore_password = AAIConfig.get(AAIConstants.AAI_KEYSTORE_PASSWD); + } + catch (AAIException e) { + throw e; + } + return(getClient(truststore_path, truststore_password, keystore_path, keystore_password)); + } } diff --git a/aai-core/src/main/java/org/onap/aai/util/MapperUtil.java b/aai-core/src/main/java/org/onap/aai/util/MapperUtil.java deleted file mode 100644 index 47a937d4..00000000 --- a/aai-core/src/main/java/org/onap/aai/util/MapperUtil.java +++ /dev/null @@ -1,121 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Modifications Copyright © 2018 IBM. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.util; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; - -import org.onap.aai.exceptions.AAIException; - -public class MapperUtil { - - /** - * Instantiates MapperUtil. - */ - private MapperUtil() { - // prevent instantiation - } - - /** - * Read as object of. - * - * @param <T> the generic type - * @param clazz the clazz - * @param value the value - * @return the t - * @throws AAIException the AAI exception - */ - public static <T> T readAsObjectOf(Class<T> clazz, String value) throws AAIException { - ObjectMapper mapper = new ObjectMapper(); - try { - return mapper.readValue(value, clazz); - } catch (Exception e) { - throw new AAIException("AAI_4007", e); - } - } - - /** - * Read with dashes as object of. - * - * @param <T> the generic type - * @param clazz the clazz - * @param value the value - * @return the t - * @throws AAIException the AAI exception - */ - public static <T> T readWithDashesAsObjectOf(Class<T> clazz, String value) throws AAIException { - ObjectMapper mapper = new ObjectMapper(); - try { - mapper.registerModule(new JaxbAnnotationModule()); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false); - - return mapper.readValue(value, clazz); - } catch (Exception e) { - throw new AAIException("AAI_4007", e); - } - } - - /** - * Write as JSON string. - * - * @param obj the obj - * @return the string - * @throws AAIException the AAI exception - */ - public static String writeAsJSONString(Object obj) throws AAIException { - ObjectMapper mapper = new ObjectMapper(); - try { - return mapper.writeValueAsString(obj); - } catch (Exception e) { - throw new AAIException("AAI_4008", e); - } - } - - /** - * Write as JSON string with dashes. - * - * @param obj the obj - * @return the string - * @throws AAIException the AAI exception - */ - public static String writeAsJSONStringWithDashes(Object obj) throws AAIException { - ObjectMapper mapper = new ObjectMapper(); - try { - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - - mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - mapper.configure(SerializationFeature.INDENT_OUTPUT, false); - mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false); - - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false); - - mapper.registerModule(new JaxbAnnotationModule()); - return mapper.writeValueAsString(obj); - } catch (Exception e) { - throw new AAIException("AAI_4008", e); - } - } -} diff --git a/aai-core/src/main/java/org/onap/aai/util/PojoUtils.java b/aai-core/src/main/java/org/onap/aai/util/PojoUtils.java index 218f0dd8..05cbf97c 100644 --- a/aai-core/src/main/java/org/onap/aai/util/PojoUtils.java +++ b/aai-core/src/main/java/org/onap/aai/util/PojoUtils.java @@ -129,11 +129,7 @@ public class PojoUtils { mapper.registerModule(new JaxbAnnotationModule()); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - mapper.writeValue(baos, clazz); - - return baos.toString(); + return mapper.writeValueAsString(clazz); } /** diff --git a/aai-core/src/main/java/org/onap/aai/util/RestController.java b/aai-core/src/main/java/org/onap/aai/util/RestController.java index a1419d14..8527ffe5 100644 --- a/aai-core/src/main/java/org/onap/aai/util/RestController.java +++ b/aai-core/src/main/java/org/onap/aai/util/RestController.java @@ -20,26 +20,30 @@ package org.onap.aai.util; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientResponse; +import java.io.IOException; import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.UUID; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.logging.LoggingContext; public class RestController implements RestControllerInterface { private static final String TARGET_NAME = "AAI"; - private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(RestController.class); + private static Logger LOGGER = LoggerFactory.getLogger(RestController.class); private static Client client = null; @@ -85,6 +89,9 @@ public class RestController implements RestControllerInterface { this.initRestClient(); } + public RestController(String truststorePath, String truststorePassword, String keystorePath, String keystorePassword) throws AAIException { + this.initRestClient(truststorePath, truststorePassword, keystorePath, keystorePassword); + } /** * Inits the rest client. * @@ -101,11 +108,29 @@ public class RestController implements RestControllerInterface { } } } + /** + * Inits the rest client. + * + * @throws AAIException the AAI exception + */ + public void initRestClient(String truststorePath, String truststorePassword, String keystorePath, String keystorePassword) throws AAIException { + if (client == null) { + try { + client = getHttpsAuthClient(truststorePath, truststorePassword, keystorePath, keystorePassword); + } catch (KeyManagementException e) { + throw new AAIException("AAI_7117", "KeyManagementException in REST call to DB: " + e.toString()); + } catch (Exception e) { + throw new AAIException("AAI_7117", " Exception in REST call to DB: " + e.toString()); + } + } + } + public Client getHttpsAuthClient(String truststorePath, String truststorePassword, String keystorePath, String keystorePassword) throws KeyManagementException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { + return HttpsAuthClient.getClient(truststorePath, truststorePassword, keystorePath, keystorePassword); + } - public Client getHttpsAuthClient() throws KeyManagementException { + public Client getHttpsAuthClient() throws KeyManagementException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, AAIException { return HttpsAuthClient.getClient(); } - /** * Sets the rest srvr base URL. * @@ -151,13 +176,6 @@ public class RestController implements RestControllerInterface { String url = ""; transId += ":" + UUID.randomUUID().toString(); - LoggingContext.save(); - LoggingContext.partnerName(sourceID); - LoggingContext.targetEntity(TARGET_NAME); - LoggingContext.requestId(transId); - LoggingContext.serviceName(methodName); - LoggingContext.targetServiceName(methodName); - LOGGER.debug(methodName + " start"); restObject.set(t); @@ -177,7 +195,6 @@ public class RestController implements RestControllerInterface { AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)) + path; } } - initRestClient(); LOGGER.debug(url + " for the get REST API"); ClientResponse cres = client.resource(url).accept("application/json").header("X-TransactionId", transId) .header("X-FromAppId", sourceID).header("Real-Time", "true").type("application/json") @@ -192,12 +209,9 @@ public class RestController implements RestControllerInterface { restObject.set(t); LOGGER.debug(methodName + "REST api GET was successfull!"); } else { - LoggingContext.restore(); // System.out.println(methodName + ": url=" + url + " failed with status=" + cres.getStatus()); throw new AAIException("AAI_7116", methodName + " with status=" + cres.getStatus() + ", url=" + url); } - - LoggingContext.restore(); } /** @@ -219,20 +233,12 @@ public class RestController implements RestControllerInterface { String url = ""; transId += ":" + UUID.randomUUID().toString(); - LoggingContext.save(); - LoggingContext.partnerName(sourceID); - LoggingContext.targetEntity(TARGET_NAME); - LoggingContext.requestId(transId); - LoggingContext.serviceName(methodName); - LoggingContext.targetServiceName(methodName); - LOGGER.debug(methodName + " start"); restObject.set(t); url = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE) + apiVersion + "/" + path; - initRestClient(); LOGGER.debug(url + " for the get REST API"); ClientResponse cres = client.resource(url).accept("application/json").header("X-TransactionId", transId) .header("X-FromAppId", sourceID).header("Real-Time", "true").type("application/json") @@ -247,12 +253,9 @@ public class RestController implements RestControllerInterface { restObject.set(t); LOGGER.debug(methodName + "REST api GET was successfull!"); } else { - LoggingContext.restore(); // System.out.println(methodName + ": url=" + url + " failed with status=" + cres.getStatus()); throw new AAIException("AAI_7116", methodName + " with status=" + cres.getStatus() + ", url=" + url); } - - LoggingContext.restore(); } /** @@ -320,17 +323,8 @@ public class RestController implements RestControllerInterface { String url = ""; transId += ":" + UUID.randomUUID().toString(); - LoggingContext.save(); - LoggingContext.partnerName(sourceID); - LoggingContext.targetEntity(TARGET_NAME); - LoggingContext.requestId(transId); - LoggingContext.serviceName(methodName); - LoggingContext.targetServiceName(methodName); - LOGGER.debug(methodName + " start"); - initRestClient(); - if (oldserver) { url = AAIConfig.get(AAIConstants.AAI_OLDSERVER_URL) + path; } else { @@ -356,9 +350,7 @@ public class RestController implements RestControllerInterface { int statuscode = cres.getStatus(); if (statuscode >= 200 && statuscode <= 299) { LOGGER.debug(methodName + ": url=" + url + ", request=" + path); - LoggingContext.restore(); } else { - LoggingContext.restore(); throw new AAIException("AAI_7116", methodName + " with status=" + statuscode + ", url=" + url + ", msg=" + cres.getEntity(String.class)); } @@ -381,16 +373,8 @@ public class RestController implements RestControllerInterface { String url = ""; transId += ":" + UUID.randomUUID().toString(); - LoggingContext.save(); - LoggingContext.partnerName(sourceID); - LoggingContext.targetEntity(TARGET_NAME); - LoggingContext.requestId(transId); - LoggingContext.serviceName(methodName); - LoggingContext.targetServiceName(methodName); - LOGGER.debug(methodName + " start"); - initRestClient(); String request = "{}"; if (overrideLocalHost == null) { overrideLocalHost = AAIConfig.get(AAIConstants.AAI_LOCAL_OVERRIDE, AAIConstants.AAI_LOCAL_OVERRIDE_DEFAULT); @@ -408,13 +392,10 @@ public class RestController implements RestControllerInterface { if (cres.getStatus() == 404) { // resource not found LOGGER.info("Resource does not exist...: " + cres.getStatus() + ":" + cres.getEntity(String.class)); - LoggingContext.restore(); } else if (cres.getStatus() == 200 || cres.getStatus() == 204) { LOGGER.info("Resource " + url + " deleted"); - LoggingContext.restore(); } else { LOGGER.error("Deleting Resource failed: " + cres.getStatus() + ":" + cres.getEntity(String.class)); - LoggingContext.restore(); throw new AAIException("AAI_7116", "Error during DELETE"); } } @@ -440,18 +421,10 @@ public class RestController implements RestControllerInterface { String url = ""; transId += ":" + UUID.randomUUID().toString(); - LoggingContext.save(); - LoggingContext.partnerName(sourceID); - LoggingContext.targetEntity(TARGET_NAME); - LoggingContext.requestId(transId); - LoggingContext.serviceName(methodName); - LoggingContext.targetServiceName(methodName); - LOGGER.debug(methodName + " start"); try { - initRestClient(); url = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE) + apiVersion + "/" + path; ClientResponse cres = client.resource(url).accept("application/json").header("X-TransactionId", transId) @@ -473,7 +446,6 @@ public class RestController implements RestControllerInterface { throw new AAIException("AAI_7116", methodName + " with url=" + url + ", Exception: " + e.toString()); } finally { - LoggingContext.restore(); } } @@ -558,13 +530,6 @@ public class RestController implements RestControllerInterface { String url = ""; transId += ":" + UUID.randomUUID().toString(); - LoggingContext.save(); - LoggingContext.partnerName(sourceID); - LoggingContext.targetEntity(TARGET_NAME); - LoggingContext.requestId(transId); - LoggingContext.serviceName(methodName); - LoggingContext.targetServiceName(methodName); - int numRetries = 5; ClientResponse cres = null; int statusCode = -1; @@ -582,7 +547,6 @@ public class RestController implements RestControllerInterface { AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)) + path; } - initRestClient(); do { cres = client.resource(url).accept("application/json").header("X-TransactionId", transId) @@ -613,7 +577,6 @@ public class RestController implements RestControllerInterface { throw new AAIException("AAI_7116", methodName + " with url=" + url + ", Exception: " + e.toString()); } finally { - LoggingContext.restore(); } } diff --git a/aai-core/src/main/java/org/onap/aai/util/StoreNotificationEvent.java b/aai-core/src/main/java/org/onap/aai/util/StoreNotificationEvent.java index 8b2bf50a..01d21ca7 100644 --- a/aai-core/src/main/java/org/onap/aai/util/StoreNotificationEvent.java +++ b/aai-core/src/main/java/org/onap/aai/util/StoreNotificationEvent.java @@ -20,8 +20,8 @@ package org.onap.aai.util; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.StringWriter; import java.util.Iterator; @@ -45,7 +45,7 @@ import org.springframework.core.env.Environment; public class StoreNotificationEvent { - private static final EELFLogger logger = EELFManager.getInstance().getLogger(StoreNotificationEvent.class); + private static final Logger LOGGER = LoggerFactory.getLogger(StoreNotificationEvent.class); private MessageProducer messageProducer; private String fromAppId = ""; @@ -81,7 +81,7 @@ public class StoreNotificationEvent { * @throws AAIException * the AAI exception */ - public String storeEvent(NotificationEvent.EventHeader eh, Object obj) throws AAIException { + public String storeEventAndSendToJms(NotificationEvent.EventHeader eh, Object obj) throws AAIException { if (obj == null) { throw new AAIException("AAI_7350"); @@ -235,7 +235,94 @@ public class StoreNotificationEvent { } } - public String storeEvent(Loader loader, Introspector eventHeader, Introspector obj) throws AAIException { + public String storeEventOnly(Loader loader, Introspector eventHeader, Introspector obj) throws AAIException { + if (obj == null) { + throw new AAIException("AAI_7350"); + } + + try { + final Introspector notificationEvent = loader.introspectorFromName("notification-event"); + + if (eventHeader.getValue("id") == null) { + eventHeader.setValue("id", genDate2() + "-" + UUID.randomUUID().toString()); + } + + if (eventHeader.getValue("timestamp") == null) { + eventHeader.setValue("timestamp", genDate()); + } + + if (eventHeader.getValue("entity-link") == null) { + eventHeader.setValue("entity-link", "UNK"); + } + + if (eventHeader.getValue("action") == null) { + eventHeader.setValue("action", "UNK"); + } + + if (eventHeader.getValue("event-type") == null) { + eventHeader.setValue("event-type", AAIConfig.get("aai.notificationEvent.default.eventType", "UNK")); + } + + if (eventHeader.getValue("domain") == null) { + eventHeader.setValue("domain", AAIConfig.get("aai.notificationEvent.default.domain", "UNK")); + } + + if (eventHeader.getValue("source-name") == null) { + eventHeader.setValue("source-name", AAIConfig.get("aai.notificationEvent.default.sourceName", "UNK")); + } + + if (eventHeader.getValue("sequence-number") == null) { + eventHeader.setValue("sequence-number", + AAIConfig.get("aai.notificationEvent.default.sequenceNumber", "UNK")); + } + + if (eventHeader.getValue("severity") == null) { + eventHeader.setValue("severity", AAIConfig.get("aai.notificationEvent.default.severity", "UNK")); + } + + if (eventHeader.getValue("version") == null) { + eventHeader.setValue("version", AAIConfig.get("aai.notificationEvent.default.version", "UNK")); + } + + if (notificationEvent.getValue("cambria-partition") == null) { + notificationEvent.setValue("cambria-partition", + AAIConfig.get("aai.notificationEvent.default.partition", AAIConstants.UEB_PUB_PARTITION_AAI)); + } + + notificationEvent.setValue("event-header", eventHeader.getUnderlyingObject()); + notificationEvent.setValue("entity", obj.getUnderlyingObject()); + + String entityJson = notificationEvent.marshal(false); + JSONObject entityJsonObject = new JSONObject(entityJson); + + JSONObject entityJsonObjectUpdated = new JSONObject(); + + JSONObject entityHeader = entityJsonObject.getJSONObject("event-header"); + String cambriaPartition = entityJsonObject.getString("cambria.partition"); + + entityJsonObject.remove("event-header"); + entityJsonObject.remove("cambria.partition"); + + entityJsonObjectUpdated.put("event-header", entityHeader); + entityJsonObjectUpdated.put("cambria.partition", cambriaPartition); + + Iterator<String> iter = entityJsonObject.keys(); + JSONObject entity = new JSONObject(); + if (iter.hasNext()) { + entity = entityJsonObject.getJSONObject(iter.next()); + } + + entityJsonObjectUpdated.put("entity", entity); + + return entityJsonObjectUpdated.toString(); + } catch (JSONException e) { + throw new AAIException("AAI_7350", e); + } catch (AAIUnknownObjectException e) { + throw new AAIException("AAI_7350", e); + } + } + + public String storeEventAndSendToJms(Loader loader, Introspector eventHeader, Introspector obj) throws AAIException { if (obj == null) { throw new AAIException("AAI_7350"); } diff --git a/aai-core/src/main/java/org/onap/aai/util/delta/DeltaAction.java b/aai-core/src/main/java/org/onap/aai/util/delta/DeltaAction.java new file mode 100644 index 00000000..1b1e49ae --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/delta/DeltaAction.java @@ -0,0 +1,30 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.util.delta; + +public enum DeltaAction { + CREATE, + UPDATE, + DELETE, + CREATE_REL, + DELETE_REL, + STATIC +} diff --git a/aai-core/src/main/java/org/onap/aai/util/delta/DeltaEvents.java b/aai-core/src/main/java/org/onap/aai/util/delta/DeltaEvents.java new file mode 100644 index 00000000..f240f4e8 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/delta/DeltaEvents.java @@ -0,0 +1,136 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.util.delta; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.gson.*; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.dmaap.AAIDmaapEventJMSProducer; +import org.onap.aai.dmaap.MessageProducer; +import org.onap.aai.util.AAIConfig; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; + +public class DeltaEvents { + + private static final Logger LOGGER = LoggerFactory.getLogger(DeltaEvents.class); + + private static final Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) + .create(); + + private String transId; + private String sourceName; + private String eventVersion = "v1"; + private String schemaVersion; + private Map<String, ObjectDelta> objectDeltas; + + private MessageProducer messageProducer; + + public DeltaEvents(String transId, String sourceName, String schemaVersion, Map<String, ObjectDelta> objectDeltas) { + this(transId, sourceName, schemaVersion, objectDeltas, new AAIDmaapEventJMSProducer()); + } + + public DeltaEvents(String transId, String sourceName, String schemaVersion, Map<String, ObjectDelta> objectDeltas, MessageProducer messageProducer) { + this.transId = transId; + this.sourceName = sourceName; + this.schemaVersion = schemaVersion; + this.objectDeltas = objectDeltas; + this.messageProducer = messageProducer; + } + + public boolean triggerEvents() { + if (objectDeltas.isEmpty()) { + return false; + } + + JsonObject finalJson = new JsonObject(); + finalJson.addProperty("event-topic", "DELTA"); + finalJson.addProperty("transId", transId); + finalJson.addProperty("fromAppId", sourceName); + finalJson.addProperty("fullId", ""); + finalJson.add("aaiEventPayload", buildEvent()); + + this.messageProducer.sendMessageToDefaultDestination(finalJson.toString()); + return true; + } + + private JsonObject buildEvent() { + JsonObject event = new JsonObject(); + event.addProperty("cambria.partition", this.getPartition()); + event.add("event-header", getHeader()); + event.add("entities", gson.toJsonTree(objectDeltas.values())); + return event; + } + + private String getPartition() { + return "DELTA"; + } + + private JsonObject getHeader() { + ObjectDelta first = objectDeltas.values().iterator().next(); + JsonObject header = new JsonObject(); + header.addProperty("id", this.transId); + header.addProperty("timestamp", this.getTimeStamp(first.getTimestamp())); + header.addProperty("source-name", this.sourceName); + header.addProperty("domain", this.getDomain()); + header.addProperty("event-type", this.getEventType()); + header.addProperty("event-version", this.eventVersion); + header.addProperty("schema-version", this.schemaVersion); + header.addProperty("action", first.getAction().toString()); + header.addProperty("entity-type", this.getEntityType(first)); + header.addProperty("entity-link", first.getUri()); + header.addProperty("entity-uuid", this.getUUID(first)); + + return header; + } + + private String getUUID(ObjectDelta objectDelta) { + return (String) objectDelta.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue(); + } + + private String getEntityType(ObjectDelta objectDelta) { + return (String) objectDelta.getPropertyDeltas().get(AAIProperties.NODE_TYPE).getValue(); + } + + private String getEventType() { + return "DELTA"; + } + + private String getDomain() { + return AAIConfig.get("aai.notificationEvent.default.domain", "UNK"); + } + + /** + * Given Long timestamp convert to format YYYYMMdd-HH:mm:ss:SSS + * @param timestamp milliseconds since epoc + * @return long timestamp in format YYYYMMdd-HH:mm:ss:SSS + */ + private String getTimeStamp(long timestamp) { + //SimpleDateFormat is not thread safe new instance needed + DateFormat df = new SimpleDateFormat("YYYYMMdd-HH:mm:ss:SSS"); + return df.format(new Date(timestamp)); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/delta/ObjectDelta.java b/aai-core/src/main/java/org/onap/aai/util/delta/ObjectDelta.java new file mode 100644 index 00000000..c560dbf6 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/delta/ObjectDelta.java @@ -0,0 +1,126 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.util.delta; + +import com.google.gson.annotations.SerializedName; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ObjectDelta { + + @SerializedName("uri") + private String uri; + + @SerializedName("action") + private DeltaAction action; + + @SerializedName("source-of-truth") + private String sourceOfTruth; + + @SerializedName("timestamp") + private long timestamp; + + @SerializedName("property-deltas") + private Map<String, PropertyDelta> propertyDeltas = new HashMap<>(); + + @SerializedName("relationship-deltas") + private List<RelationshipDelta> relationshipDeltas = new ArrayList<>(); + + public ObjectDelta(String uri, DeltaAction action, String sourceOfTruth, long timestamp) { + this.uri = uri; + this.action = action; + this.sourceOfTruth = sourceOfTruth; + this.timestamp = timestamp; + } + + public void addPropertyDelta(String prop, PropertyDelta propertyDelta) { + propertyDeltas.put(prop, propertyDelta); + } + + public void addRelationshipDelta(RelationshipDelta relationshipDelta) { + relationshipDeltas.add(relationshipDelta); + } + + + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public DeltaAction getAction() { + return action; + } + + public void setAction(DeltaAction action) { + this.action = action; + } + + public String getSourceOfTruth() { + return sourceOfTruth; + } + + public void setSourceOfTruth(String sourceOfTruth) { + this.sourceOfTruth = sourceOfTruth; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public void setPropertyDeltas(Map<String, PropertyDelta> propertyDeltas) { + this.propertyDeltas = propertyDeltas; + } + + public void setRelationshipDeltas(List<RelationshipDelta> relationshipDeltas) { + this.relationshipDeltas = relationshipDeltas; + } + + public Map<String, PropertyDelta> getPropertyDeltas() { + return propertyDeltas; + } + + public List<RelationshipDelta> getRelationshipDeltas() { + return relationshipDeltas; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("uri", uri) + .append("action", action) + .append("sourceOfTruth", sourceOfTruth) + .append("timestamp", timestamp) + .append("propertyDeltas", propertyDeltas) + .append("relationshipDeltas", relationshipDeltas) + .toString(); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/delta/PropertyDelta.java b/aai-core/src/main/java/org/onap/aai/util/delta/PropertyDelta.java new file mode 100644 index 00000000..46a0072c --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/delta/PropertyDelta.java @@ -0,0 +1,79 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.delta; + +import com.google.gson.annotations.SerializedName; +import org.apache.commons.lang3.builder.ToStringBuilder; + +public class PropertyDelta { + + @SerializedName("action") + protected DeltaAction action; + + @SerializedName("value") + protected Object value; + + @SerializedName("old-value") + private Object oldValue; + + + public PropertyDelta(DeltaAction action, Object value) { + this.action = action; + this.value = value; + } + + public PropertyDelta(DeltaAction action, Object value, Object oldValue) { + this(action, value); + this.oldValue = oldValue; + } + + public DeltaAction getAction() { + return action; + } + + public void setAction(DeltaAction action) { + this.action = action; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public Object getOldValue() { + return oldValue; + } + + public void setOldValue(Object oldValue) { + this.oldValue = oldValue; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("action", action) + .append("value", value) + .append("oldValue", oldValue) + .toString(); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/delta/PropertyDeltaFactory.java b/aai-core/src/main/java/org/onap/aai/util/delta/PropertyDeltaFactory.java new file mode 100644 index 00000000..366d6886 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/delta/PropertyDeltaFactory.java @@ -0,0 +1,34 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.util.delta; + +public class PropertyDeltaFactory { + + public static PropertyDelta getDelta(DeltaAction action, Object value, Object oldValue) { + //TODO handle if action is not UPDATE + return new PropertyDelta(action, value, oldValue); + } + + public static PropertyDelta getDelta(DeltaAction action, Object value) { + //TODO handle if action is UPDATE + return new PropertyDelta(action, value); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/delta/RelationshipDelta.java b/aai-core/src/main/java/org/onap/aai/util/delta/RelationshipDelta.java new file mode 100644 index 00000000..1dcad1b3 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/delta/RelationshipDelta.java @@ -0,0 +1,133 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.util.delta; + +import com.google.gson.annotations.SerializedName; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import java.util.HashMap; +import java.util.Map; + +public class RelationshipDelta { + + @SerializedName("action") + private DeltaAction action; + + @SerializedName("in-v-uuid") + private String inVUuid; + + @SerializedName("out-v-uuid") + private String outVUuid; + + @SerializedName("in-v-uri") + private String inVUri; + + @SerializedName("out-v-uri") + private String outVUri; + + @SerializedName("label") + private String label; + + @SerializedName("props") + private Map<String, Object> props = new HashMap<>(); + + public RelationshipDelta(DeltaAction action, String inVUUID, String outVUUID, String inVUri, String outVUri, String label) { + this.action = action; + this.inVUuid = inVUUID; + this.outVUuid = outVUUID; + this.inVUri = inVUri; + this.outVUri = outVUri; + this.label = label; + } + + public DeltaAction getAction() { + return action; + } + + public void setAction(DeltaAction action) { + this.action = action; + } + + public String getInVUuid() { + return inVUuid; + } + + public void setInVUuid(String inVUuid) { + this.inVUuid = inVUuid; + } + + public String getOutVUuid() { + return outVUuid; + } + + public void setOutVUuid(String outVUuid) { + this.outVUuid = outVUuid; + } + + public String getInVUri() { + return inVUri; + } + + public void setInVUri(String inVUri) { + this.inVUri = inVUri; + } + + public String getOutVUri() { + return outVUri; + } + + public void setOutVUri(String outVUri) { + this.outVUri = outVUri; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public Map<String, Object> getProps() { + return props; + } + + public void setProps(Map<String, Object> props) { + this.props = props; + } + + public void addProp(String key, String value) { + this.props.put(key, value); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("action", action) + .append("inVUuid", inVUuid) + .append("outVUuid", outVUuid) + .append("inVUri", inVUri) + .append("outVUri", outVUri) + .append("label", label) + .append("props", props) + .toString(); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/web/EventClientPublisher.java b/aai-core/src/main/java/org/onap/aai/web/EventClientPublisher.java index d552f231..c5629254 100644 --- a/aai-core/src/main/java/org/onap/aai/web/EventClientPublisher.java +++ b/aai-core/src/main/java/org/onap/aai/web/EventClientPublisher.java @@ -20,8 +20,8 @@ package org.onap.aai.web; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; import java.util.Base64; @@ -37,7 +37,7 @@ import org.springframework.web.client.RestTemplate; @Configuration public class EventClientPublisher { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(EventClientPublisher.class); + private static final Logger LOGGER = LoggerFactory.getLogger(EventClientPublisher.class); @Value("${dmaap.ribbon.listOfServers:}") private String hosts; diff --git a/aai-core/src/main/resources/specs/transform-related-to-node.json b/aai-core/src/main/resources/specs/transform-related-to-node.json new file mode 100644 index 00000000..c7e018a8 --- /dev/null +++ b/aai-core/src/main/resources/specs/transform-related-to-node.json @@ -0,0 +1,21 @@ +[ + { + "operation": "shift", + "spec": { + "results": "result", + "*": "&" + } + }, + { + "operation": "shift", + "spec": { + "result": { + "*": { + "related-to": "result.[&(1,0)].&(0,0).node", + "*": "result.[&(1,0)].&(0,0)" + } + }, + "*": "&" + } + } +]
\ No newline at end of file diff --git a/aai-core/src/main/resources/swagger.html.ftl b/aai-core/src/main/resources/swagger.html.ftl new file mode 100644 index 00000000..1a2827f8 --- /dev/null +++ b/aai-core/src/main/resources/swagger.html.ftl @@ -0,0 +1,241 @@ +<#-- + + ============LICENSE_START======================================================= + org.onap.aai + ================================================================================ + Copyright © 2017-18 AT&T Intellectual Property. All rights reserved. + Copyright © 2018 Huawei Technologies (Australia) Pty Ltd. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + + ECOMP is a trademark and service mark of AT&T Intellectual Property. + +--> +<!DOCTYPE html> +<html> +<head> +<style>/*! + * Bootstrap v3.3.6 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{p EdgeRules.ftl + ont-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover,a.text-primary:focus{color:#286090}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover,a.bg-primary:focus{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:800px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:900px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#fff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform 0.6s ease-in-out;-moz-transition:-moz-transform 0.6s ease-in-out;-o-transition:-o-transform 0.6s ease-in-out;transition:transform 0.6s ease-in-out;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;-moz-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.panel-definition{border-color:#a2a2a2}.panel-definition>.panel-heading{color:#000;background-color:#eee;border-color:#a2a2a2}.panel-definition>.panel-heading+.panel-collapse>.panel-body{border-top-color:#a2a2a2}.panel-definition>.panel-heading .badge{color:#eee;background-color:#000}.panel-definition>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#a2a2a2}.json-schema-description:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Description";padding-bottom:.5em;display:block}.json-schema-description:not(:last-child){padding-bottom:1.5em}.json-schema-properties:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Properties";padding-bottom:.5em;display:block}.json-schema-properties:not(:last-child){padding-bottom:1.5em}.json-schema-properties dd:not(:last-child){padding-bottom:1em}.json-schema-properties dl{margin:0}.json-schema-example:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Example";padding-bottom:.5em;display:block}.json-schema-example:not(:last-child){padding-bottom:1.5em}.json-schema-array-items:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Items";padding-bottom:.5em;display:block}.json-schema-array-items:not(:last-child){padding-bottom:1.5em}.json-schema-allOf-inherited:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Inherited";padding-bottom:.5em;display:block}.json-schema-allOf-inherited:not(:last-child){padding-bottom:1.5em}.json-schema-allOf-inherited ul{padding-left:0;list-style:none}.json-schema-anyOf>dl{border-left:2px solid #a2a2a2;padding-left:1em}.json-schema-anyOf>dl dt:not(:first-child):before{content:"or "}.json-schema-anyOf>dl dt:first-child:before{content:"either "}.json-schema-additionalProperties:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Additional properties";padding-bottom:.5em;display:block}.json-schema-additionalProperties:not(:last-child){padding-bottom:1.5em}.json-inner-schema .json-schema-properties,.json-inner-schema .json-schema-array-items,.json-inner-schema .json-schema-description,.json-inner-schema .json-schema-example{padding-left:1em;margin-top:.5em;padding-bottom:.5em;border-left:2px solid #a2a2a2}.json-property-discriminator:before{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;background-color:#777;content:"discriminator"}a.json-property-discriminator:before:hover,a.json-property-discriminator:before:focus{color:#fff;text-decoration:none;cursor:pointer}.json-property-discriminator:before:empty{display:none}.btn .json-property-discriminator:before{position:relative;top:-1px}.json-property-discriminator:before[href]:hover,.json-property-discriminator:before[href]:focus{background-color:#5e5e5e}.json-property-required:before{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;background-color:#777;content:"required"}a.json-property-required:before:hover,a.json-property-required:before:focus{color:#fff;text-decoration:none;cursor:pointer}.json-property-required:before:empty{display:none}.btn .json-property-required:before{position:relative;top:-1px}.json-property-required:before[href]:hover,.json-property-required:before[href]:focus{background-color:#5e5e5e}.json-property-read-only:before{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;background-color:#777;content:"read only"}a.json-property-read-only:before:hover,a.json-property-read-only:before:focus{color:#fff;text-decoration:none;cursor:pointer}.json-property-read-only:before:empty{display:none}.btn .json-property-read-only:before{position:relative;top:-1px}.json-property-read-only:before[href]:hover,.json-property-read-only:before[href]:focus{background-color:#5e5e5e}.json-property-type{font-style:italic;font-weight:100}.json-property-format{font-size:smaller}.json-property-enum{font-weight:lighter;font-size:small}.json-property-default-value{font-weight:lighter;font-size:small}.json-property-default-value:before{content:'(default: "'}.json-property-default-value:after{content:'")'}.json-property-enum-item{font-weight:lighter;font-size:small}.json-property-enum-item:before,.json-property-enum-item:after{content:"\""}.json-schema--reference{font-size:90%}.table.swagger--summary>tbody>tr>td.swagger--summary-path{vertical-align:middle}.table.swagger--summary>tbody>tr>td p{margin:0}.swagger--panel-operation-post{border-color:#78cc94}.swagger--panel-operation-post>.panel-heading{color:#333;background-color:#e7f6ec;border-color:#78cc94}.swagger--panel-operation-post>.panel-heading+.panel-collapse>.panel-body{border-top-color:#78cc94}.swagger--panel-operation-post>.panel-heading .badge{color:#e7f6ec;background-color:#333}.swagger--panel-operation-post>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#78cc94}.swagger--panel-operation-post .operation-name{font-weight:bold}.swagger--panel-operation-post .operation-summary{float:right !important}.swagger--panel-operation-get{border-color:#74a8d1}.swagger--panel-operation-get>.panel-heading{color:#333;background-color:#e7f0f7;border-color:#74a8d1}.swagger--panel-operation-get>.panel-heading+.panel-collapse>.panel-body{border-top-color:#74a8d1}.swagger--panel-operation-get>.panel-heading .badge{color:#e7f0f7;background-color:#333}.swagger--panel-operation-get>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#74a8d1}.swagger--panel-operation-get .operation-name{font-weight:bold}.swagger--panel-operation-get .operation-summary{float:right !important}.swagger--panel-operation-put{border-color:#d8ab71}.swagger--panel-operation-put>.panel-heading{color:#333;background-color:#f9f2e9;border-color:#d8ab71}.swagger--panel-operation-put>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d8ab71}.swagger--panel-operation-put>.panel-heading .badge{color:#f9f2e9;background-color:#333}.swagger--panel-operation-put>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d8ab71}.swagger--panel-operation-put .operation-name{font-weight:bold}.swagger--panel-operation-put .operation-summary{float:right !important}.swagger--panel-operation-patch{border-color:#ed7c59}.swagger--panel-operation-patch>.panel-heading{color:#333;background-color:#FCE9E3;border-color:#ed7c59}.swagger--panel-operation-patch>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ed7c59}.swagger--panel-operation-patch>.panel-heading .badge{color:#FCE9E3;background-color:#333}.swagger--panel-operation-patch>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ed7c59}.swagger--panel-operation-patch .operation-name{font-weight:bold}.swagger--panel-operation-patch .operation-summary{float:right !important}.swagger--panel-operation-options{border-color:#74a8d1}.swagger--panel-operation-options>.panel-heading{color:#333;background-color:#e7f0f7;border-color:#74a8d1}.swagger--panel-operation-options>.panel-heading+.panel-collapse>.panel-body{border-top-color:#74a8d1}.swagger--panel-operation-options>.panel-heading .badge{color:#e7f0f7;background-color:#333}.swagger--panel-operation-options>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#74a8d1}.swagger--panel-operation-options .operation-name{font-weight:bold}.swagger--panel-operation-options .operation-summary{float:right !important}.swagger--panel-operation-delete{border-color:#c77d7d}.swagger--panel-operation-delete>.panel-heading{color:#333;background-color:#f5e8e8;border-color:#c77d7d}.swagger--panel-operation-delete>.panel-heading+.panel-collapse>.panel-body{border-top-color:#c77d7d}.swagger--panel-operation-delete>.panel-heading .badge{color:#f5e8e8;background-color:#333}.swagger--panel-operation-delete>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#c77d7d}.swagger--panel-operation-delete .operation-name{font-weight:bold}.swagger--panel-operation-delete .operation-summary{float:right !important}.swagger--panel-operation-head{border-color:#f3ff34}.swagger--panel-operation-head>.panel-heading{color:#333;background-color:#fcffcd;border-color:#f3ff34}.swagger--panel-operation-head>.panel-heading+.panel-collapse>.panel-body{border-top-color:#f3ff34}.swagger--panel-operation-head>.panel-heading .badge{color:#fcffcd;background-color:#333}.swagger--panel-operation-head>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#f3ff34}.swagger--panel-operation-head .operation-name{font-weight:bold}.swagger--panel-operation-head .operation-summary{float:right !important}.sw-operation-description:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Description";padding-bottom:.5em;display:block}.sw-operation-description:not(:last-child){padding-bottom:1.5em}.sw-request-params:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Request parameters";padding-bottom:.5em;display:block}.sw-request-params:not(:last-child){padding-bottom:1.5em}.sw-request-body:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Request body";padding-bottom:.5em;display:block}.sw-request-body:not(:last-child){padding-bottom:1.5em}.sw-responses:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Responses";padding-bottom:.5em;display:block}.sw-responses:not(:last-child){padding-bottom:1.5em}.swagger--global:before{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;background-color:#777;content:'global'}a.swagger--global:before:hover,a.swagger--global:before:focus{color:#fff;text-decoration:none;cursor:pointer}.swagger--global:before:empty{display:none}.btn .swagger--global:before{position:relative;top:-1px}.swagger--global:before[href]:hover,.swagger--global:before[href]:focus{background-color:#5e5e5e}table.table th.sw-param-key{width:auto}table.table th.sw-param-key:before{content:"Key"}table.table th.sw-param-name{width:auto}table.table th.sw-param-name:before{content:"Name"}table.table th.sw-param-description{width:auto}table.table th.sw-param-description:before{content:"Description"}table.table th.sw-param-data-type{width:auto}table.table th.sw-param-data-type:before{content:"Data type"}table.table th.sw-param-type{width:auto}table.table th.sw-param-type:before{content:"Type"}table.table th.sw-request-security-schema{width:auto}table.table th.sw-request-security-schema:before{content:"Schema"}table.table th.sw-request-security-scopes{width:auto}table.table th.sw-request-security-scopes:before{content:"Scopes"}table.table th.sw-response-header-name{width:auto}table.table th.sw-response-header-name:before{content:"Header"}table.table th.sw-response-header-description{width:auto}table.table th.sw-response-header-description:before{content:"Description"}table.table th.sw-response-header-data-type{width:auto}table.table th.sw-response-header-data-type:before{content:"Data type"}.sw-response-name-value{font-weight:bold}.sw-response-description-text{padding-bottom:.5em}code.highlight{padding:0}.panel-security-definition{border-color:#a2a2a2}.panel-security-definition>.panel-heading{color:#000;background-color:#eee;border-color:#a2a2a2}.panel-security-definition>.panel-heading+.panel-collapse>.panel-body{border-top-color:#a2a2a2}.panel-security-definition>.panel-heading .badge{color:#eee;background-color:#000}.panel-security-definition>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#a2a2a2}.sw-request-security:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Security";padding-bottom:.5em;display:block}.sw-request-security:not(:last-child){padding-bottom:1.5em}.sw-security-definition-basic:before{color:#555;font-size:smaller;content:"(HTTP Basic Authentication)"}span.sw-default-value-header{font-weight:bold}.sw-info-version{font-weight:bold}.sw-info-version span{font-family:monospace;font-weight:normal;font-size:1.1em}</style> + + <meta charset="UTF-8"> + <title>Active and Available Inventory REST API.</title> +</head> +<body> +<div class="container"> + <h1>Active and Available Inventory REST API.</h1> + <p class="sw-info-version">Version: <span>${version}</span></p> + <p><p>${description}</p> + </p> + + <div id="sw-schemes" class="sw-default-value"> + <span class="sw-default-value-header">Schemes:</span> + https + </div> + + <h2 id="swagger--summary-tags">Summary</h2> + <ol> + <#list aaiApis?keys as key> + <li><a href="#tag-${key}">Tag: ${key}</a> + </#list> + <li><a href="#Paths">Paths</a> + <li><a href="#SchemaDefinitions">Schema definitions</a> + </ol> + + <#list aaiApis?keys as key> + <h3 id="tag-${key}" class="swagger-summary-tag">Tag: ${key}</h3> + <table class="table table-bordered table-condensed swagger--summary"> + <thead><tr> + <th>Operation</th><th>Description</th> + </tr></thead> + <tbody> + <#list aaiApis[key] as api> + <#list api.getHttpMethods() as httpVerb> + <tr><td><a href="#operation-${api.getOperation()}${httpVerb.getType()}"> + ${httpVerb.getType()?upper_case} ${api.getPath()}</a></td> + <td><p>${httpVerb.getSummary()}</p></td> + </tr> + </#list> + </#list> + </tbody> + </table> + </#list> + + <h2 id="Paths">Paths</h2> + <#list sortedAaiApis?keys as key> + <#list sortedAaiApis[key] as api> + <#list api.getHttpMethods() as httpVerb> + <span id="path-${api.getOperation()}"></span> + <div id="operation-${api.getOperation()}${httpVerb.getType()}" class="swagger--panel-operation-${httpVerb.getType()} panel"> + <div class="panel-heading"> + <div class="operation-summary">${httpVerb.getSummary()}</div> + <h3 class="panel-title"><span class="operation-name">${httpVerb.getType()?upper_case}</span> + <strong>${api.getPath()}</strong></h3> + Tags: <a href="#tag-${api.getTag()}">${api.getTag()}</a> + </div> + <div class="panel-body"> + <section class="sw-operation-description"> + <p>${httpVerb.getSummary()}</p> + </section> + <#if httpVerb.isConsumerEnabled()> + <section class="sw-request-body"> + <p><span class="label label-default">application/json</span> <span class="label label-default">application/xml</span> </p> + <#if httpVerb.isBodyParametersEnabled()> + <div class="row"> + <div class="col-md-6"> + <p><p>${httpVerb.getBodyParameters()["description"]}</p></p> + </div> + <div class="col-md-6 sw-request-model"> + <div class="panel panel-definition"> + <div class="panel-body"> + <a class="json-schema-ref" href="${httpVerb.getSchemaLink()}">${httpVerb.getSchemaType()}</a> + </div></div></div></div> + </#if> + </section> + </#if> + <#if httpVerb.isParametersEnabled()> + <section class="sw-request-params"> + <table class="table"> + <thead><tr> + <th class="sw-param-name"></th> + <th class="sw-param-description"></th> + <th class="sw-param-type"></th> + <th class="sw-param-data-type"></th> + <th class="sw-param-annotation"></th> + </tr></thead> + <tbody> + <#list httpVerb.getParameters() as param> + <tr><td>${param["name"]}</td> + <td> + <#if param['description']??> + <p>${param["description"]}</p> + </#if> + </td> + <td>${param["in"]}</td> + <td> + <#if param['type']??> + <span class="json-property-type">${param["type"]}</span> + <span class="json-property-range" title="Value limits"></span> + </#if> + </td> + <td> + <#if param['required']> + <span class="json-property-required"></span> + </#if> + </td> + </tr> + </#list> + </tbody> + </table></section> + </#if> + + <section class="sw-responses"> + <p><span class="label label-default">application/json</span> <span class="label label-default">application/xml</span> </p> + <dl> + <#list httpVerb.getResponses() as response> + <dt class="sw-response-${response.getResponseCode()}"> + ${response.getResponseCode()} OK + </dt> + <dd class="sw-response-${response.getResponseCode()}"> + <div class="row"><div class="col-md-12"> + <p>successful operation</p> + </div></div> + <div class="row"> + <#if httpVerb.isHasReturnSchema()> + <div class="col-md-6 sw-response-model"> + <div class="panel panel-definition"> + <div class="panel-body"> + <a class="json-schema-ref" href="${httpVerb.getReturnSchemaLink()}">${httpVerb.getReturnSchemaObject()}</a> + </div></div></div> + </#if> + </div> + </dd> + </#list> + <dt class="sw-response-default">default</dt> + <dd class="sw-response-default"> + <div class="row"><div class="col-md-12"> + <p>Response codes found in <a href="${wikiLink}">response codes</a>.</p> + </div></div> + <div class="row"><div class="col-md-6 sw-response-model"></div></div> + </dd> + </dl> + </section> + </div> + </div> + + </#list> + </#list> + </#list> + + <h2 id="SchemaDefinitions">Schema definitions</h2> + <#list definitions as definition> + <div id="definition-${definition.getDefinitionName()}" class="panel panel-definition"> + <div class="panel-heading"><h3 class="panel-title"> + <a name="/definitions/${definition.getDefinitionName()}"></a>${definition.getDefinitionName()}: + <span class="json-property-type"><span class="json-property-type">object</span> + <span class="json-property-range" title="Value limits"></span></span> + </h3></div> + <div class="panel-body"> + <#if definition.isHasDescription()> + <section class="json-schema-description"> + ${definition.getDefinitionDescription()} + </section> + </#if> + <section class="json-schema-properties"><dl> + <#list definition.getRegularPropertyList() as definitionProperty> + <dt data-property-name="${definitionProperty.getPropertyName()}"> + <span class="json-property-name">${definitionProperty.getPropertyName()}:</span> + <#if definitionProperty.isHasType()> + <span class="json-property-type">${definitionProperty.getPropertyType()}</span> + </#if> + <span class="json-property-range" title="Value limits"></span> + <#if definitionProperty.isRequired()> + <span class="json-property-required"></span> + </#if> + </dt> + <dd> + <#if definitionProperty.isHasPropertyDescription()> + <p>${definitionProperty.getPropertyDescription()}</p> + </#if> + <div class="json-inner-schema"></div> + </dd> + </#list> + <#list definition.getSchemaPropertyList() as definitionProperty> + <dt data-property-name="${definitionProperty.getPropertyName()}"> + <span class="json-property-name">${definitionProperty.getPropertyName()}:</span> + <#if definitionProperty.isHasType()> + <span class="json-property-type">${definitionProperty.getPropertyType()}</span> + </#if> + <span class="json-property-range" title="Value limits"></span> + <#if definitionProperty.isRequired()> + <span class="json-property-required"></span> + </#if> + </dt> + <dd><div class="json-inner-schema"><section class="json-schema-array-items"> + <span class="json-property-type"> + <a class="json-schema-ref" href="${definitionProperty.getPropertyReference()}">${definitionProperty.getPropertyReferenceObjectName()}</a></span> + <span class="json-property-range" title="Value limits"></span> + <div class="json-inner-schema"></div> + </section></div></dd> + </#list> + </dl></section> + </div></div> + + </#list> +</div> +</body> +</html> diff --git a/aai-core/src/test/java/org/onap/aai/AAISetup.java b/aai-core/src/test/java/org/onap/aai/AAISetup.java index 4bc30b8c..ac9cba68 100644 --- a/aai-core/src/test/java/org/onap/aai/AAISetup.java +++ b/aai-core/src/test/java/org/onap/aai/AAISetup.java @@ -20,15 +20,10 @@ package org.onap.aai; -import java.util.Map; - -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; -import org.onap.aai.config.ConfigConfiguration; -import org.onap.aai.config.IntrospectionConfig; -import org.onap.aai.config.RestBeanConfig; -import org.onap.aai.config.SpringContextAware; +import org.onap.aai.config.*; import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.introspection.MoxyLoader; @@ -47,13 +42,30 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.rules.SpringClassRule; import org.springframework.test.context.junit4.rules.SpringMethodRule; +import java.util.Map; + @ContextConfiguration( - classes = {ConfigConfiguration.class, AAIConfigTranslator.class, EdgeIngestor.class, EdgeSerializer.class, - NodeIngestor.class, SpringContextAware.class, IntrospectionConfig.class, RestBeanConfig.class}) + classes = { + ConfigConfiguration.class, + AAIConfigTranslator.class, + EdgeIngestor.class, + EdgeSerializer.class, + NodeIngestor.class, + SpringContextAware.class, + IntrospectionConfig.class, + RestBeanConfig.class, + XmlFormatTransformerConfiguration.class + } +) @TestPropertySource( - properties = {"schema.uri.base.path = /aai", "schema.xsd.maxoccurs = 5000", "schema.translator.list=config", - "schema.nodes.location=src/test/resources/onap/oxm", - "schema.edges.location=src/test/resources/onap/dbedgerules"}) + properties = { + "schema.uri.base.path = /aai", + "schema.xsd.maxoccurs = 5000", + "schema.translator.list=config", + "schema.nodes.location=src/test/resources/onap/oxm", + "schema.edges.location=src/test/resources/onap/dbedgerules" + } +) public abstract class AAISetup { @ClassRule @@ -88,8 +100,8 @@ public abstract class AAISetup { protected static final String SERVICE_NAME = "JUNIT"; - @Before - public void setupBundleconfig() throws Exception { + @BeforeClass + public static void setupBundleconfig() throws Exception { System.setProperty("AJSC_HOME", "."); System.setProperty("BUNDLECONFIG_DIR", "src/test/resources/bundleconfig-local"); System.setProperty("aai.service.name", SERVICE_NAME); diff --git a/aai-core/src/test/java/org/onap/aai/DataLinkSetup.java b/aai-core/src/test/java/org/onap/aai/DataLinkSetup.java index f4d62d44..8a093669 100644 --- a/aai-core/src/test/java/org/onap/aai/DataLinkSetup.java +++ b/aai-core/src/test/java/org/onap/aai/DataLinkSetup.java @@ -25,10 +25,7 @@ import java.util.Map; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; -import org.onap.aai.config.ConfigConfiguration; -import org.onap.aai.config.IntrospectionConfig; -import org.onap.aai.config.RestBeanConfig; -import org.onap.aai.config.SpringContextAware; +import org.onap.aai.config.*; import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.introspection.MoxyLoader; @@ -53,7 +50,7 @@ import org.springframework.test.context.junit4.rules.SpringMethodRule; @ContextConfiguration( classes = {ConfigConfiguration.class, TestUtilConfigTranslatorforDataLink.class, EdgeIngestor.class, EdgeSerializer.class, NodeIngestor.class, SpringContextAware.class, IntrospectionConfig.class, - RestBeanConfig.class}) + RestBeanConfig.class, XmlFormatTransformerConfiguration.class}) @TestPropertySource( properties = {"schema.uri.base.path = /aai", "schema.xsd.maxoccurs = 5000", "schema.version.api.default = v4", "schema.version.edge.label.start = v4", "schema.version.depth.start = v3", diff --git a/aai-core/src/test/java/org/onap/aai/HttpTestUtil.java b/aai-core/src/test/java/org/onap/aai/HttpTestUtil.java index 6a9e7256..588cbc95 100644 --- a/aai-core/src/test/java/org/onap/aai/HttpTestUtil.java +++ b/aai-core/src/test/java/org/onap/aai/HttpTestUtil.java @@ -20,32 +20,20 @@ package org.onap.aai; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import javax.ws.rs.core.*; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.javatuples.Pair; import org.mockito.Mockito; import org.onap.aai.config.SpringContextAware; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.parsers.uri.URIToObject; import org.onap.aai.rest.db.DBRequest; import org.onap.aai.rest.db.HttpEntry; +import org.onap.aai.rest.ueb.UEBNotification; import org.onap.aai.restcore.HttpMethod; import org.onap.aai.restcore.RESTAPI; import org.onap.aai.serialization.engines.QueryStyle; @@ -53,15 +41,24 @@ import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.setup.SchemaVersion; import org.onap.aai.setup.SchemaVersions; +import javax.ws.rs.core.*; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.*; + +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.*; + public class HttpTestUtil extends RESTAPI { protected HttpEntry traversalHttpEntry; protected HttpEntry traversalUriHttpEntry; - private static final EELFLogger logger = EELFManager.getInstance().getLogger(HttpTestUtil.class); + private static final Logger logger = LoggerFactory.getLogger(HttpTestUtil.class); protected static final MediaType APPLICATION_JSON = MediaType.valueOf("application/json"); + protected static final MediaType APPLICATION_XML = MediaType.valueOf("application/xml"); private static final String EMPTY = ""; private final QueryStyle queryStyle; @@ -74,12 +71,40 @@ public class HttpTestUtil extends RESTAPI { protected List<String> aaiRequestContextList; protected List<MediaType> outputMediaTypes; + protected LoaderFactory loaderFactory; + protected SchemaVersions schemaVersions; + protected UEBNotification notification; + protected int notificationDepth; + protected String acceptType; public HttpTestUtil(QueryStyle qs) { + this(qs, "application/json"); + } + + public HttpTestUtil(QueryStyle qs, String acceptType) { this.queryStyle = qs; traversalHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + loaderFactory = SpringContextAware.getBean(LoaderFactory.class); + schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); + notification = null; + this.acceptType = acceptType; + } + + public HttpTestUtil(QueryStyle qs, UEBNotification uebNotification, int notificationDepth) { + this(qs, uebNotification, notificationDepth, "application/json"); + } + + public HttpTestUtil(QueryStyle qs, UEBNotification uebNotification, int notificationDepth, String acceptType) { + this.queryStyle = qs; + this.traversalHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + this.traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + this.loaderFactory = SpringContextAware.getBean(LoaderFactory.class); + this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); + this.notification = uebNotification; + this.notificationDepth = notificationDepth; + this.acceptType = acceptType; } public void init() { @@ -93,11 +118,15 @@ public class HttpTestUtil extends RESTAPI { headersMultiMap.add("X-FromAppId", "JUNIT"); headersMultiMap.add("X-TransactionId", UUID.randomUUID().toString()); headersMultiMap.add("Real-Time", "true"); - headersMultiMap.add("Accept", "application/json"); + headersMultiMap.add("Accept", acceptType); headersMultiMap.add("aai-request-context", ""); outputMediaTypes = new ArrayList<>(); - outputMediaTypes.add(APPLICATION_JSON); + if(acceptType.equals("application/json")){ + outputMediaTypes.add(APPLICATION_JSON); + } else { + outputMediaTypes.add(APPLICATION_XML); + } aaiRequestContextList = new ArrayList<>(); aaiRequestContextList.add(""); @@ -112,9 +141,127 @@ public class HttpTestUtil extends RESTAPI { doReturn(null).when(queryParameters).remove(anyObject()); when(httpHeaders.getMediaType()).thenReturn(APPLICATION_JSON); + + try { + if(notification != null){ + doNothing().when(notification).triggerEvents(); + } + } catch (AAIException e) { + e.printStackTrace(); + } } public Response doPut(String uri, String payload) throws UnsupportedEncodingException, AAIException { + Map<String, String> puts = new HashMap<>(); + puts.put(uri, payload); + return this.doPut(puts); + } + + public Response doPut(Map<String, String> uriPayload) throws UnsupportedEncodingException, AAIException { + + this.init(); + Response response = null; + boolean success = true; + TransactionalGraphEngine dbEngine = null; + + try { + + List<DBRequest> dbRequestList = new ArrayList<>(); + for(Map.Entry<String, String> entry : uriPayload.entrySet()){ + + String uri = entry.getKey(); + String payload = entry.getValue(); + if (uri.startsWith("/aai/")) { + uri = uri.substring(5); + } + + logger.info("Starting the put request for the uri {} with payload {}", uri, payload); + + String[] arr = uri.split("/"); + + SchemaVersion version = null; + + if (arr.length > 1) { + if (arr[0].matches("^v\\d+")) { + version = new SchemaVersion(arr[0]); + uri = uri.replaceAll("^v\\d+", ""); + } + } + + if (version == null) { + version = schemaVersions.getDefaultVersion(); + } + Mockito.when(uriInfo.getPath()).thenReturn(uri); + + if(notification != null){ + traversalHttpEntry.setHttpEntryProperties(version, notification, notificationDepth); + } else { + traversalHttpEntry.setHttpEntryProperties(version); + } + Loader loader = traversalHttpEntry.getLoader(); + dbEngine = traversalHttpEntry.getDbEngine(); + + URI uriObject = UriBuilder.fromPath(uri).build(); + URIToObject uriToObject = new URIToObject(loader, uriObject); + + String objType = uriToObject.getEntityName(); + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); + + logger.info("Unmarshalling the payload to this {}", objType); + + Introspector obj; + HttpMethod httpMethod; + if (uri.contains("/relationship-list/relationship")) { + obj = loader.unmarshal("relationship", payload, + org.onap.aai.restcore.MediaType.getEnum("application/json")); + httpMethod = HttpMethod.PUT_EDGE; + } else { + obj = loader.unmarshal(objType, payload, org.onap.aai.restcore.MediaType.getEnum("application/json")); + httpMethod = HttpMethod.PUT; + this.validateIntrospector(obj, loader, uriObject, httpMethod); + } + + DBRequest dbRequest = new DBRequest.Builder(httpMethod, uriObject, uriQuery, obj, httpHeaders, uriInfo, + "JUNIT-TRANSACTION").rawRequestContent(payload).build(); + + dbRequestList.add(dbRequest); + + } + + Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = + traversalHttpEntry.process(dbRequestList, "JUNIT"); + response = responsesTuple.getValue1().get(0).getValue1(); + + } catch (AAIException e) { + response = this.consumerExceptionResponseGenerator(httpHeaders, uriInfo, HttpMethod.PUT, e); + success = false; + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = this.consumerExceptionResponseGenerator(httpHeaders, uriInfo, HttpMethod.PUT, ex); + success = false; + } finally { + if (success) { + if (response != null) { + if ((response.getStatus() / 100) == 2) { + logger.info("Successfully completed the PUT request with status {} and committing it to DB", + response.getStatus()); + } else { + logFailure(HttpMethod.PUT, response); + } + } + dbEngine.commit(); + } else { + if (response != null) { + logFailure(HttpMethod.PUT, response); + } + dbEngine.rollback(); + } + } + + return response; + } + + public Response doPatch(String uri, String payload) throws UnsupportedEncodingException, AAIException { this.init(); Response response = null; @@ -133,22 +280,23 @@ public class HttpTestUtil extends RESTAPI { SchemaVersion version = null; - if (arr != null && arr.length > 1) { + if (arr.length > 1) { if (arr[0].matches("^v\\d+")) { version = new SchemaVersion(arr[0]); uri = uri.replaceAll("^v\\d+", ""); } } - SchemaVersions schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); if (version == null) { version = schemaVersions.getDefaultVersion(); } Mockito.when(uriInfo.getPath()).thenReturn(uri); - DBConnectionType type = DBConnectionType.REALTIME; - - traversalHttpEntry.setHttpEntryProperties(version, type); + if(notification != null){ + traversalHttpEntry.setHttpEntryProperties(version, notification, notificationDepth); + } else { + traversalHttpEntry.setHttpEntryProperties(version); + } Loader loader = traversalHttpEntry.getLoader(); dbEngine = traversalHttpEntry.getDbEngine(); @@ -162,24 +310,18 @@ public class HttpTestUtil extends RESTAPI { Introspector obj; HttpMethod httpMethod; - if (uri.contains("/relationship-list/relationship")) { - obj = loader.unmarshal("relationship", payload, - org.onap.aai.restcore.MediaType.getEnum("application/json")); - httpMethod = HttpMethod.PUT_EDGE; - } else { - obj = loader.unmarshal(objType, payload, org.onap.aai.restcore.MediaType.getEnum("application/json")); - httpMethod = HttpMethod.PUT; - this.validateIntrospector(obj, loader, uriObject, httpMethod); - } + obj = loader.unmarshal(objType, payload, org.onap.aai.restcore.MediaType.getEnum("application/json")); + httpMethod = HttpMethod.MERGE_PATCH; + this.validateIntrospector(obj, loader, uriObject, httpMethod); DBRequest dbRequest = new DBRequest.Builder(httpMethod, uriObject, uriQuery, obj, httpHeaders, uriInfo, - "JUNIT-TRANSACTION").rawRequestContent(payload).build(); + "JUNIT-TRANSACTION").rawRequestContent(payload).build(); List<DBRequest> dbRequestList = new ArrayList<>(); dbRequestList.add(dbRequest); Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = - traversalHttpEntry.process(dbRequestList, "JUNIT"); + traversalHttpEntry.process(dbRequestList, "JUNIT"); response = responsesTuple.getValue1().get(0).getValue1(); } catch (AAIException e) { @@ -194,7 +336,7 @@ public class HttpTestUtil extends RESTAPI { if (response != null) { if ((response.getStatus() / 100) == 2) { logger.info("Successfully completed the PUT request with status {} and committing it to DB", - response.getStatus()); + response.getStatus()); } else { logFailure(HttpMethod.PUT, response); } @@ -211,7 +353,11 @@ public class HttpTestUtil extends RESTAPI { return response; } - public Response doGet(String uri, String depth) { + public Response doGet(String uri, String depth){ + return doGet(uri, depth, null); + } + + public Response doGet(String uri, String depth, String format) { this.init(); Response response = null; @@ -230,20 +376,22 @@ public class HttpTestUtil extends RESTAPI { SchemaVersion version = null; - if (arr != null && arr.length > 1) { + if (arr.length > 1) { if (arr[0].matches("^v\\d+")) { version = new SchemaVersion(arr[0]); uri = uri.replaceAll("^v\\d+", ""); } } - SchemaVersions schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); if (version == null) { version = schemaVersions.getDefaultVersion(); } - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(version, type); + if(notification != null){ + traversalHttpEntry.setHttpEntryProperties(version, notification, notificationDepth); + } else { + traversalHttpEntry.setHttpEntryProperties(version); + } Loader loader = traversalHttpEntry.getLoader(); dbEngine = traversalHttpEntry.getDbEngine(); @@ -253,6 +401,10 @@ public class HttpTestUtil extends RESTAPI { queryParameters.add("depth", depth); } + if(format != null){ + queryParameters.add("format", format); + } + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, queryParameters); Mockito.when(uriInfo.getPath()).thenReturn(uri); @@ -309,7 +461,7 @@ public class HttpTestUtil extends RESTAPI { return this.doGet(uri, "all"); } - public Response doDelete(String uri, String resourceVersion) throws UnsupportedEncodingException, AAIException { + public Response doDelete(Map<String, Pair<String, String>> deletes){ this.init(); Response response = null; @@ -318,77 +470,81 @@ public class HttpTestUtil extends RESTAPI { try { - uri = uri.replaceAll("/aai/", ""); - logger.info("Starting the delete request for the uri {} with resource version {}", uri, resourceVersion); + List<DBRequest> dbRequestList = new ArrayList<>(); + for (Map.Entry<String, Pair<String, String>> delete : deletes.entrySet()) { + String uri = delete.getKey(); + String resourceVersion = delete.getValue().getValue0(); + String content = delete.getValue().getValue1(); + uri = uri.replaceAll("/aai/", ""); + logger.info("Starting the delete request for the uri {} with resource version {}", uri, resourceVersion); - String[] arr = uri.split("/"); + String[] arr = uri.split("/"); - SchemaVersion version = null; + SchemaVersion version = null; - if (arr != null && arr.length > 1) { - if (arr[0].matches("^v\\d+")) { - version = new SchemaVersion(arr[0]); - if (!uri.contains("relationship-list/relationship")) { + if (arr.length > 1) { + if (arr[0].matches("^v\\d+")) { + version = new SchemaVersion(arr[0]); uri = uri.replaceAll("^v\\d+", ""); } } - } - SchemaVersions schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); - if (version == null) { - version = schemaVersions.getDefaultVersion(); - } + if (version == null) { + version = schemaVersions.getDefaultVersion(); + } - Mockito.when(uriInfo.getPath()).thenReturn(uri); - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(version, type); + Mockito.when(uriInfo.getPath()).thenReturn(uri); + if (notification != null) { + traversalHttpEntry.setHttpEntryProperties(version, notification, notificationDepth); + } else { + traversalHttpEntry.setHttpEntryProperties(version); + } + Loader loader = traversalHttpEntry.getLoader(); + dbEngine = traversalHttpEntry.getDbEngine(); - traversalHttpEntry.setHttpEntryProperties(version, type); - Loader loader = traversalHttpEntry.getLoader(); - dbEngine = traversalHttpEntry.getDbEngine(); + URI uriObject = UriBuilder.fromPath(uri).build(); + URIToObject uriToObject = new URIToObject(loader, uriObject); - URI uriObject = UriBuilder.fromPath(uri).build(); - URIToObject uriToObject = new URIToObject(loader, uriObject); + String objType = uriToObject.getEntityName(); + queryParameters.add("resource-version", resourceVersion); + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, queryParameters); - String objType = uriToObject.getEntityName(); - queryParameters.add("resource-version", resourceVersion); - QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, queryParameters); + logger.info("Unmarshalling the payload to this {}", objType); - logger.info("Unmarshalling the payload to this {}", objType); + Introspector obj; - Introspector obj; - HttpMethod httpMethod; - if (uri.contains("/relationship-list/relationship")) { - obj = loader.introspectorFromName("relationship"); - httpMethod = HttpMethod.DELETE_EDGE; - } else { - obj = loader.introspectorFromName(objType); - httpMethod = HttpMethod.DELETE; - } + HttpMethod httpMethod; - DBRequest dbRequest = new DBRequest.Builder(httpMethod, uriObject, uriQuery, obj, httpHeaders, uriInfo, - "JUNIT-TRANSACTION").build(); + if (uri.contains("/relationship-list/relationship")) { + httpMethod = HttpMethod.DELETE_EDGE; + obj = loader.unmarshal("relationship", content, org.onap.aai.restcore.MediaType.getEnum("application/json")); + } else { + obj = loader.introspectorFromName(objType); + httpMethod = HttpMethod.DELETE; + } - List<DBRequest> dbRequestList = new ArrayList<>(); - dbRequestList.add(dbRequest); + DBRequest dbRequest = new DBRequest.Builder(httpMethod, uriObject, uriQuery, obj, httpHeaders, uriInfo, "JUNIT-TRANSACTION").build(); + + dbRequestList.add(dbRequest); + } Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = - traversalHttpEntry.process(dbRequestList, "JUNIT"); + traversalHttpEntry.process(dbRequestList, "JUNIT"); response = responsesTuple.getValue1().get(0).getValue1(); } catch (AAIException e) { - response = this.consumerExceptionResponseGenerator(httpHeaders, uriInfo, HttpMethod.PUT, e); + response = this.consumerExceptionResponseGenerator(httpHeaders, uriInfo, HttpMethod.DELETE, e); success = false; } catch (Exception e) { AAIException ex = new AAIException("AAI_4000", e); - response = this.consumerExceptionResponseGenerator(httpHeaders, uriInfo, HttpMethod.PUT, ex); + response = this.consumerExceptionResponseGenerator(httpHeaders, uriInfo, HttpMethod.DELETE, ex); success = false; } finally { if (success) { if (response != null) { if ((response.getStatus() / 100) == 2) { logger.info("Successfully completed the DELETE request with status {} and committing it to DB", - response.getStatus()); + response.getStatus()); } else { logFailure(HttpMethod.DELETE, response); } @@ -403,6 +559,15 @@ public class HttpTestUtil extends RESTAPI { return response; } + public Response doDelete(String uri, String resourceVersion) { + return this.doDelete(uri, resourceVersion, null); + } + public Response doDelete(String uri, String resourceVersion, String content) { + Map<String, Pair<String, String>> deletes = new HashMap<>(); + deletes.put(uri, new Pair<>(resourceVersion, content)); + return this.doDelete(deletes); + } + public static void logFailure(HttpMethod httpMethod, Response response) { logger.info("Unable to complete the {} request with status {} and rolling back", httpMethod.toString(), response.getStatus()); diff --git a/aai-core/src/test/java/org/onap/aai/auth/AAIAuthCoreTest.java b/aai-core/src/test/java/org/onap/aai/auth/AAIAuthCoreTest.java deleted file mode 100644 index d6075c1f..00000000 --- a/aai-core/src/test/java/org/onap/aai/auth/AAIAuthCoreTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.auth; - -import static org.junit.Assert.*; - -import org.junit.Before; -import org.junit.Test; -import org.onap.aai.AAISetup; -import org.onap.aai.auth.exceptions.AAIUnrecognizedFunctionException; - -public class AAIAuthCoreTest extends AAISetup { - - private AAIAuthCore authCore; - - @Before - public void setup() { - authCore = new AAIAuthCore("/aai"); - } - - @Test - public void getAuthPolicyFunctionNameTest() { - - String uri = "/aai/v3/search/edge-tag-query"; - assertEquals("Get aai function name from " + uri, "search", authCore.getAuthPolicyFunctName(uri)); - - uri = "/aai/v10/search/edge-tag-query"; - assertEquals("Get aai function name from " + uri, "search", authCore.getAuthPolicyFunctName(uri)); - - uri = "/aai/search/model"; - assertEquals("Get aai function name from " + uri, "search", authCore.getAuthPolicyFunctName(uri)); - - uri = "/aai/v9/cloud-infrastructure/cloud-regions/cloud-region/somecloudregion/some-cloud-owner"; - assertEquals("Get aai function name from " + uri, "cloud-infrastructure", authCore.getAuthPolicyFunctName(uri)); - - uri = "/aai/v8/network/pnfs/pnf/ff4ca01orc/p-interfaces"; - assertEquals("Get aai function name from " + uri, "network", authCore.getAuthPolicyFunctName(uri)); - - uri = "/aai/util/echo"; - assertEquals("Get aai function name from " + uri, "util", authCore.getAuthPolicyFunctName(uri)); - - uri = "/aai/tools"; - assertEquals("Get aai function name from " + uri, "tools", authCore.getAuthPolicyFunctName(uri)); - - uri = "/aai/v12/bulk/single-transaction"; - assertEquals("Get aai function name from " + uri, "bulk", authCore.getAuthPolicyFunctName(uri)); - - } - - @Test - public void validUsernameAuthTest() throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("testUser".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", "")); - } - - @Test - public void validUsernameInvalidHttpMethodAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("testUser".toLowerCase(), "/aai/v0/testFunction/someUri", "POST", "")); - } - - @Test(expected = AAIUnrecognizedFunctionException.class) - public void validUsernameInvalidFunctionInURIAuthTest() throws AAIUnrecognizedFunctionException { - authCore.authorize("testUser".toLowerCase(), "/aai/v0/badFunction/someUri", "PUT", ""); - } - - @Test - public void invalidUsernameAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("invlaidTestUser".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", "")); - } - - @Test - public void validUsernameIsTheExactWildcardIdAuthTest() throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("testWildcardId".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", "")); - } - - @Test - public void validUsernameContainsTheWildcardIdAuthTest() throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("cn=blah, testWildcardId, O=".toLowerCase(), "/aai/v0/testFunction/someUri", - "PUT", "", "aafWildCardIssuer")); - } - - @Test - public void validUsernameContainsTheWildcardIdInvalidIssuerAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("cn=blah, testWildcardId, O=".toLowerCase(), "/aai/v0/testFunction/someUri", - "PUT", "", "invalidIssuer")); - } - - @Test - public void invalidUsernameContainsRegularUsernameAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse( - authCore.authorize("cn=blah, testUser, O=".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", "")); - } - - @Test - public void haProxyUsernameAuthTest() throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/util/echo", "GET", "")); - } - - @Test - public void haProxyUsernameInvalidFunctionAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", "")); - } - - @Test - public void validUsernameViaHaProxyAuthTest() throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", - "testUser".toLowerCase())); - } - - @Test - public void validUsernameInvalidHttpMethodViaHaProxyAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/v0/testFunction/someUri", "POST", - "testUser".toLowerCase())); - } - - @Test(expected = AAIUnrecognizedFunctionException.class) - public void validUsernameInvalidFunctionInURIViaHaProxyAuthTest() throws AAIUnrecognizedFunctionException { - authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/v0/badFunction/someUri", "PUT", - "testUser".toLowerCase()); - } - - @Test - public void invalidUsernameViaHaProxyAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", - "invlaidTestUser".toLowerCase())); - } - - @Test - public void validUsernameIsTheExactWildcardIdViaHaProxyAuthTest() throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", - "testWildcardId".toLowerCase())); - } - - @Test - public void validUsernameContainsTheWildcardIdViaHaProxyAuthTest() throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", - "cn=blah, testWildcardId, O=".toLowerCase(), "aafWildCardIssuer")); - } - - @Test - public void invalidUsernameContainsRegularUsernameViaHaProxyAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", - "cn=blah, testUser, O=".toLowerCase())); - } - - @Test - public void haProxyUsernameTwiceAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("ha-proxy-user".toLowerCase(), "/aai/v0/testFunction/someUri", "PUT", - "ha-proxy-user".toLowerCase())); - } - - @Test - public void haProxyWildcardIdAuthTest() throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), "/aai/util/echo", "GET", "", - "aafWildCardIssuer")); - } - - @Test - public void haProxyWildcardIdInvalidFunctionAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), - "/aai/v0/testFunction/someUri", "PUT", "")); - } - - @Test - public void validUsernameViaHaProxyWildcardIdAuthTest() throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), "/aai/v0/testFunction/someUri", - "PUT", "testUser".toLowerCase(), "aafWildCardIssuer")); - } - - @Test - public void validUsernameInvalidHttpMethodViaHaProxyWildcardIdAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), - "/aai/v0/testFunction/someUri", "POST", "testUser".toLowerCase())); - } - - @Test(expected = AAIUnrecognizedFunctionException.class) - public void validUsernameInvalidFunctionInURIViaHaProxyWildcardIdAuthTest() - throws AAIUnrecognizedFunctionException { - authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), "/aai/v0/badFunction/someUri", "PUT", - "testUser".toLowerCase()); - } - - @Test - public void invalidUsernameViaHaProxyWildcardIdAuthTest() throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), - "/aai/v0/testFunction/someUri", "PUT", "invlaidTestUser".toLowerCase())); - } - - @Test - public void validUsernameIsTheExactWildcardIdViaHaProxyWildcardIdAuthTest() - throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), "/aai/v0/testFunction/someUri", - "PUT", "testWildcardId".toLowerCase(), "aafWildCardIssuer")); - } - - @Test - public void validUsernameContainsTheWildcardIdViaHaProxyWildcardIdAuthTest() - throws AAIUnrecognizedFunctionException { - assertTrue(authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), "/aai/v0/testFunction/someUri", - "PUT", "cn=blah, testWildcardId, O=".toLowerCase(), "aafWildCardIssuer")); - } - - @Test - public void validUsernameContainsTheWildcardIdViaHaProxyWildcardIdInvalidIssuerAuthTest() - throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), - "/aai/v0/testFunction/someUri", "PUT", "cn=blah, testWildcardId, O=".toLowerCase(), "invalidIssuer")); - } - - @Test - public void invalidUsernameContainsRegularUsernameViaHaProxyWildcardIdAuthTest() - throws AAIUnrecognizedFunctionException { - assertFalse(authCore.authorize("cn=blah, ha-proxy-wildcard-id, O=".toLowerCase(), - "/aai/v0/testFunction/someUri", "PUT", "cn=blah, testUser, O=".toLowerCase())); - } - -} diff --git a/aai-core/src/test/java/org/onap/aai/auth/AAIUserTest.java b/aai-core/src/test/java/org/onap/aai/auth/AAIUserTest.java deleted file mode 100644 index cf5eafbd..00000000 --- a/aai-core/src/test/java/org/onap/aai/auth/AAIUserTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.auth; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.onap.aai.AAISetup; - -public class AAIUserTest extends AAISetup { - - @Test - public void testIsAuth() { - AAIUser usr = new AAIUser("testUser"); - usr.addRole("testRole"); - usr.setUserAccess("auth", "GET"); - usr.setUserAccess("auth", "PUT"); - usr.setUserAccess("authentication", "PUT", "GET", "POST"); - - assertEquals(true, usr.hasAccess("auth", "GET")); - assertEquals(true, usr.hasAccess("auth", "PUT")); - assertEquals(true, usr.hasAccess("authentication", "POST")); - } - - @Test - public void testIsNotAuth() { - AAIUser usr = new AAIUser("testUser"); - usr.addRole("testRole"); - - assertEquals(false, usr.hasAccess("auth", "GET")); - - usr.setUserAccess("auth", "GET"); - assertEquals(false, usr.hasAccess("auth", "PUT")); - } - -} diff --git a/aai-core/src/test/java/org/onap/aai/dbmap/AAIGraphTest.java b/aai-core/src/test/java/org/onap/aai/dbmap/AAIGraphTest.java index 48d2583d..f2c7b27c 100644 --- a/aai-core/src/test/java/org/onap/aai/dbmap/AAIGraphTest.java +++ b/aai-core/src/test/java/org/onap/aai/dbmap/AAIGraphTest.java @@ -20,17 +20,6 @@ package org.onap.aai.dbmap; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.Matchers.matchesPattern; -import static org.junit.Assert.*; - -import java.io.FileNotFoundException; -import java.util.HashSet; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - import org.janusgraph.core.JanusGraph; import org.janusgraph.core.JanusGraphFactory; import org.janusgraph.core.schema.JanusGraphIndex; @@ -48,6 +37,17 @@ import org.onap.aai.schema.enums.PropertyMetadata; import org.onap.aai.setup.SchemaVersions; import org.onap.aai.util.AAIConstants; +import java.io.FileNotFoundException; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.matchesPattern; +import static org.junit.Assert.*; + public class AAIGraphTest extends AAISetup { @Before public void setup() { @@ -67,21 +67,9 @@ public class AAIGraphTest extends AAISetup { graphMgt.rollback(); } - @Test - public void getCachedInstanceConnectionName() throws Exception { - - JanusGraphManagement graphMgt = AAIGraph.getInstance().getGraph(DBConnectionType.CACHED).openManagement(); - String connectionInstanceName = - graphMgt.getOpenInstances().stream().filter(c -> c.contains("current")).findFirst().get(); - assertThat(connectionInstanceName, containsString(SERVICE_NAME)); - assertThat(connectionInstanceName, containsString("cached")); - assertThat(connectionInstanceName, - matchesPattern("^\\d+_[\\w\\-\\d]+_" + SERVICE_NAME + "_cached_\\d+\\(current\\)$")); - graphMgt.rollback(); - } @Test - public void JanusGraphOpenNameTest() throws Exception { + public void janusGraphOpenNameTest() throws Exception { JanusGraph graph = JanusGraphFactory.open(new AAIGraphConfig.Builder(AAIConstants.REALTIME_DB_CONFIG) .forService(SERVICE_NAME).withGraphType("graphType").buildConfiguration()); JanusGraphManagement graphMgt = graph.openManagement(); @@ -94,7 +82,7 @@ public class AAIGraphTest extends AAISetup { } @Test(expected = FileNotFoundException.class) - public void JanusGraphOpenNameWithInvalidFilePathTest() throws Exception { + public void janusGraphOpenNameWithInvalidFilePathTest() throws Exception { JanusGraph graph = JanusGraphFactory.open(new AAIGraphConfig.Builder("invalid").forService(SERVICE_NAME) .withGraphType("graphType").buildConfiguration()); JanusGraphManagement graphMgt = graph.openManagement(); diff --git a/aai-core/src/test/java/org/onap/aai/introspection/JSONStrategyTest.java b/aai-core/src/test/java/org/onap/aai/introspection/JSONStrategyTest.java index 8b44b312..b684e3fa 100644 --- a/aai-core/src/test/java/org/onap/aai/introspection/JSONStrategyTest.java +++ b/aai-core/src/test/java/org/onap/aai/introspection/JSONStrategyTest.java @@ -20,16 +20,18 @@ package org.onap.aai.introspection; -import java.util.HashSet; -import java.util.Set; - import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.onap.aai.AAISetup; +import java.util.HashSet; +import java.util.Set; + +@Ignore("Not a used/flushed out feature") public class JSONStrategyTest extends AAISetup { private JSONStrategy jsonStrategy; private JSONStrategy jsonStrategyContainer; diff --git a/aai-core/src/test/java/org/onap/aai/introspection/MoxyEngineTest.java b/aai-core/src/test/java/org/onap/aai/introspection/MoxyEngineTest.java index 0e6a9aab..fe128353 100644 --- a/aai-core/src/test/java/org/onap/aai/introspection/MoxyEngineTest.java +++ b/aai-core/src/test/java/org/onap/aai/introspection/MoxyEngineTest.java @@ -20,6 +20,7 @@ package org.onap.aai.introspection; +import org.junit.Assert; import org.junit.Test; import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.springframework.test.annotation.DirtiesContext; @@ -43,4 +44,23 @@ public class MoxyEngineTest extends IntrospectorTestSpec { } + @Test + public void testDslStartNodeProps() throws AAIUnknownObjectException { + Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion()); + Introspector obj = loader.introspectorFromName("pserver"); + Assert.assertFalse(obj.getDslStartNodeProperties().contains("in-maint")); + Assert.assertTrue(obj.getDslStartNodeProperties().contains("pserver-name2")); + + } + + @Test + public void testDslStartNodePropsDefault() throws AAIUnknownObjectException { + /* + * Use indexedprops when there is no dslStartNodeProps + */ + Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion()); + Introspector obj = loader.introspectorFromName("vserver"); + Assert.assertTrue(obj.getDslStartNodeProperties().contains("in-maint")); + } + } diff --git a/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataCopyTest.java b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataCopyTest.java index 79597355..7dadb14a 100644 --- a/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataCopyTest.java +++ b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataCopyTest.java @@ -20,19 +20,6 @@ package org.onap.aai.introspection.sideeffect; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.Collection; - import org.apache.commons.io.IOUtils; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.structure.Graph; @@ -48,10 +35,11 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.AAISetup; import org.onap.aai.db.props.AAIProperties; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.edges.enums.EdgeProperty; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.introspection.*; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; import org.onap.aai.introspection.sideeffect.exceptions.AAIMissingRequiredPropertyException; import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.serialization.db.DBSerializer; @@ -59,13 +47,24 @@ import org.onap.aai.serialization.engines.JanusGraphDBEngine; import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + @RunWith(value = Parameterized.class) public class DataCopyTest extends AAISetup { private static JanusGraph graph; private final static ModelType introspectorFactoryType = ModelType.MOXY; - private final static DBConnectionType type = DBConnectionType.REALTIME; private static Loader loader; private static TransactionalGraphEngine dbEngine; @Mock @@ -77,7 +76,7 @@ public class DataCopyTest extends AAISetup { @Rule public ExpectedException thrown = ExpectedException.none(); - @Parameterized.Parameter(value = 0) + @Parameterized.Parameter public QueryStyle queryStyle; @Parameterized.Parameters(name = "QueryStyle.{0}") @@ -86,27 +85,40 @@ public class DataCopyTest extends AAISetup { } @BeforeClass - public static void setup() throws NoSuchFieldException, SecurityException, Exception { + public static void setup() { graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); System.setProperty("AJSC_HOME", "."); System.setProperty("BUNDLECONFIG_DIR", "src/test/resources/bundleconfig-local"); graph.traversal() - .addV("aai-node-type", "model", "model-invariant-id", "key1", AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key1") - .as("v1") - .addV("aai-node-type", "model-ver", "model-ver", "myValue", "model-version-id", "key2", "model-version", - "testValue", AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key1/model-vers/model-ver/key2") - .addOutE("org.onap.relationships.inventory.BelongsTo", "v1", EdgeProperty.CONTAINS.toString(), true) - .addV("aai-node-type", "model", "model-invariant-id", "key3", AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key3") - .as("v2") - .addV("aai-node-type", "model-ver", "model-ver", "myValue", "model-version-id", "key4", - AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key3/model-vers/model-ver/key4") - .addOutE("org.onap.relationships.inventory.BelongsTo", "v2", EdgeProperty.CONTAINS.toString(), true) - .next(); + .addV("model") + .property("aai-node-type", "model") + .property("model-invariant-id", "key1") + .property(AAIProperties.AAI_URI,"/service-design-and-creation/models/model/key1") + .as("v1") + .addV("model-ver") + .property("aai-node-type", "model-ver") + .property("model-ver", "myValue") + .property("model-version-id", "key2") + .property("model-version", "testValue") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key1/model-vers/model-ver/key2") + .as("v2") + .addE("org.onap.relationships.inventory.BelongsTo").to("v1").from("v2") + .property(EdgeProperty.CONTAINS.toString(), true) + .addV("model") + .property("aai-node-type", "model") + .property("model-invariant-id", "key3") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key3") + .as("v3") + .addV() + .property("aai-node-type", "model-ver") + .property("model-ver", "myValue") + .property("model-version-id", "key4") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key3/model-vers/model-ver/key4") + .as("v4") + .addE("org.onap.relationships.inventory.BelongsTo").to("v3").from("v4") + .property(EdgeProperty.CONTAINS.toString(), true) + .next(); graph.tx().commit(); } @@ -120,13 +132,12 @@ public class DataCopyTest extends AAISetup { public void initMock() { loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, schemaVersions.getDefaultVersion()); MockitoAnnotations.initMocks(this); - dbEngine = new JanusGraphDBEngine(queryStyle, type, loader); + dbEngine = new JanusGraphDBEngine(queryStyle, loader); } @Test - public void runPopulatePersonaModelVer() throws URISyntaxException, AAIException, UnsupportedEncodingException, - IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, - InstantiationException, NoSuchMethodException, MalformedURLException { + public void runPopulatePersonaModelVer() throws AAIException, UnsupportedEncodingException, + IllegalArgumentException, SecurityException { final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); final Introspector obj = loader.introspectorFromName("generic-vnf"); @@ -154,13 +165,10 @@ public class DataCopyTest extends AAISetup { } @Test - public void verifyNestedSideEffect() - throws URISyntaxException, AAIException, IllegalAccessException, IllegalArgumentException, - InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, IOException { + public void verifyNestedSideEffect() throws AAIException, IllegalArgumentException, SecurityException, IOException { final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); final Introspector obj = loader.unmarshal("customer", this.getJsonString("nested-case.json")); - // System.out.println(obj.marshal(true)); TransactionalGraphEngine spy = spy(dbEngine); TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin()); Graph g = graph.newTransaction(); @@ -251,15 +259,15 @@ public class DataCopyTest extends AAISetup { runner.execute(obj, self); - assertEquals("no model-version-id", true, obj.getValue("model-version-id") == null); - assertEquals("no model-invariant-id", true, obj.getValue("model-invariant-id") == null); + assertNull("no model-version-id", obj.getValue("model-version-id")); + assertNull("no model-invariant-id", obj.getValue("model-invariant-id")); } private String getJsonString(String filename) throws IOException { FileInputStream is = new FileInputStream("src/test/resources/oxm/sideeffect/" + filename); - String s = IOUtils.toString(is, "UTF-8"); + String s = IOUtils.toString(is, StandardCharsets.UTF_8); IOUtils.closeQuietly(is); return s; diff --git a/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataLinkTest.java b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataLinkTest.java index cec342ea..62c366cb 100644 --- a/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataLinkTest.java +++ b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataLinkTest.java @@ -20,54 +20,51 @@ package org.onap.aai.introspection.sideeffect; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import java.io.UnsupportedEncodingException; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.Direction; -import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.janusgraph.core.Cardinality; import org.janusgraph.core.JanusGraph; import org.janusgraph.core.JanusGraphFactory; +import org.janusgraph.core.schema.JanusGraphManagement; import org.junit.*; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.onap.aai.AAISetup; import org.onap.aai.DataLinkSetup; import org.onap.aai.db.props.AAIProperties; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.edges.enums.EdgeProperty; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.introspection.*; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.serialization.db.DBSerializer; import org.onap.aai.serialization.engines.JanusGraphDBEngine; import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.*; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + @RunWith(value = Parameterized.class) public class DataLinkTest extends DataLinkSetup { private static JanusGraph graph; private final static ModelType introspectorFactoryType = ModelType.MOXY; - private final static DBConnectionType type = DBConnectionType.REALTIME; private static Loader loader; private static TransactionalGraphEngine dbEngine; @Mock @@ -79,7 +76,7 @@ public class DataLinkTest extends DataLinkSetup { @Rule public ExpectedException thrown = ExpectedException.none(); - @Parameterized.Parameter(value = 0) + @Parameterized.Parameter public QueryStyle queryStyle; @Parameterized.Parameters(name = "QueryStyle.{0}") @@ -88,50 +85,133 @@ public class DataLinkTest extends DataLinkSetup { } @BeforeClass - public static void setup() throws NoSuchFieldException, SecurityException, Exception { + public static void setup() { graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + JanusGraphManagement graphMgt = graph.openManagement(); + graphMgt.makePropertyKey(AAIProperties.CREATED_TS).dataType(Long.class).cardinality(Cardinality.SINGLE) + .make(); + graphMgt.makePropertyKey(AAIProperties.LAST_MOD_TS).dataType(Long.class).cardinality(Cardinality.SINGLE) + .make(); + graphMgt.commit(); graph.traversal() - .addV("aai-node-type", "vpn-binding", "vpn-id", "addKey", AAIProperties.AAI_URI, - "/network/vpn-bindings/vpn-binding/addKey") - .as("v1") - .addV("aai-node-type", "vpn-binding", "vpn-id", "modifyKey", AAIProperties.AAI_URI, - "/network/vpn-bindings/vpn-binding/modifyKey") - .as("v2") - .addV("aai-node-type", "route-target", "global-route-target", "modifyTargetKey", "route-target-role", - "modifyRoleKey", "linked", true, AAIProperties.AAI_URI, - "/network/vpn-bindings/vpn-binding/modifyKey/route-targets/route-target/modifyTargetKey/modifyRoleKey") - .addOutE("org.onap.relationships.inventory.BelongsTo", "v2", EdgeProperty.CONTAINS.toString(), true) - .addV("aai-node-type", "vpn-binding", "vpn-id", "deleteKey", AAIProperties.AAI_URI, - "/network/vpn-bindings/vpn-binding/deleteKey") - .as("v3") - .addV("aai-node-type", "route-target", "global-route-target", "deleteTargetKey", "route-target-role", - "deleteRoleKey", "linked", true, AAIProperties.AAI_URI, - "/network/vpn-bindings/vpn-binding/deleteKey/route-targets/route-target/deleteTargetKey/deleteRoleKey") - .addOutE("org.onap.relationships.inventory.BelongsTo", "v3", EdgeProperty.CONTAINS.toString(), true) - .addV("aai-node-type", "vpn-binding", "vpn-id", "getKey", AAIProperties.AAI_URI, - "/network/vpn-bindings/vpn-binding/getKey") - .as("v4") - .addV("aai-node-type", "route-target", "global-route-target", "getTargetKey", "route-target-role", - "getRoleKey", "linked", true, AAIProperties.AAI_URI, - "/network/vpn-bindings/vpn-binding/getKey/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink") - .addOutE("org.onap.relationships.inventory.BelongsTo", "v4", EdgeProperty.CONTAINS.toString(), true) - .addV("aai-node-type", "vpn-binding", "vpn-id", "getKeyNoLink", AAIProperties.AAI_URI, - "/network/vpn-bindings/vpn-binding/getKeyNoLink") - .as("v5") - .addV("aai-node-type", "route-target", "global-route-target", "getTargetKeyNoLink", "route-target-role", - "getRoleKeyNoLink", AAIProperties.AAI_URI, - "/network/vpn-bindings/vpn-binding/getKeyNoLink/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink") - .addOutE("org.onap.relationships.inventory.BelongsTo", "v5", EdgeProperty.CONTAINS.toString(), true) + .addV() + .property("aai-node-type", "vpn-binding") + .property("vpn-id", "addKey") + .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/addKey") + .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()) + .property(AAIProperties.CREATED_TS, 123) + .property(AAIProperties.SOURCE_OF_TRUTH, "sot") + .property(AAIProperties.RESOURCE_VERSION, "123") + .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot") + .property(AAIProperties.LAST_MOD_TS, 333) + .as("v1") + .addV() + .property("aai-node-type", "vpn-binding") + .property("vpn-id", "modifyKey") + .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/modifyKey") + .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()) + .property(AAIProperties.CREATED_TS, 123) + .property(AAIProperties.SOURCE_OF_TRUTH, "sot") + .property(AAIProperties.RESOURCE_VERSION, "123") + .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot") + .property(AAIProperties.LAST_MOD_TS, 333) + .as("v2") + .addV() + .property("aai-node-type", "route-target") + .property("global-route-target", "modifyTargetKey") + .property("route-target-role", "modifyRoleKey") + .property("linked", true) + .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/modifyKey/route-targets/route-target/modifyTargetKey/modifyRoleKey") + .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()) + .property(AAIProperties.CREATED_TS, 123) + .property(AAIProperties.SOURCE_OF_TRUTH, "sot") + .property(AAIProperties.RESOURCE_VERSION, "123") + .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot") + .property(AAIProperties.LAST_MOD_TS, 333) + .as("v3") + .addE("org.onap.relationships.inventory.BelongsTo").to("v2").from("v3") + .property(EdgeProperty.CONTAINS.toString(), true) + .addV() + .property("aai-node-type", "vpn-binding") + .property("vpn-id", "deleteKey") + .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/deleteKey") + .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()) + .property(AAIProperties.CREATED_TS, 123) + .property(AAIProperties.SOURCE_OF_TRUTH, "sot") + .property(AAIProperties.RESOURCE_VERSION, "123") + .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot") + .property(AAIProperties.LAST_MOD_TS, 333) + .as("v4") + .addV() + .property("aai-node-type", "route-target") + .property("global-route-target", "deleteTargetKey") + .property("route-target-role", "deleteRoleKey") + .property("linked", true) + .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/deleteKey/route-targets/route-target/deleteTargetKey/deleteRoleKey") + .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()) + .property(AAIProperties.CREATED_TS, 123) + .property(AAIProperties.SOURCE_OF_TRUTH, "sot") + .property(AAIProperties.RESOURCE_VERSION, "123") + .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot") + .property(AAIProperties.LAST_MOD_TS, 333) + .as("v5") + .addE("org.onap.relationships.inventory.BelongsTo").to("v4").from("v5") + .property(EdgeProperty.CONTAINS.toString(), true) + .addV() + .property("aai-node-type", "vpn-binding") + .property("vpn-id", "getKey") + .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKey") + .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()) + .property(AAIProperties.CREATED_TS, 123) + .property(AAIProperties.SOURCE_OF_TRUTH, "sot") + .property(AAIProperties.RESOURCE_VERSION, "123") + .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot") + .property(AAIProperties.LAST_MOD_TS, 333) + .as("v6") + .addV() + .property("aai-node-type", "route-target") + .property("global-route-target", "getTargetKey") + .property("route-target-role", "getRoleKey") + .property("linked", true) + .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKey/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink") + .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()) + .property(AAIProperties.CREATED_TS, 123) + .property(AAIProperties.SOURCE_OF_TRUTH, "sot") + .property(AAIProperties.RESOURCE_VERSION, "123") + .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot") + .property(AAIProperties.LAST_MOD_TS, 333) + .as("v7") + .addE("org.onap.relationships.inventory.BelongsTo").to("v6").from("v7") + .property(EdgeProperty.CONTAINS.toString(), true) + .addV() + .property("aai-node-type", "vpn-binding") + .property("vpn-id", "getKeyNoLink") + .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKeyNoLink") + .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()) + .property(AAIProperties.CREATED_TS, 123) + .property(AAIProperties.SOURCE_OF_TRUTH, "sot") + .property(AAIProperties.RESOURCE_VERSION, "123") + .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot") + .property(AAIProperties.LAST_MOD_TS, 333) + .as("v8") + .addV() + .property("aai-node-type", "route-target") + .property("global-route-target", "getTargetKeyNoLink") + .property("route-target-role", "getRoleKeyNoLink") + .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKeyNoLink/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink") + .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()) + .property(AAIProperties.CREATED_TS, 123) + .property(AAIProperties.SOURCE_OF_TRUTH, "sot") + .property(AAIProperties.RESOURCE_VERSION, "123") + .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot") + .property(AAIProperties.LAST_MOD_TS, 333) + .as("v9") + .addE("org.onap.relationships.inventory.BelongsTo").to("v8").from("v9") + .property(EdgeProperty.CONTAINS.toString(), true) .next(); graph.tx().commit(); - /* - * Commented for SysOut issues - */ - // graph.traversal().V().has("aai-uri","/network/vpn-bindings/vpn-binding/deleteKey").properties().forEachRemaining(p->System.out.println(p.key() - // +" : " + p.value())); - } @AfterClass @@ -144,13 +224,12 @@ public class DataLinkTest extends DataLinkSetup { public void initMock() { loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, schemaVersions.getDefaultVersion()); MockitoAnnotations.initMocks(this); - dbEngine = new JanusGraphDBEngine(queryStyle, type, loader); + dbEngine = new JanusGraphDBEngine(queryStyle, loader); } @Test - public void verifyCreationOfVertex() throws URISyntaxException, AAIException, UnsupportedEncodingException, - IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, - InstantiationException, NoSuchMethodException, MalformedURLException { + public void verifyCreationOfVertex() throws AAIException, UnsupportedEncodingException, + IllegalArgumentException, SecurityException { final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion()); final Introspector obj = loader.introspectorFromName("vpn-binding"); @@ -161,25 +240,6 @@ public class DataLinkTest extends DataLinkSetup { TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin()); Graph g = graph.newTransaction(); GraphTraversalSource traversal = g.traversal(); - // Graph g = graph.newTransaction(); - // GraphTraversalSource traversal = g; - // System.out.println("Begin method inventory:"); - Iterator<Vertex> vertexItr = traversal.V(); - while (vertexItr != null && vertexItr.hasNext()) { - Vertex v = vertexItr.next(); - // System.out.println("\nnodeType="+v.<String>property("aai-node-type")); - for (String key : v.keys()) { - // System.out.println("label="+v.label()+";key= "+key+";value= "+v.value(key)+";id= "+v.id()); - } - Direction d = null; - Iterator<Edge> edgeItr = v.edges(Direction.BOTH); - while (edgeItr != null && edgeItr.hasNext()) { - Edge e = edgeItr.next(); - // System.out.println("outV="+e.outVertex().property(AAIProperties.NODE_TYPE)+"/"+e.outVertex().id()+";inV= - // "+e.inVertex().property(AAIProperties.NODE_TYPE)+"/"+e.inVertex().id()); - } - } - // System.out.println("End method inventory:"); when(spy.asAdmin()).thenReturn(adminSpy); when(adminSpy.getTraversalSource()).thenReturn(traversal); when(spy.tx()).thenReturn(g); @@ -192,16 +252,14 @@ public class DataLinkTest extends DataLinkSetup { runner.execute(obj, self); - assertEquals("route-target vertex found", true, traversal.V().has(AAIProperties.NODE_TYPE, "route-target") - .has("global-route-target", "key1").has("route-target-role", "key2").has("linked", true).hasNext()); + assertTrue("route-target vertex found", traversal.V().has(AAIProperties.NODE_TYPE, "route-target").has("global-route-target", "key1").has("route-target-role", "key2").has("linked", true).hasNext()); g.tx().rollback(); } @Test - public void verifyModificationOfVertex() throws URISyntaxException, AAIException, UnsupportedEncodingException, - IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, - InstantiationException, NoSuchMethodException, MalformedURLException { + public void verifyModificationOfVertex() throws AAIException, UnsupportedEncodingException, + IllegalArgumentException, SecurityException { final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion()); final Introspector obj = loader.introspectorFromName("vpn-binding"); @@ -210,30 +268,11 @@ public class DataLinkTest extends DataLinkSetup { obj.setValue("route-target-role", "modifyRoleKey2"); TransactionalGraphEngine spy = spy(dbEngine); TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin()); - // Graph g = graph.newTransaction(); - // GraphTraversalSource traversal = g; Graph g = graph.newTransaction(); GraphTraversalSource traversal = g.traversal(); - Iterator<Vertex> vertexItr = traversal.V(); - while (vertexItr != null && vertexItr.hasNext()) { - Vertex v = vertexItr.next(); - // System.out.println("\nnodeType="+v.<String>property("aai-node-type")); - for (String key : v.keys()) { - // System.out.println("label="+v.label()+";key= "+key+";value= "+v.value(key)+"/"+v.id()); - } - Direction d = null; - Iterator<Edge> edgeItr = v.edges(Direction.BOTH); - while (edgeItr != null && edgeItr.hasNext()) { - Edge e = edgeItr.next(); - // System.out.println("outV="+e.outVertex().property(AAIProperties.NODE_TYPE)+"/"+e.outVertex().id()+";inV= - // "+e.inVertex().property(AAIProperties.NODE_TYPE)+"/"+e.inVertex().id()); - } - } - // System.out.println("End method inventory:"); when(spy.asAdmin()).thenReturn(adminSpy); when(adminSpy.getTraversalSource()).thenReturn(traversal); - // when(spy.tx()).thenReturn(graph); when(spy.tx()).thenReturn(g); when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop); when(prop.orElse(null)).thenReturn(obj.getURI()); @@ -241,44 +280,8 @@ public class DataLinkTest extends DataLinkSetup { new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST"); SideEffectRunner runner = new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build(); - // System.out.println("Traversal Source: "+traversal.toString()); - vertexItr = traversal.V(); - // System.out.println("Begin method inventory:"); - while (vertexItr != null && vertexItr.hasNext()) { - Vertex v = vertexItr.next(); - // System.out.println("\nnodeType="+v.<String>property("aai-node-type")); - for (String key : v.keys()) { - // System.out.println("label="+v.label()+";key= "+key+";value= "+v.value(key)+"/"+v.id()); - } - Iterator<Edge> edgeItr = v.edges(Direction.BOTH); - while (edgeItr != null && edgeItr.hasNext()) { - Edge e = edgeItr.next(); - // System.out.println("outV="+e.outVertex().property(AAIProperties.NODE_TYPE)+"/"+e.outVertex().id()+";inV= - // "+e.inVertex().property(AAIProperties.NODE_TYPE)+"/"+e.inVertex().id()); - } - } - // System.out.println("End method inventory:"); - try { - runner.execute(obj, self); - } catch (Exception e) { - - } - // runner.execute(obj, self); - // System.out.println("=================\n"); - vertexItr = traversal.V(); - while (vertexItr != null && vertexItr.hasNext()) { - Vertex v = vertexItr.next(); - // System.out.println("\nnodeType="+v.<String>property("aai-node-type")); - for (String key : v.keys()) { - // System.out.println("label="+v.label()+";key= "+key+";value= "+v.value(key)+"/"+v.id()); - } - Iterator<Edge> edgeItr = v.edges(Direction.BOTH); - while (edgeItr != null && edgeItr.hasNext()) { - Edge e = edgeItr.next(); - // System.out.println("outV="+e.outVertex().property(AAIProperties.NODE_TYPE)+"/"+e.outVertex().id()+";inV= - // "+e.inVertex().property(AAIProperties.NODE_TYPE)+"/"+e.inVertex().id()); - } - } + runner.execute(obj, self); + assertThat("new route-target vertex found with/or without link", traversal.V().has(AAIProperties.NODE_TYPE, "route-target") .has("global-route-target", "modifyTargetKey2").has("route-target-role", "modifyRoleKey2") @@ -301,9 +304,7 @@ public class DataLinkTest extends DataLinkSetup { } @Test - public void verifyDeleteOfVertex() throws URISyntaxException, AAIException, UnsupportedEncodingException, - IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, - InstantiationException, NoSuchMethodException, MalformedURLException { + public void verifyDeleteOfVertex() throws Exception { final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion()); final Introspector obj = loader.introspectorFromName("vpn-binding"); @@ -325,18 +326,14 @@ public class DataLinkTest extends DataLinkSetup { runner.execute(obj, self); - assertEquals("route-target vertex not found", false, - traversal.V().has(AAIProperties.NODE_TYPE, "route-target").has("global-route-target", "deleteTargetKey") - .has("route-target-role", "deleteRoleKey").has("linked", true).hasNext()); + assertFalse("route-target vertex not found", traversal.V().has(AAIProperties.NODE_TYPE, "route-target").has("global-route-target", "deleteTargetKey").has("route-target-role", "deleteRoleKey").has("linked", true).hasNext()); g.tx().rollback(); } @Test - public void verifyPropertyPopulation() throws URISyntaxException, AAIException, UnsupportedEncodingException, - IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, - InstantiationException, NoSuchMethodException, MalformedURLException { + public void verifyPropertyPopulation() throws Exception { final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion()); final Introspector obj = loader.introspectorFromName("vpn-binding"); @@ -357,17 +354,14 @@ public class DataLinkTest extends DataLinkSetup { runner.execute(obj, self); - assertEquals("both properties have been populated in target object", true, - obj.getValue("global-route-target").equals("getTargetKey") - && obj.getValue("route-target-role").equals("getRoleKey")); + assertTrue("both properties have been populated in target object", obj.getValue("global-route-target").equals("getTargetKey") && obj.getValue("route-target-role").equals("getRoleKey")); g.tx().rollback(); } @Test - public void verifyPropertyPopulationWithV10OnlyPut() throws URISyntaxException, AAIException, - UnsupportedEncodingException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, - SecurityException, InstantiationException, NoSuchMethodException, MalformedURLException { + public void verifyPropertyPopulationWithV10OnlyPut() throws AAIException, + UnsupportedEncodingException, IllegalArgumentException, SecurityException { final Introspector obj = loader.introspectorFromName("vpn-binding"); obj.setValue("vpn-id", "getKeyNoLink"); final Introspector routeTargets = loader.introspectorFromName("route-targets"); diff --git a/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/PrivateEdgeTest.java b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/PrivateEdgeTest.java index 1bae4065..6a7bfd33 100644 --- a/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/PrivateEdgeTest.java +++ b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/PrivateEdgeTest.java @@ -20,19 +20,6 @@ package org.onap.aai.introspection.sideeffect; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.StringContains.containsString; -import static org.junit.Assert.*; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Graph; @@ -46,29 +33,42 @@ import org.junit.runners.Parameterized; import org.mockito.MockitoAnnotations; import org.onap.aai.AAISetup; import org.onap.aai.db.props.AAIProperties; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.edges.enums.EdgeProperty; -import org.onap.aai.introspection.*; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; import org.onap.aai.serialization.db.DBSerializer; import org.onap.aai.serialization.engines.JanusGraphDBEngine; import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.springframework.test.annotation.DirtiesContext; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + @RunWith(value = Parameterized.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class PrivateEdgeTest extends AAISetup { private static JanusGraph graph; private final static ModelType introspectorFactoryType = ModelType.MOXY; - private final static DBConnectionType type = DBConnectionType.REALTIME; - private Loader loader; private static TransactionalGraphEngine dbEngine; @Rule public ExpectedException thrown = ExpectedException.none(); - @Parameterized.Parameter(value = 0) + @Parameterized.Parameter public QueryStyle queryStyle; @Parameterized.Parameters(name = "QueryStyle.{0}") @@ -77,7 +77,7 @@ public class PrivateEdgeTest extends AAISetup { } @BeforeClass - public static void setup() throws Exception { + public static void setup() { graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); @@ -85,28 +85,48 @@ public class PrivateEdgeTest extends AAISetup { System.setProperty("BUNDLECONFIG_DIR", "src/test/resources/bundleconfig-local"); graph.traversal() - .addV("aai-node-type", "model", "model-invariant-id", "key1", AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key1") - .as("v1") - .addV("aai-node-type", "model-ver", "model-ver", "myValue", "model-version-id", "key2", "model-version", - "testValue", AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key1/model-vers/model-ver/key2") - .addOutE("org.onap.relationships.inventory.BelongsTo", "v1", EdgeProperty.CONTAINS.toString(), true) - .addV("aai-node-type", "model", "model-invariant-id", "key100", AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key100") - .as("v5") - .addV("aai-node-type", "model-ver", "model-ver", "myValue", "model-version-id", "key200", - "model-version", "testValue", AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key100/model-vers/model-ver/key200") - .addOutE("org.onap.relationships.inventory.BelongsTo", "v5", EdgeProperty.CONTAINS.toString(), true) - .addV("aai-node-type", "model", "model-invariant-id", "key3", AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key3") - .as("v2") - .addV("aai-node-type", "model-ver", "model-ver", "myValue", "model-version-id", "key4", - AAIProperties.AAI_URI, - "/service-design-and-creation/models/model/key3/model-vers/model-ver/key4") - .addOutE("org.onap.relationships.inventory.BelongsTo", "v2", EdgeProperty.CONTAINS.toString(), true) - .next(); + .addV() + .property("aai-node-type", "model") + .property("model-invariant-id", "key1") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key1") + .as("v1") + .addV() + .property("aai-node-type", "model-ver") + .property("model-ver", "myValue") + .property("model-version-id", "key2") + .property("model-version", "testValue") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key1/model-vers/model-ver/key2") + .as("v2") + .addE("org.onap.relationships.inventory.BelongsTo").to("v1").from("v2") + .property(EdgeProperty.CONTAINS.toString(), true) + .addV() + .property("aai-node-type", "model") + .property("model-invariant-id", "key100") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key100") + .as("v3") + .addV() + .property("aai-node-type", "model-ver") + .property("model-ver", "myValue") + .property("model-version-id", "key200") + .property("model-version", "testValue") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key100/model-vers/model-ver/key200") + .as("v4") + .addE("org.onap.relationships.inventory.BelongsTo").to("v3").from("v4") + .property(EdgeProperty.CONTAINS.toString(), true) + .addV() + .property("aai-node-type", "model") + .property("model-invariant-id", "key3") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key3") + .as("v5") + .addV() + .property("aai-node-type", "model-ver") + .property("model-ver", "myValue") + .property("model-version-id", "key4") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key3/model-vers/model-ver/key4") + .as("v6") + .addE("org.onap.relationships.inventory.BelongsTo").to("v5").from("v6") + .property(EdgeProperty.CONTAINS.toString(), true) + .next(); graph.tx().commit(); } @@ -118,9 +138,9 @@ public class PrivateEdgeTest extends AAISetup { @Before public void initMock() { - loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, schemaVersions.getDefaultVersion()); + Loader loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, schemaVersions.getDefaultVersion()); MockitoAnnotations.initMocks(this); - dbEngine = new JanusGraphDBEngine(queryStyle, type, loader); + dbEngine = new JanusGraphDBEngine(queryStyle, loader); } @Test @@ -137,8 +157,12 @@ public class PrivateEdgeTest extends AAISetup { when(spy.asAdmin()).thenReturn(adminSpy); when(adminSpy.getTraversalSource()).thenReturn(traversal); - Vertex selfV = traversal.addV("aai-node-type", "generic-vnf", "vnf-id", "myId", "aai-uri", obj.getURI(), - "model-invariant-id", "key1").next(); + Vertex selfV = traversal.addV("generic-vnf") + .property("aai-node-type", "generic-vnf") + .property("vnf-id", "myId") + .property("aai-uri", obj.getURI()) + .property("model-invariant-id", "key1") + .next(); thrown.expectMessage(containsString("Cannot complete privateEdge uri")); DBSerializer serializer = @@ -150,7 +174,7 @@ public class PrivateEdgeTest extends AAISetup { assertNull(edgeList); assertThat(edgeList, is(not(empty()))); - assertThat(edgeList.size(), is(1)); + assertEquals(1, edgeList.size()); g.tx().rollback(); } diff --git a/aai-core/src/test/java/org/onap/aai/logging/CustomLogPatternLayoutTest.java b/aai-core/src/test/java/org/onap/aai/logging/CustomLogPatternLayoutTest.java index dce34b53..250cdda8 100644 --- a/aai-core/src/test/java/org/onap/aai/logging/CustomLogPatternLayoutTest.java +++ b/aai-core/src/test/java/org/onap/aai/logging/CustomLogPatternLayoutTest.java @@ -20,13 +20,11 @@ package org.onap.aai.logging; +import org.junit.Test; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import org.junit.Test; -import org.onap.aai.logging.CNName; -import org.onap.aai.logging.CustomLogPatternLayout; - public class CustomLogPatternLayoutTest { /** diff --git a/aai-core/src/test/java/org/onap/aai/logging/DME2RestFlagTest.java b/aai-core/src/test/java/org/onap/aai/logging/DME2RestFlagTest.java index bc7f9499..72b1150e 100644 --- a/aai-core/src/test/java/org/onap/aai/logging/DME2RestFlagTest.java +++ b/aai-core/src/test/java/org/onap/aai/logging/DME2RestFlagTest.java @@ -20,12 +20,12 @@ package org.onap.aai.logging; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - import ch.qos.logback.access.spi.IAccessEvent; +import org.junit.Before; +import org.junit.Test; -import org.junit.*; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; public class DME2RestFlagTest { diff --git a/aai-core/src/test/java/org/onap/aai/logging/EcompErrorCategoryTest.java b/aai-core/src/test/java/org/onap/aai/logging/EcompErrorCategoryTest.java deleted file mode 100644 index 65c78121..00000000 --- a/aai-core/src/test/java/org/onap/aai/logging/EcompErrorCategoryTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; - -import org.junit.*; - -public class EcompErrorCategoryTest { - - EcompErrorCategory _ecompErrorCategory; - ILoggingEvent mockEvent; - - @Before - public void setUp() throws Exception { - - mockEvent = mock(ILoggingEvent.class); - _ecompErrorCategory = spy(EcompErrorCategory.class); - - } - - @Test - public void warn() { - String defaultCategory = "WARN"; - assertEquals(_ecompErrorCategory.convert(mockEvent), defaultCategory); - } - -} diff --git a/aai-core/src/test/java/org/onap/aai/logging/EcompResponseCodeTest.java b/aai-core/src/test/java/org/onap/aai/logging/EcompResponseCodeTest.java deleted file mode 100644 index 8319f9a3..00000000 --- a/aai-core/src/test/java/org/onap/aai/logging/EcompResponseCodeTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; - -import org.junit.*; - -public class EcompResponseCodeTest { - - EcompResponseCode _ecompResponseCode; - ILoggingEvent mockEvent; - - @Before - public void setUp() throws Exception { - - mockEvent = mock(ILoggingEvent.class); - _ecompResponseCode = spy(EcompResponseCode.class); - - } - - @Test - public void getDefaultCode() { - assertEquals(_ecompResponseCode.convert(mockEvent), LoggingContext.UNKNOWN_ERROR); - } - -} diff --git a/aai-core/src/test/java/org/onap/aai/logging/EcompResponseDescriptionTest.java b/aai-core/src/test/java/org/onap/aai/logging/EcompResponseDescriptionTest.java deleted file mode 100644 index 4bcf79cd..00000000 --- a/aai-core/src/test/java/org/onap/aai/logging/EcompResponseDescriptionTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; - -import org.junit.*; -import org.onap.aai.logging.LoggingContext.LoggingField; - -public class EcompResponseDescriptionTest { - - EcompResponseDescription _ecompResponseDescription; - ILoggingEvent mockEvent; - - @Before - public void setUp() throws Exception { - - mockEvent = mock(ILoggingEvent.class); - _ecompResponseDescription = spy(EcompResponseDescription.class); - - } - - @Test - public void getDefaultDesc() { - assertEquals(_ecompResponseDescription.convert(mockEvent), _ecompResponseDescription.DEFAULT_DESCRIPTION); - } - -} diff --git a/aai-core/src/test/java/org/onap/aai/logging/EelfClassOfCallerTest.java b/aai-core/src/test/java/org/onap/aai/logging/EelfClassOfCallerTest.java deleted file mode 100644 index bc77ae81..00000000 --- a/aai-core/src/test/java/org/onap/aai/logging/EelfClassOfCallerTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -import org.junit.*; - -public class EelfClassOfCallerTest { - - EelfClassOfCaller _eelfClassOfCaller; - ILoggingEvent mockEvent; - StackTraceElement[] cdafive = new StackTraceElement[5]; - StackTraceElement[] cdaone = new StackTraceElement[1]; - StackTraceElement[] cdazero = new StackTraceElement[0]; - - @Before - public void setUp() throws Exception { - - mockEvent = mock(ILoggingEvent.class); - _eelfClassOfCaller = spy(EelfClassOfCaller.class); - - } - - @Test - public void getFullyQualifiedNameCDALENFiveTest() { - StackTraceElement temp = new StackTraceElement("classname_five", "methodname", "filename", 4); - cdafive[2] = temp; - when(mockEvent.getCallerData()).thenReturn(cdafive); - assertEquals(_eelfClassOfCaller.getFullyQualifiedName(mockEvent), "classname_five"); - - } - - @Test - public void getFullyQualifiedNameCDALenOneTest() { - StackTraceElement temp = new StackTraceElement("classname_one", "methodname", "filename", 4); - cdaone[0] = temp; - when(mockEvent.getCallerData()).thenReturn(cdaone); - assertEquals(_eelfClassOfCaller.getFullyQualifiedName(mockEvent), "classname_one"); - - } - - @Test - public void getFullyQualifiedNameCDALenZeroTest() { - when(mockEvent.getCallerData()).thenReturn(cdazero); - assertEquals(_eelfClassOfCaller.getFullyQualifiedName(mockEvent), "?"); - - } - -} diff --git a/aai-core/src/test/java/org/onap/aai/logging/ErrorObjectTest.java b/aai-core/src/test/java/org/onap/aai/logging/ErrorObjectTest.java index 1c55bc11..cbe5bc6b 100644 --- a/aai-core/src/test/java/org/onap/aai/logging/ErrorObjectTest.java +++ b/aai-core/src/test/java/org/onap/aai/logging/ErrorObjectTest.java @@ -20,12 +20,12 @@ package org.onap.aai.logging; -import static org.junit.Assert.*; +import org.junit.Test; -import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; -import org.junit.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; public class ErrorObjectTest { @@ -98,7 +98,7 @@ public class ErrorObjectTest { } @Test - public void SetErrorCodeTest() { + public void setErrorCodeTest() { newErrorObject.setErrorCode("newErrorCode"); assertEquals(newErrorObject.getErrorCode(), "newErrorCode"); } diff --git a/aai-core/src/test/java/org/onap/aai/logging/LoggingContextTest.java b/aai-core/src/test/java/org/onap/aai/logging/LoggingContextTest.java deleted file mode 100644 index 74347730..00000000 --- a/aai-core/src/test/java/org/onap/aai/logging/LoggingContextTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.logging; - -import static org.junit.Assert.*; - -import java.util.*; - -import org.junit.Test; - -public class LoggingContextTest { - - private static final int MAX_STORED_CONTEXTS = 100; - - @Test - public void testStopWatch() { - try { - LoggingContext.stopWatchStop(); - throw new AssertionError( - "No exception thrown when LoggingContext.stopWatchStop() called without a prior LoggingContext.stopWatchStart()"); - } catch (StopWatchNotStartedException e) { - // Expected - } - - LoggingContext.stopWatchStart(); - - assertTrue(LoggingContext.stopWatchStop() >= 0); - - try { - LoggingContext.stopWatchStop(); - throw new AssertionError("No exception thrown when LoggingContext.stopWatchStop() twice in succession"); - } catch (StopWatchNotStartedException e) { - // Expected - } - } - - @Test - public void testRequestId() { // AKA Transaction ID - final String sUuid = "57d51eaa-edc6-4f50-a69d-f2d4d2445120"; - - LoggingContext.requestId(sUuid); - - assertEquals(LoggingContext.requestId(), UUID.fromString(sUuid)); - - final UUID uuid = UUID.randomUUID(); - - LoggingContext.requestId(uuid); - - assertEquals(LoggingContext.requestId(), uuid); - - LoggingContext.requestId("foo"); // Illegal - this will result in a new, randomly - // generated UUID as per the logging spec - - assertNotNull(LoggingContext.requestId()); // Make sure ANY UUID was assigned - assertNotEquals(LoggingContext.requestId(), uuid); // Make sure it actually changed from the last - // known valid UUID - } - - @Test - public void testClear() { - LoggingContext.init(); - LoggingContext.clear(); - - assertEquals(Collections.emptyMap(), LoggingContext.getCopy()); - } - - @Test - public void testSaveRestore() { - - final Deque<Map<String, String>> contexts = new LinkedList<Map<String, String>>(); - - LoggingContext.init(); - - for (int i = 0; i < MAX_STORED_CONTEXTS; i++) { - LoggingContext.customField1(String.valueOf(i)); - - assertEquals(LoggingContext.customField1(), String.valueOf(i)); - - LoggingContext.save(); - - contexts.push(LoggingContext.getCopy()); - } - - while (contexts.peek() != null) { - LoggingContext.restore(); - - assertEquals(LoggingContext.getCopy(), contexts.pop()); - } - } -} diff --git a/aai-core/src/test/java/org/onap/aai/parsers/query/LegacyQueryTest.java b/aai-core/src/test/java/org/onap/aai/parsers/query/LegacyQueryTest.java index 4cdc55fa..e8ccdddd 100644 --- a/aai-core/src/test/java/org/onap/aai/parsers/query/LegacyQueryTest.java +++ b/aai-core/src/test/java/org/onap/aai/parsers/query/LegacyQueryTest.java @@ -20,15 +20,6 @@ package org.onap.aai.parsers.query; -import static org.junit.Assert.assertEquals; - -import java.io.UnsupportedEncodingException; -import java.net.URI; - -import javax.ws.rs.core.UriBuilder; -import javax.xml.bind.JAXBException; - -import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; import org.junit.Ignore; import org.junit.Test; import org.onap.aai.AAISetup; @@ -39,12 +30,18 @@ import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.setup.SchemaVersion; +import javax.ws.rs.core.UriBuilder; +import javax.xml.bind.JAXBException; +import java.io.UnsupportedEncodingException; +import java.net.URI; + +import static org.junit.Assert.assertEquals; + @Ignore public class LegacyQueryTest extends AAISetup { private TransactionalGraphEngine dbEngine; private SchemaVersion version; - private DynamicJAXBContext context = nodeIngestor.getContextForVersion(version); public void setup() { version = new SchemaVersion("v10"); @@ -60,7 +57,7 @@ public class LegacyQueryTest extends AAISetup { * @throws AAIException the AAI exception */ @Test - public void parentQuery() throws JAXBException, UnsupportedEncodingException, AAIException { + public void parentQuery() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/pservers/pserver/key1").build(); @@ -82,7 +79,7 @@ public class LegacyQueryTest extends AAISetup { * @throws AAIException the AAI exception */ @Test - public void childQuery() throws JAXBException, UnsupportedEncodingException, AAIException { + public void childQuery() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/pservers/pserver/key1/lag-interfaces/lag-interface/key2") .build(); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri); @@ -104,7 +101,7 @@ public class LegacyQueryTest extends AAISetup { * @throws AAIException the AAI exception */ @Test - public void namingExceptions() throws JAXBException, UnsupportedEncodingException, AAIException { + public void namingExceptions() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655") .build(); diff --git a/aai-core/src/test/java/org/onap/aai/prevalidation/ValidationServiceTest.java b/aai-core/src/test/java/org/onap/aai/prevalidation/ValidationServiceTest.java new file mode 100644 index 00000000..883c8b61 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/prevalidation/ValidationServiceTest.java @@ -0,0 +1,199 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2018-19 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.prevalidation; + +import com.google.gson.Gson; +import org.apache.http.conn.ConnectTimeoutException; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.aai.PayloadUtil; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.restclient.RestClient; +import org.springframework.boot.test.rule.OutputCapture; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; + +import java.io.IOException; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.util.List; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; + +public class ValidationServiceTest { + + private RestClient restClient; + + private ValidationService validationService; + + @Rule + public OutputCapture capture = new OutputCapture(); + + private Gson gson; + + @Before + public void setUp() throws Exception { + gson = new Gson(); + restClient = Mockito.mock(RestClient.class); + validationService = Mockito.spy(new ValidationService(restClient, "JUNIT", "generic-vnf", null)); + } + + @Test + public void testNodeTypeThatIsAllowedAndItShouldReturnTrue() { + boolean shouldValidate = validationService.shouldValidate("generic-vnf"); + assertThat(shouldValidate, is(true)); + } + + @Test + public void testNodeTypeThatIsNotAllowedAndItShouldReturnFalse() { + boolean shouldValidate = validationService.shouldValidate("customer"); + assertThat(shouldValidate, is(false)); + } + + @Test + public void testPreValidateWithSuccessRequestAndServiceIsDownAndShouldErrorWithConnectionRefused() throws IOException, AAIException { + + String pserverRequest = PayloadUtil.getResourcePayload("prevalidation/success-request-with-no-violations.json"); + + Mockito + .when( + restClient.execute( + eq(ValidationService.VALIDATION_ENDPOINT), + eq(HttpMethod.POST), + any(), + eq(pserverRequest) + ) + ).thenThrow(new RuntimeException(new ConnectException("Connection refused"))); + + validationService.preValidate(pserverRequest); + + assertThat(capture.toString(), containsString("Connection refused to the validation microservice due to service unreachable")); + } + + @Test + public void testPreValidateWithSuccessRequestAndServiceIsUnreachableAndShouldErrorWithConnectionTimeout() throws IOException, AAIException { + + String pserverRequest = PayloadUtil.getResourcePayload("prevalidation/success-request-with-no-violations.json"); + + Mockito + .when( + restClient.execute( + eq(ValidationService.VALIDATION_ENDPOINT), + eq(HttpMethod.POST), + any(), + eq(pserverRequest) + ) + ).thenThrow(new RuntimeException(new ConnectTimeoutException("Connection timed out"))); + + validationService.preValidate(pserverRequest); + + assertThat(capture.toString(), containsString("Connection timeout to the validation microservice as this could indicate the server is unable to reach port")); + } + + @Test + public void testPreValidateWithSuccessRequestAndRespondSuccessfullyWithinAllowedTime() throws IOException, AAIException { + + String pserverRequest = PayloadUtil.getResourcePayload("prevalidation/success-request-with-no-violations.json"); + String validationResponse = PayloadUtil.getResourcePayload("prevalidation/success-response-with-empty-violations.json"); + + ResponseEntity responseEntity = Mockito.mock(ResponseEntity.class, Mockito.RETURNS_DEEP_STUBS); + + Mockito + .when( + restClient.execute( + eq(ValidationService.VALIDATION_ENDPOINT), + eq(HttpMethod.POST), + any(), + eq(pserverRequest) + ) + ).thenReturn(responseEntity); + + Mockito.when(responseEntity.getStatusCodeValue()).thenReturn(200); + Mockito.when(responseEntity.getBody()).thenReturn(validationResponse); + + Mockito.doReturn(true).when(validationService).isSuccess(responseEntity); + + List<String> errorMessages = validationService.preValidate(pserverRequest); + assertNotNull("Expected the error messages to be not null", errorMessages); + assertThat(errorMessages.size(), is(0)); + } + + @Test + public void testPreValidateWithSuccessRequestAndServiceIsAvailableAndRequestIsTakingTooLongAndClientShouldTimeout() throws IOException, AAIException { + + String pserverRequest = PayloadUtil.getResourcePayload("prevalidation/success-request-with-no-violations.json"); + + Mockito + .when( + restClient.execute( + eq(ValidationService.VALIDATION_ENDPOINT), + eq(HttpMethod.POST), + any(), + eq(pserverRequest) + ) + ).thenThrow(new RuntimeException(new SocketTimeoutException("Request timed out due to taking longer than client expected"))); + + validationService.preValidate(pserverRequest); + + assertThat(capture.toString(), containsString("Request to validation service took longer than the currently set timeout")); + } + + @Test + public void testExtractViolationsReturnsSuccessfullyAListWhenViolationsAreFound() throws IOException { + + String genericVnfRequest = PayloadUtil.getResourcePayload("prevalidation/failed-response-with-violations.json"); + + Validation validation = gson.fromJson(genericVnfRequest, Validation.class); + List<String> errorMessages = validationService.extractViolations(validation); + assertNotNull("Expected the error messages to be not null", errorMessages); + assertThat(errorMessages.size(), is(1)); + assertThat(errorMessages.get(0), is("Invalid nf values, check nf-type, nf-role, nf-function, and nf-naming-code")); + } + + @Test + public void testErrorMessagesAreEmptyListWhenViolationsReturnEmptyList() throws IOException { + + String genericVnfRequest = PayloadUtil.getResourcePayload("prevalidation/success-response-with-empty-violations.json"); + + Validation validation = gson.fromJson(genericVnfRequest, Validation.class); + List<String> errorMessages = validationService.extractViolations(validation); + assertNotNull("Expected the error messages to be not null", errorMessages); + assertThat(errorMessages.size(), is(0)); + } + + @Test + public void testErrorMessagesAreEmptyListWhenViolationsIsNotFoundInJson() throws IOException { + + String genericVnfRequest = PayloadUtil.getResourcePayload("prevalidation/success-response-with-exclude-violations.json"); + + Validation validation = gson.fromJson(genericVnfRequest, Validation.class); + List<String> errorMessages = validationService.extractViolations(validation); + assertNotNull("Expected the error messages to be not null", errorMessages); + assertThat(errorMessages.size(), is(0)); + } +} diff --git a/aai-core/src/test/java/org/onap/aai/query/builder/QueryBuilderTestAbstraction.java b/aai-core/src/test/java/org/onap/aai/query/builder/QueryBuilderTestAbstraction.java index 0e527493..44d812c3 100644 --- a/aai-core/src/test/java/org/onap/aai/query/builder/QueryBuilderTestAbstraction.java +++ b/aai-core/src/test/java/org/onap/aai/query/builder/QueryBuilderTestAbstraction.java @@ -20,16 +20,8 @@ package org.onap.aai.query.builder; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.collection.IsIterableContainingInOrder.contains; -import static org.junit.Assert.*; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - import org.apache.tinkerpop.gremlin.process.traversal.Path; +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.process.traversal.step.util.BulkSet; import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; @@ -42,6 +34,7 @@ import org.junit.runner.RunWith; import org.onap.aai.config.ConfigConfiguration; import org.onap.aai.config.IntrospectionConfig; import org.onap.aai.config.SpringContextAware; +import org.onap.aai.config.XmlFormatTransformerConfiguration; import org.onap.aai.db.props.AAIProperties; import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.edges.enums.EdgeType; @@ -53,7 +46,6 @@ import org.onap.aai.nodes.NodeIngestor; import org.onap.aai.serialization.db.EdgeSerializer; import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException; import org.onap.aai.serialization.queryformats.QueryFormatTestHelper; -import org.onap.aai.setup.SchemaLocationsBean; import org.onap.aai.setup.SchemaVersions; import org.onap.aai.util.AAIConstants; import org.springframework.beans.factory.annotation.Autowired; @@ -62,10 +54,19 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; +import static org.junit.Assert.*; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( classes = {ConfigConfiguration.class, QueryTestsConfigTranslator.class, NodeIngestor.class, EdgeIngestor.class, - EdgeSerializer.class, SpringContextAware.class, IntrospectionConfig.class}) + EdgeSerializer.class, SpringContextAware.class, IntrospectionConfig.class, XmlFormatTransformerConfiguration.class}) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) @TestPropertySource( properties = {"schema.translator.list = config", "schema.nodes.location=src/test/resources/onap/oxm", @@ -95,14 +96,14 @@ public abstract class QueryBuilderTestAbstraction { } @Before - public void configure() throws Exception { + public void configure() { loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); g = graph.traversal(); } @After - public void deConfigure() throws Exception { + public void deConfigure() { g.tx().rollback(); } @@ -111,11 +112,30 @@ public abstract class QueryBuilderTestAbstraction { graph.close(); } + /* + * This helper method was designed to minimize the changes needed due to the eventual + * removal of the addV(String...) method. + * Correct vertex creation addV(label).property(k,v).property(k,v)... + */ + @Deprecated + protected GraphTraversal<Vertex, Vertex> addVHelper(GraphTraversalSource gts, String label, Object... props) { + for (int i = 0; i < props.length; i++) { + if (props[i].equals(AAIProperties.NODE_TYPE)) { + label = props[i+1].toString(); + } + } + GraphTraversal<Vertex, Vertex> v = gts.addV(label); + for (int i = 0; i < props.length; i+=2) { + v.property(props[i], props[i+1]); + } + return v; + } + @Test public void createEdgeGVnfToVnfcTraversal() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "myvnf").next(); - Vertex vnfc = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "myvnf").next(); + Vertex vnfc = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); testEdgeSer.addEdge(g, gvnf, vnfc, "uses"); QueryBuilder<Vertex> tQ = getNewVertexTraversalWithTestEdgeRules(gvnf); @@ -128,8 +148,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void createEdgeLinterfaceToLogicalLinkTraversal() throws AAIException { - Vertex lInterface = g.addV("aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); - Vertex logicalLink = g.addV("aai-node-type", "logical-link", "link-name", "logical-link-a").next(); + Vertex lInterface = this.addVHelper(g, "vertex", "aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); + Vertex logicalLink = this.addVHelper(g, "vertex", "aai-node-type", "logical-link", "link-name", "logical-link-a").next(); testEdgeSer.addEdge(g, lInterface, logicalLink, "sourceLInterface"); QueryBuilder<Vertex> tQ = getNewVertexTraversalWithTestEdgeRules(lInterface); @@ -144,8 +164,8 @@ public abstract class QueryBuilderTestAbstraction { @SuppressWarnings("rawtypes") @Test public void createEdgeLinterfaceToLogicalLinkTraversal_tree() throws AAIException { - Vertex lInterface = g.addV("aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); - Vertex logicalLink = g.addV("aai-node-type", "logical-link", "link-name", "logical-link-a").next(); + Vertex lInterface = this.addVHelper(g, "vertex", "aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); + Vertex logicalLink = this.addVHelper(g, "vertex", "aai-node-type", "logical-link", "link-name", "logical-link-a").next(); testEdgeSer.addEdge(g, lInterface, logicalLink, "sourceLInterface"); QueryBuilder<Tree> tQ = getNewTreeTraversalWithTestEdgeRules(lInterface).createEdgeTraversal(EdgeType.COUSIN, @@ -163,9 +183,9 @@ public abstract class QueryBuilderTestAbstraction { @SuppressWarnings("rawtypes") @Test public void createEdgeLinterfaceToLogicalLinkTraversal_Path() throws AAIException { - Vertex pInterface = g.addV("aai-node-type", "p-interface", "interface-name", "p-interface-a").next(); - Vertex lInterface = g.addV("aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); - Vertex logicalLink = g.addV("aai-node-type", "logical-link", "link-name", "logical-link-a").next(); + Vertex pInterface = this.addVHelper(g, "vertex", "aai-node-type", "p-interface", "interface-name", "p-interface-a").next(); + Vertex lInterface = this.addVHelper(g, "vertex", "aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); + Vertex logicalLink = this.addVHelper(g, "vertex", "aai-node-type", "logical-link", "link-name", "logical-link-a").next(); testEdgeSer.addEdge(g, lInterface, logicalLink); testEdgeSer.addTreeEdge(g, pInterface, lInterface); @@ -183,8 +203,8 @@ public abstract class QueryBuilderTestAbstraction { @SuppressWarnings("rawtypes") @Test public void parentVertexTest() throws AAIException { - Vertex pInterface = g.addV("aai-node-type", "p-interface", "interface-name", "p-interface-a").next(); - Vertex lInterface = g.addV("aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); + Vertex pInterface = this.addVHelper(g, "vertex", "aai-node-type", "p-interface", "interface-name", "p-interface-a").next(); + Vertex lInterface = this.addVHelper(g, "vertex", "aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); testEdgeSer.addTreeEdge(g, pInterface, lInterface); @@ -197,8 +217,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void createEdgeLinterfaceToLogicalLinkIntrospectorTraversal() throws AAIException { - Vertex lInterface = g.addV("aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); - Vertex logicalLink = g.addV("aai-node-type", "logical-link", "link-name", "logical-link-a").next(); + Vertex lInterface = this.addVHelper(g, "vertex", "aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); + Vertex logicalLink = this.addVHelper(g, "vertex", "aai-node-type", "logical-link", "link-name", "logical-link-a").next(); testEdgeSer.addEdge(g, lInterface, logicalLink, "sourceLInterface"); QueryBuilder<Vertex> tQ = getNewVertexTraversalWithTestEdgeRules(lInterface); @@ -214,8 +234,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void createEdgeLinterfaceToLogicalLinkVertexToIntrospectorTraversal() throws AAIException { - Vertex lInterface = g.addV("aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); - Vertex logicalLink = g.addV("aai-node-type", "logical-link", "link-name", "logical-link-a").next(); + Vertex lInterface = this.addVHelper(g, "vertex", "aai-node-type", "l-interface", "interface-name", "l-interface-a").next(); + Vertex logicalLink = this.addVHelper(g, "vertex", "aai-node-type", "logical-link", "link-name", "logical-link-a").next(); testEdgeSer.addEdge(g, lInterface, logicalLink, "sourceLInterface"); QueryBuilder<Vertex> tQ = getNewVertexTraversalWithTestEdgeRules(lInterface); @@ -230,8 +250,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeToVertexTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex vnfc1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex vnfc1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); testEdgeSer.addEdge(g, gvnf, vnfc1); @@ -248,8 +268,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeToVertexTraversalSingleOutRuleTest() throws AAIException { - Vertex vce = g.addV("aai-node-type", "vce", "vnf-id", "vce").next(); - Vertex vnfc1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex vce = this.addVHelper(g, "vertex", "aai-node-type", "vce", "vnf-id", "vce").next(); + Vertex vnfc1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); testEdgeSer.addEdge(g, vce, vnfc1); @@ -272,8 +292,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeToVertexTraversalSingleInRuleTest() throws AAIException { - Vertex vce = g.addV("aai-node-type", "vce", "vnf-id", "vce").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex vce = this.addVHelper(g, "vertex", "aai-node-type", "vce", "vnf-id", "vce").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); testEdgeSer.addEdge(g, vce, pserver); @@ -290,9 +310,9 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeToVertexMultiRuleTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex vnfc1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); - Vertex vnfc2 = g.addV("aai-node-type", "vnfc", "vnfc-name", "b-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex vnfc1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex vnfc2 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "b-name").next(); testEdgeSer.addEdge(g, gvnf, vnfc1); testEdgeSer.addEdge(g, gvnf, vnfc2, "re-uses"); @@ -311,9 +331,9 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeToVertexMultiLabelTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); - Vertex vnfc1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex vnfc1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); testEdgeSer.addEdge(g, gvnf, vnfc1); testEdgeSer.addEdge(g, pserver, vnfc1); @@ -329,10 +349,10 @@ public abstract class QueryBuilderTestAbstraction { } @Test - public void limitTraversalTest() throws AAIException { + public void limitTraversalTest() { - g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); - g.addV("aai-node-type", "vnfc", "vnfc-name", "b-name").next(); + this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "b-name").next(); QueryBuilder<Vertex> tQ = new GremlinTraversal<>(loader, g); tQ.getVerticesByProperty("aai-node-type", "vnfc").limit(1); @@ -344,10 +364,10 @@ public abstract class QueryBuilderTestAbstraction { } @Test - public void getVertexesByPropertiesTraversalTest() throws AAIException { + public void getVertexesByPropertiesTraversalTest() { - g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); - g.addV("aai-node-type", "vnfc", "vnfc-name", "b-name").next(); + this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "b-name").next(); QueryBuilder<Vertex> tQ = new GremlinTraversal<>(loader, g); tQ.getVerticesByProperty("vnfc-name", Arrays.asList("a-name", "b-name")); @@ -359,25 +379,38 @@ public abstract class QueryBuilderTestAbstraction { } @Test - public void getVertexesByIndexedPropertyTraversalTest() throws AAIException { + public void getVerticesByCommaSeperatedValueTraversalTest() { - g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); - g.addV("aai-node-type", "vnfc", "vnfc-name", "b-name").next(); + this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "b-name").next(); QueryBuilder<Vertex> tQ = new GremlinTraversal<>(loader, g); - tQ.getVerticesByIndexedProperty("aai-node-type", "vnfc"); + tQ.getVerticesByCommaSeperatedValue("vnfc-name","a-name, b-name"); List<Vertex> list = tQ.toList(); assertEquals("Has 2 vertexes ", 2, list.size()); + } + + @Test + public void getVertexesByIndexedPropertyTraversalTest() { + + this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "b-name").next(); + QueryBuilder<Vertex> tQ = new GremlinTraversal<>(loader, g); + tQ.getVerticesByIndexedProperty("aai-node-type", "vnfc"); + + List<Vertex> list = tQ.toList(); + + assertEquals("Has 2 vertexes ", 2, list.size()); } @Test public void dedupTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); testEdgeSer.addEdge(g, gvnf, pserver); testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -395,8 +428,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void storeCapTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); testEdgeSer.addEdge(g, gvnf, pserver); testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -414,8 +447,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void storeCapUnfoldTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); testEdgeSer.addEdge(g, gvnf, pserver); testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -431,10 +464,10 @@ public abstract class QueryBuilderTestAbstraction { } @Test - public void nextAndHasNextTraversalTest() throws AAIException { + public void nextAndHasNextTraversalTest() { - Vertex v1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); - Vertex v2 = g.addV("aai-node-type", "vnfc", "vnfc-name", "b-name").next(); + Vertex v1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex v2 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "b-name").next(); QueryBuilder<Vertex> tQ = new GremlinTraversal<>(loader, g); tQ.getVerticesByProperty("aai-node-type", "vnfc"); @@ -453,8 +486,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeToVertexMultiRuleOutTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); testEdgeSer.addEdge(g, gvnf, pserver); testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -472,8 +505,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeToVertexMultiRuleInTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex complex = g.addV("aai-node-type", "complex", "physical-location-id", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex complex = this.addVHelper(g, "vertex", "aai-node-type", "complex", "physical-location-id", "a-name").next(); testEdgeSer.addEdge(g, gvnf, complex); testEdgeSer.addEdge(g, gvnf, complex, "complex-generic-vnf-B"); @@ -491,8 +524,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeTraversalSingleInRuleTest() throws AAIException { - Vertex vce = g.addV("aai-node-type", "vce", "vnf-id", "vce").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex vce = this.addVHelper(g, "vertex", "aai-node-type", "vce", "vnf-id", "vce").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); Edge e = testEdgeSer.addEdge(g, vce, pserver); @@ -509,8 +542,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeTraversalSingleOutRuleTest() throws AAIException { - Vertex vce = g.addV("aai-node-type", "vce", "vnf-id", "vce").next(); - Vertex vnfc1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex vce = this.addVHelper(g, "vertex", "aai-node-type", "vce", "vnf-id", "vce").next(); + Vertex vnfc1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); Edge e = testEdgeSer.addEdge(g, vce, vnfc1); @@ -527,8 +560,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeTraversalMultiRuleOutTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); Edge e1 = testEdgeSer.addEdge(g, gvnf, pserver); Edge e2 = testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -547,8 +580,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeTraversalMultiRuleInTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex complex = g.addV("aai-node-type", "complex", "physical-location-id", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex complex = this.addVHelper(g, "vertex", "aai-node-type", "complex", "physical-location-id", "a-name").next(); Edge e1 = testEdgeSer.addEdge(g, gvnf, complex); Edge e2 = testEdgeSer.addEdge(g, gvnf, complex, "complex-generic-vnf-B"); @@ -567,9 +600,9 @@ public abstract class QueryBuilderTestAbstraction { @Test public void edgeTraversalMultiRuleTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex vnfc1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); - Vertex vnfc2 = g.addV("aai-node-type", "vnfc", "vnfc-name", "b-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex vnfc1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex vnfc2 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "b-name").next(); Edge e1 = testEdgeSer.addEdge(g, gvnf, vnfc1); Edge e2 = testEdgeSer.addEdge(g, gvnf, vnfc2, "re-uses"); @@ -589,8 +622,8 @@ public abstract class QueryBuilderTestAbstraction { @Test(expected = NoEdgeRuleFoundException.class) public void getEdgesBetweenWithLabelsEmptyListTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); testEdgeSer.addEdge(g, gvnf, pserver); testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -603,8 +636,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void getEdgesBetweenWithLabelsSingleItemTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); Edge e1 = testEdgeSer.addEdge(g, gvnf, pserver); Edge e2 = testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -624,8 +657,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void getEdgesBetweenWithLabelsMultipleItemTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); Edge e1 = testEdgeSer.addEdge(g, gvnf, pserver); Edge e2 = testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -656,8 +689,8 @@ public abstract class QueryBuilderTestAbstraction { } private Vertex getVertex() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); testEdgeSer.addEdge(g, gvnf, pserver); testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -667,8 +700,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void createEdgeTraversalWithLabelsSingleItemTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); Edge e1 = testEdgeSer.addEdge(g, gvnf, pserver); Edge e2 = testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -688,8 +721,8 @@ public abstract class QueryBuilderTestAbstraction { @Test public void createEdgeTraversalWithLabelsMultipleItemTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); Edge e1 = testEdgeSer.addEdge(g, gvnf, pserver); Edge e2 = testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -706,6 +739,50 @@ public abstract class QueryBuilderTestAbstraction { } + @Test + public void createEdgeTraversalIfParameterIsPresentParameterExistsTest() throws AAIException { + + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver1 = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex pserver2 = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "b-name").next(); + Vertex optionalVce = this.addVHelper(g, "vertex", "aai-node-type", "vce", "vnf-id", "optional").next(); + + testEdgeSer.addEdge(g, gvnf, pserver1); + testEdgeSer.addEdge(g, gvnf, pserver2); + testEdgeSer.addEdge(g, optionalVce, pserver1); + + QueryBuilder<Edge> tQ = getNewEdgeTraversalWithTestEdgeRules(gvnf); + tQ.createEdgeTraversal(EdgeType.COUSIN, "generic-vnf", "pserver"); + + List<Vertex> list = tQ.createEdgeTraversalIfParameterIsPresent(EdgeType.COUSIN, "pserver", "vce", "optional").toList(); + assertEquals("Has 1 vertex ", 1, list.size()); + assertTrue("result has optional-vce vertex ", list.contains(optionalVce)); + } + + @Test + public void createEdgeTraversalIfParameterIsPresentParameterDoesNotExistTest() throws AAIException { + + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver1 = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex pserver2 = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "b-name").next(); + Vertex optionalVce = this.addVHelper(g, "vertex", "aai-node-type", "vce", "vnf-id", "optional").next(); + + testEdgeSer.addEdge(g, gvnf, pserver1); + testEdgeSer.addEdge(g, gvnf, pserver2); + testEdgeSer.addEdge(g, optionalVce, pserver1); + + QueryBuilder<Edge> tQ = getNewEdgeTraversalWithTestEdgeRules(gvnf); + tQ.createEdgeTraversal(EdgeType.COUSIN, "generic-vnf", "pserver"); + MissingOptionalParameter missingParameter = MissingOptionalParameter.getInstance(); + + List<Vertex> list = tQ.createEdgeTraversalIfParameterIsPresent(EdgeType.COUSIN, "pserver", "vce", missingParameter).toList(); + assertEquals("Has 2 vertices ", 2, list.size()); + assertTrue("result has pserver-1 vertex ", list.contains(pserver1)); + assertTrue("result has pserver-2 vertex ", list.contains(pserver2)); + assertTrue("result does not have optional-vce vertex ", !list.contains(optionalVce)); + } + + protected abstract QueryBuilder<Edge> getNewEdgeTraversalWithTestEdgeRules(Vertex v); protected abstract QueryBuilder<Edge> getNewEdgeTraversalWithTestEdgeRules(); diff --git a/aai-core/src/test/java/org/onap/aai/query/builder/TraversalQueryTest.java b/aai-core/src/test/java/org/onap/aai/query/builder/TraversalQueryTest.java index eb1e57c3..4eac35eb 100644 --- a/aai-core/src/test/java/org/onap/aai/query/builder/TraversalQueryTest.java +++ b/aai-core/src/test/java/org/onap/aai/query/builder/TraversalQueryTest.java @@ -20,14 +20,6 @@ package org.onap.aai.query.builder; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.List; - import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; @@ -40,6 +32,14 @@ import org.onap.aai.db.props.AAIProperties; import org.onap.aai.edges.enums.EdgeType; import org.onap.aai.exceptions.AAIException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + public class TraversalQueryTest extends QueryBuilderTestAbstraction { @Override @@ -141,8 +141,8 @@ public class TraversalQueryTest extends QueryBuilderTestAbstraction { @Test public void abstractEdgeToVertexTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex vnfc1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex vnfc1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); testEdgeSer.addEdge(g, gvnf, vnfc1); @@ -159,8 +159,8 @@ public class TraversalQueryTest extends QueryBuilderTestAbstraction { @Test public void abstractEdgeToVertexTraversalSingleOutRuleTest() throws AAIException { - Vertex vce = g.addV("aai-node-type", "vce", "vnf-id", "vce").next(); - Vertex vnfc1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex vce = this.addVHelper(g, "vertex", "aai-node-type", "vce", "vnf-id", "vce").next(); + Vertex vnfc1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); testEdgeSer.addEdge(g, vce, vnfc1); @@ -183,8 +183,8 @@ public class TraversalQueryTest extends QueryBuilderTestAbstraction { @Test public void abstractEdgeToVertexTraversalSingleInRuleTest() throws AAIException { - Vertex vce = g.addV("aai-node-type", "vce", "vnf-id", "vce").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex vce = this.addVHelper(g, "vertex", "aai-node-type", "vce", "vnf-id", "vce").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); testEdgeSer.addEdge(g, vce, pserver); @@ -201,9 +201,9 @@ public class TraversalQueryTest extends QueryBuilderTestAbstraction { @Test public void abstractEdgeToVertexMultiRuleTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex vnfc1 = g.addV("aai-node-type", "vnfc", "vnfc-name", "a-name").next(); - Vertex vnfc2 = g.addV("aai-node-type", "vnfc", "vnfc-name", "b-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex vnfc1 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "a-name").next(); + Vertex vnfc2 = this.addVHelper(g, "vertex", "aai-node-type", "vnfc", "vnfc-name", "b-name").next(); testEdgeSer.addEdge(g, gvnf, vnfc1); testEdgeSer.addEdge(g, gvnf, vnfc2, "re-uses"); @@ -222,8 +222,8 @@ public class TraversalQueryTest extends QueryBuilderTestAbstraction { @Test public void abstractEdgeToVertexMultiRuleOutTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex pserver = g.addV("aai-node-type", "pserver", "hostname", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex pserver = this.addVHelper(g, "vertex", "aai-node-type", "pserver", "hostname", "a-name").next(); testEdgeSer.addEdge(g, gvnf, pserver); testEdgeSer.addEdge(g, gvnf, pserver, "generic-vnf-pserver-B"); @@ -241,8 +241,8 @@ public class TraversalQueryTest extends QueryBuilderTestAbstraction { @Test public void abstractEdgeToVertexMultiRuleInTraversalTest() throws AAIException { - Vertex gvnf = g.addV("aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); - Vertex complex = g.addV("aai-node-type", "complex", "physical-location-id", "a-name").next(); + Vertex gvnf = this.addVHelper(g, "vertex", "aai-node-type", "generic-vnf", "vnf-id", "gvnf").next(); + Vertex complex = this.addVHelper(g, "vertex", "aai-node-type", "complex", "physical-location-id", "a-name").next(); testEdgeSer.addEdge(g, gvnf, complex); testEdgeSer.addEdge(g, gvnf, complex, "complex-generic-vnf-B"); diff --git a/aai-core/src/test/java/org/onap/aai/query/builder/optimization/AbstractGraphTraversalBuilderOptmizationTest.java b/aai-core/src/test/java/org/onap/aai/query/builder/optimization/AbstractGraphTraversalBuilderOptmizationTest.java index 911cb20c..b517ced2 100644 --- a/aai-core/src/test/java/org/onap/aai/query/builder/optimization/AbstractGraphTraversalBuilderOptmizationTest.java +++ b/aai-core/src/test/java/org/onap/aai/query/builder/optimization/AbstractGraphTraversalBuilderOptmizationTest.java @@ -20,16 +20,7 @@ package org.onap.aai.query.builder.optimization; -import static org.junit.Assert.assertEquals; - import com.google.common.base.CaseFormat; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.Random; - import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; @@ -38,7 +29,6 @@ import org.junit.AfterClass; import org.onap.aai.AAISetup; import org.onap.aai.db.props.AAIProperties; import org.onap.aai.dbmap.AAIGraph; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.ModelType; @@ -50,6 +40,14 @@ import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.springframework.beans.factory.annotation.Autowired; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +import static org.junit.Assert.assertEquals; + public abstract class AbstractGraphTraversalBuilderOptmizationTest extends AAISetup { protected static final List<String> RANDOM_VALUES = Arrays.asList("A", "B", "C", "D", "E"); @@ -74,7 +72,6 @@ public abstract class AbstractGraphTraversalBuilderOptmizationTest extends AAISe private static final ModelType introspectorFactoryType = ModelType.MOXY; private static final QueryStyle queryStyle = QueryStyle.TRAVERSAL; - private static final DBConnectionType type = DBConnectionType.REALTIME; private static TransactionalGraphEngine dbEngine; private static DBSerializer dbser; protected static Loader loader; @@ -89,7 +86,7 @@ public abstract class AbstractGraphTraversalBuilderOptmizationTest extends AAISe loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, schemaVersions.getDefaultVersion()); graph = AAIGraph.getInstance().getGraph(); - dbEngine = new JanusGraphDBEngine(queryStyle, type, loader); + dbEngine = new JanusGraphDBEngine(queryStyle, loader); g = dbEngine.startTransaction().traversal(); dbser = new DBSerializer(schemaVersions.getDefaultVersion(), dbEngine, introspectorFactoryType, "AAI-TEST-" + prefix); @@ -107,8 +104,12 @@ public abstract class AbstractGraphTraversalBuilderOptmizationTest extends AAISe for (int crCtr = 0; crCtr < 3; crCtr++) { crUri = String.format(crUriPattern, prefix + "cloud-owner-" + crCtr, prefix + "cloud-region-id-" + crCtr); // System.out.println(crUri); - cr = g.addV(AAIProperties.NODE_TYPE, CLOUD_REGION, CLOUD_REGION_ID, prefix + "cloud-region-id-" + crCtr, - CLOUD_OWNER, prefix + "cloud-owner-" + crCtr, AAIProperties.AAI_URI, crUri).next(); + cr = g.addV(CLOUD_REGION) + .property(AAIProperties.NODE_TYPE, CLOUD_REGION) + .property(CLOUD_REGION_ID, prefix + "cloud-region-id-" + crCtr) + .property(CLOUD_OWNER, prefix + "cloud-owner-" + crCtr) + .property(AAIProperties.AAI_URI, crUri) + .next(); for (int i = 0; i < tenantNum; i++) { Introspector intro = loader.introspectorFromName(TENANT); tenant = dbser.createNewVertex(intro); diff --git a/aai-core/src/test/java/org/onap/aai/rest/HPACapabilityTest.java b/aai-core/src/test/java/org/onap/aai/rest/HPACapabilityTest.java index a742313a..34477206 100644 --- a/aai-core/src/test/java/org/onap/aai/rest/HPACapabilityTest.java +++ b/aai-core/src/test/java/org/onap/aai/rest/HPACapabilityTest.java @@ -22,8 +22,8 @@ package org.onap.aai.rest; import static org.junit.Assert.assertEquals; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.jayway.jsonpath.JsonPath; import java.util.*; @@ -45,7 +45,7 @@ import org.skyscreamer.jsonassert.JSONAssert; @RunWith(AAIJunitRunner.class) public class HPACapabilityTest { - private static EELFLogger logger = EELFManager.getInstance().getLogger(HPACapabilityTest.class); + private static Logger logger = LoggerFactory.getLogger(HPACapabilityTest.class); private HttpTestUtil httpTestUtil; private Map<String, String> templateValuesMap; diff --git a/aai-core/src/test/java/org/onap/aai/rest/ImpliedDeleteIntegrationTest.java b/aai-core/src/test/java/org/onap/aai/rest/ImpliedDeleteIntegrationTest.java new file mode 100644 index 00000000..2b7a5818 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/rest/ImpliedDeleteIntegrationTest.java @@ -0,0 +1,169 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.rest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.janusgraph.core.JanusGraphTransaction; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.Mockito; +import org.onap.aai.AAISetup; +import org.onap.aai.HttpTestUtil; +import org.onap.aai.PayloadUtil; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.dbmap.AAIGraph; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.rest.ueb.NotificationEvent; +import org.onap.aai.rest.ueb.UEBNotification; +import org.onap.aai.serialization.engines.QueryStyle; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.test.annotation.DirtiesContext; + +import javax.ws.rs.core.Response; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.*; + +@RunWith(value = Parameterized.class) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class ImpliedDeleteIntegrationTest extends AAISetup { + + private static final Logger LOGGER = LoggerFactory.getLogger(ImpliedDeleteIntegrationTest.class); + + @Parameterized.Parameter(value = 0) + public QueryStyle queryStyle; + + @Parameterized.Parameters(name = "QueryStyle.{0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] { + { QueryStyle.TRAVERSAL }, + { QueryStyle.TRAVERSAL_URI } + }); + } + + @Test + public void testPutPserverWithMultiplePInterfaceChildrenAndDoPutWithZeroChildren() throws Exception { + + String uri = "/aai/v12/cloud-infrastructure/pservers/pserver/test-pserver-implied-delete"; + + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + + String resource = PayloadUtil.getResourcePayload("pserver-implied-delete.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject jsonObject = new JSONObject(response.getEntity().toString()); + JSONAssert.assertEquals(resource, response.getEntity().toString(), false); + jsonObject.getJSONObject("p-interfaces").remove("p-interface"); + + notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + + response = httpTestUtil.doPut(uri, jsonObject.toString()); + assertEquals("Expecting the pserver to be updated and delete children", 200, response.getStatus()); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + assertThat(notificationEvents.size(), is(5)); + + List<String> notificationEventHeaders = notification.getEvents() + .stream() + .map(event -> event.getEventHeader().marshal(false)) + .collect(Collectors.toList()); + + Long deletedEventsCount = notificationEventHeaders.stream().filter(e -> e.contains("\"DELETE\"")).count(); + + assertThat(deletedEventsCount, is(4L)); + + response = httpTestUtil.doGet(uri); + assertThat(response.getEntity().toString(), not(containsString("p-interface"))); + } + + @Test + public void testPutGenericVnf() throws Exception { + + String uri = "/aai/v12/network/generic-vnfs/generic-vnf/generic-vnf-implied-delete"; + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String resource = PayloadUtil.getResourcePayload("generic-vnf-implied-delete.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the generic-vnf to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, resource); + assertEquals("Expecting the generic-vnf to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri); + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + + JSONObject jsonObject = new JSONObject(response.getEntity().toString()); + JSONAssert.assertEquals(resource, response.getEntity().toString(), false); + jsonObject.getJSONObject("vf-modules").remove("vf-module"); + + response = httpTestUtil.doPut(uri, jsonObject.toString()); + assertEquals("Expecting the generic-vnf to be not deleted and fail with 403", 403, response.getStatus()); + assertThat(response.getEntity().toString(), containsString("User is not allowed to perform implicit delete")); + } + + @After + public void tearDown() { + + JanusGraphTransaction transaction = AAIGraph.getInstance().getGraph().newTransaction(); + boolean success = true; + + try { + + GraphTraversalSource g = transaction.traversal(); + + g.V().has("source-of-truth", "JUNIT").toList().forEach(v -> v.remove()); + + } catch (Exception ex) { + success = false; + LOGGER.error("Unable to remove the vertexes", ex); + } finally { + if (success) { + transaction.commit(); + } else { + transaction.rollback(); + fail("Unable to teardown the graph"); + } + } + } + +} diff --git a/aai-core/src/test/java/org/onap/aai/rest/NotificationDmaapEventTest.java b/aai-core/src/test/java/org/onap/aai/rest/NotificationDmaapEventTest.java new file mode 100644 index 00000000..16783180 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/rest/NotificationDmaapEventTest.java @@ -0,0 +1,1028 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.rest; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraph; +import org.janusgraph.core.JanusGraphTransaction; +import org.javatuples.Pair; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.Mockito; +import org.onap.aai.AAISetup; +import org.onap.aai.HttpTestUtil; +import org.onap.aai.PayloadUtil; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.dbmap.AAIGraph; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.rest.ueb.NotificationEvent; +import org.onap.aai.rest.ueb.UEBNotification; +import org.onap.aai.serialization.engines.QueryStyle; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.test.annotation.DirtiesContext; + +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.*; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.junit.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +@RunWith(value = Parameterized.class) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class NotificationDmaapEventTest extends AAISetup { + + @Parameterized.Parameter + public QueryStyle queryStyle; + + @Parameterized.Parameters(name = "QueryStyle.{0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] { + { QueryStyle.TRAVERSAL }, + { QueryStyle.TRAVERSAL_URI } + }); + } + + @Test + public void testCreateWithPserverWithAllChildrenAndVerifyMultipleNotificationsWhenNotificationDepthIsZero() throws IOException, AAIException { + + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + int expectedCreateEvents = 17; + + assertThat(notification.getEvents().size(), is(expectedCreateEvents)); + + // Verify all the events are create since its a new PUT + notification.getEvents().forEach((event) -> { + + String header = event.getEventHeader().marshal(false); + + assertThat( + event.getEventHeader().marshal(false), + containsString("\"CREATE\"") + ); + + assertThat( + header, + containsString("\"top-entity-type\":\"pserver\"") + ); + + }); + + response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + } + + // Test existing pserver create new pinterface check dmaap event for pinterface is CREATE + @Test + public void testExistingPserverCreateNewChildPInterfaceAndCheckDmaapEventForPInterfaceIsCreateWhenNotificationDepthIsZero() throws IOException, AAIException { + + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String pserverResource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, pserverResource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + notification.clearEvents(); + + + response = httpTestUtil.doGet(uri , "all"); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject pserverJson = new JSONObject(response.getEntity().toString()); + JSONObject pInterfaceObject = new JSONObject(); + pInterfaceObject.put("interface-name", "p-interface-1"); + + pserverJson.getJSONObject("p-interfaces").getJSONArray("p-interface").put(pInterfaceObject); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + response = httpTestUtil.doPut(uri, pserverJson.toString()); + assertEquals("Expecting the pserver to be updated with a new p-interface", 200, response.getStatus()); + + response = httpTestUtil.doGet(uri + "/p-interfaces/p-interface/p-interface-1", "0"); + assertEquals("Expecting the p-interface to be found", 200, response.getStatus()); + + List<NotificationEvent> events = notification.getEvents(); + assertThat(events.size(), is(2)); + + String notificationEventHeader = events.get(1).getEventHeader().marshal(false); + String notificationEventBody = events.get(1).getObj().marshal(false); + + assertThat(notificationEventHeader, containsString("\"action\":\"CREATE\"")); + assertThat(notificationEventHeader, containsString("\"entity-type\":\"p-interface\"")); + assertThat(notificationEventHeader, containsString("\"top-entity-type\":\"pserver\"")); + + String expectedNotificationHeader = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-zero/expected-notification-header-create-child-on-existing-obj.json"); + String expectedNotificationBody = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-zero/expected-notification-body-create-child-on-existing-obj.json"); + + JSONAssert.assertEquals(expectedNotificationHeader, notificationEventHeader, false); + JSONAssert.assertEquals(expectedNotificationBody, notificationEventBody, false); + } + + @Test + public void testExistingPserverCreateNewChildPInterfaceAndCheckDmaapEventForPserverIsSentWithNewPInterfaceWhenNotificationDepthIsAll() throws IOException, AAIException { + + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String pserverResource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, pserverResource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri , "all"); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject pserverJson = new JSONObject(response.getEntity().toString()); + String pserverResourceVersion = pserverJson.getString("resource-version"); + + JSONObject pInterfaceObject = new JSONObject(); + pInterfaceObject.put("interface-name", "p-interface-1"); + + pserverJson.getJSONObject("p-interfaces").getJSONArray("p-interface").put(pInterfaceObject); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + response = httpTestUtil.doPut(uri, pserverJson.toString()); + assertEquals("Expecting the pserver to be updated with a new p-interface", 200, response.getStatus()); + + response = httpTestUtil.doGet(uri + "/p-interfaces/p-interface/p-interface-1", "0"); + assertEquals("Expecting the p-interface to be found", 200, response.getStatus()); + + List<NotificationEvent> events = notification.getEvents(); + assertThat(events.size(), is(1)); + + String notificationEventHeader = events.get(0).getEventHeader().marshal(false); + String notificationEventBody = events.get(0).getObj().marshal(false); + + assertThat(notificationEventHeader, containsString("\"action\":\"UPDATE\"")); + assertThat(notificationEventHeader, containsString("\"entity-type\":\"pserver\"")); + assertThat(notificationEventHeader, containsString("\"top-entity-type\":\"pserver\"")); + + String expectedNotificationHeader = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-all/expected-notification-header-create-child-on-existing-obj.json"); + String expectedNotificationBody = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-all/expected-notification-body-create-child-on-existing-obj.json"); + + JSONAssert.assertEquals(expectedNotificationHeader, notificationEventHeader, false); + JSONAssert.assertEquals(expectedNotificationBody, notificationEventBody, false); + + response = httpTestUtil.doGet(uri, "0"); + pserverJson = new JSONObject(response.getEntity().toString()); + String newPserverResourceVersion = pserverJson.getString("resource-version"); + + // After an pserver's p-interface is updated on the pserver, even though + // the pserver nothing changed, expecting the pserver resource version to be changed + assertThat( + "Expecting the new pserver resource version and old resource version to be not same", + newPserverResourceVersion, + is(not(pserverResourceVersion)) + ); + assertEquals("Expecting the p-interface to be found", 200, response.getStatus()); + } + + // Test Bulk Scenario + @Test + public void testBulkScenarioWhereMultipleCreatesAndEnsureNoDuplicationInDmaapEventsWhenNotificationDepthIsZero() throws UnsupportedEncodingException, AAIException { + + String pserverUri = "/aai/v14/cloud-infrastructure/pservers/pserver/random-pserver"; + String cloudRegionUri = "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/random-cloud-region-owner/random-cloud-region-id"; + + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + + Map<String, String> uriPayload = new LinkedHashMap<>(); + + uriPayload.put(pserverUri, "{}"); + uriPayload.put(cloudRegionUri, "{}"); + + Response response = httpTestUtil.doPut(uriPayload); + assertThat(response.getStatus(), is(201)); + + int numberOfEventsActual = notification.getEvents().size(); + int expectedEvents = 2; + + assertThat("Expecting the number of dmaap events to be 2", numberOfEventsActual, is(expectedEvents)); + + notification.getEvents().forEach((event) -> { + String notificationEventHeader = event.getEventHeader().marshal(false); + assertThat(notificationEventHeader, containsString("\"CREATE\"")); + }); + } + + + @Test + public void testBulkScenarioWhereMultipleCreatesAndEnsureNoDuplicationInDmaapEventsWhenNotificationDepthIsAll() throws UnsupportedEncodingException, AAIException { + + String pserverUri = "/aai/v14/cloud-infrastructure/pservers/pserver/random-pserver"; + String cloudRegionUri = "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/random-cloud-region-owner/random-cloud-region-id"; + + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + + Map<String, String> uriPayload = new LinkedHashMap<>(); + + uriPayload.put(pserverUri, "{}"); + uriPayload.put(cloudRegionUri, "{}"); + + Response response = httpTestUtil.doPut(uriPayload); + assertThat(response.getStatus(), is(201)); + + int numberOfEventsActual = notification.getEvents().size(); + int expectedEvents = 2; + + assertThat("Expecting the number of dmaap events to be 2", numberOfEventsActual, is(expectedEvents)); + + notification.getEvents().forEach((event) -> { + String notificationEventHeader = event.getEventHeader().marshal(false); + assertThat(notificationEventHeader, containsString("\"CREATE\"")); + }); + } + + @Test + public void testDeleteOnExistingPserverAndCheckIfNotificationDepthIsZeroThatAllEventsHaveDeleteAndThatDepthIsZeroOnEachNotificationEvent() throws IOException, AAIException { + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String pserverResource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, pserverResource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri , "all"); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject pserverObject = new JSONObject(response.getEntity().toString()); + String resourceVersion = pserverObject.getString("resource-version"); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + response = httpTestUtil.doDelete(uri, resourceVersion); + assertEquals("Expecting the pserver to be deleted", 204, response.getStatus()); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + assertThat(notificationEvents.size(), is(17)); + + notificationEvents.forEach((event) -> { + + String header = event.getEventHeader().marshal(false); + + assertThat( + event.getEventHeader().marshal(false), + containsString("\"DELETE\"") + ); + + assertThat( + header, + containsString("\"top-entity-type\":\"pserver\"") + ); + }); + } + + + @Test + public void testDeleteOnExistingResourceVersionMismatchNoEventGenerated() throws IOException, AAIException { + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String pserverResource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, pserverResource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri , "all"); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject pserverObject = new JSONObject(response.getEntity().toString()); + String resourceVersion = pserverObject.getString("resource-version"); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + response = httpTestUtil.doDelete(uri, resourceVersion+"123"); + assertEquals("Resource version mismatch exception", 412, response.getStatus()); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + assertThat(notificationEvents.size(), is(0)); + } + + + // Test notification depth set to all + // Scenario for testing the creation of pserver with children, grandchildren + // Default behaviour is for one event to be sent out + // which includes all the children and grandchildren, etc + @Test + public void testCreateWithPserverWithAllChildrenAndVerifyOneNotificationWhenNotificationDepthIsAll() throws IOException, AAIException { + + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + assertThat(notification.getEvents().size(), is(1)); + + NotificationEvent notificationEvent = notification.getEvents().get(0); + + // Verify all the events are create since its a new PUT + String header = notificationEvent.getEventHeader().marshal(false); + + assertThat( + header, + containsString("\"CREATE\"") + ); + + assertThat( + header, + containsString("\"entity-type\":\"pserver\"") + ); + + assertThat( + header, + containsString("\"top-entity-type\":\"pserver\"") + ); + + assertThat( + header, + containsString("\"entity-link\":\"" + uri + "\"") + ); + + response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONAssert.assertEquals(response.getEntity().toString(), notificationEvent.getObj().marshal(false), false); + } + + @Test + public void testPatchExistingPserverWithChildrenAndModifyOnlyOneObjectAndVerifyThatOnlyOneNotificationEventNoChildrenWhenNotificationDepthIsZero() throws IOException, AAIException { + + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject pserverObject = new JSONObject(); + pserverObject.put("equip-type", "new-equip-patch-type"); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + response = httpTestUtil.doPatch(uri, pserverObject.toString()); + assertThat(response.getStatus(), is(200)); + + response = httpTestUtil.doGet(uri, "0"); + assertThat(response.getEntity().toString(), containsString("new-equip-patch-type")); + + assertThat(notification.getEvents().size(), is(1)); + String updateNotificationEvent = notification.getEvents().get(0).getObj().marshal(true); + + // Check that everything in notification event is also response body + // Not comparing the other way as notification only includes parents main properties + JSONAssert.assertEquals(updateNotificationEvent, response.getEntity().toString(), false); + } + + @Test + public void testPatchExistingPserverWithChildrenAndModifyOnlyOneObjectAndVerifyThatOnlyOneNotificationEventIncludeChildrenWhenNotificationDepthIsAll() throws IOException, AAIException { + + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject pserverObject = new JSONObject(); + pserverObject.put("equip-type", "new-equip-patch-type"); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + response = httpTestUtil.doPatch(uri, pserverObject.toString()); + assertThat(response.getStatus(), is(200)); + + response = httpTestUtil.doGet(uri, "all"); + assertThat(response.getEntity().toString(), containsString("new-equip-patch-type")); + + assertThat(notification.getEvents().size(), is(1)); + String updateNotificationEvent = notification.getEvents().get(0).getObj().marshal(true); + + // Check that everything in notification event is also response body + // Not comparing the other way as notification only includes parents main properties + JSONAssert.assertEquals(updateNotificationEvent, response.getEntity().toString(), false); + } + + // Test notification depth set to all + // Scenario where we are only updating one field in p-interface + // Make sure the parent and children are included + @Test + public void testUpdateExistingPserverWithChildrenAndModifyOnlyOneObjectAndVerifyThatOnlyOneNotificationEventIncludingChildrenWhenNotificationDepthIsAll() throws IOException, AAIException { + + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + response = httpTestUtil.doGet(uri + "/p-interfaces/p-interface/example-interface-name-val-46147", "0"); + assertEquals("Expecting the p-interface to be found", 200, response.getStatus()); + + JSONObject pInterfaceObject = new JSONObject(response.getEntity().toString()); + pInterfaceObject.put("equipment-identifier", "new-equipment-identifier"); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + response = httpTestUtil.doPut(uri + "/p-interfaces/p-interface/example-interface-name-val-46147", pInterfaceObject.toString()); + assertThat(response.getStatus(), is(200)); + + // Get the parent uri as the notification event json has parent structure it makes it easy to compare + response = httpTestUtil.doGet(uri); + assertThat(response.getEntity().toString(), containsString("new-equipment-identifier")); + + assertThat(notification.getEvents().size(), is(1)); + String updateNotificationEvent = notification.getEvents().get(0).getObj().marshal(true); + + // Check that everything in notification event is also response body + // Not comparing the other way as notification only includes parents main properties + JSONAssert.assertEquals(updateNotificationEvent, response.getEntity().toString(), false); + } + + // Test notification depth set to 0 + // Scenario where we are only updating one field in p-interface + @Test + public void testUpdateExistingPserverWithChildrenAndModifyOnlyPInterfaceAndVerifyThatOnlyOneNotificationForPInterfaceIsCreatedWhenNotificationDepthIsZero() throws IOException, AAIException { + + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + response = httpTestUtil.doGet(uri + "/p-interfaces/p-interface/example-interface-name-val-46147", "0"); + assertEquals("Expecting the p-interface to be found", 200, response.getStatus()); + + JSONObject pInterfaceObject = new JSONObject(response.getEntity().toString()); + pInterfaceObject.put("equipment-identifier", "new-equipment-identifier"); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + response = httpTestUtil.doPut(uri + "/p-interfaces/p-interface/example-interface-name-val-46147", pInterfaceObject.toString()); + assertThat(response.getStatus(), is(200)); + + response = httpTestUtil.doGet(uri); + assertThat(notification.getEvents().size(), is(1)); + String updateNotificationEvent = notification.getEvents().get(0).getObj().marshal(true); + System.out.println("Update notification " + updateNotificationEvent); + + // Check that everything in notification event is also response body + // Not comparing the other way as notification only includes parents main properties + JSONAssert.assertEquals(updateNotificationEvent, response.getEntity().toString(), false); + } + + @Test + public void testExistingPserverWithChildAndGenericVnfAndCreateEdgeBetweenThemAndCheckNoChildWhenNotificationDepthIsZero() throws IOException, AAIException { + + String hostname = "example-hostname-val-85598"; + + String pserverUri = "/aai/v14/cloud-infrastructure/pservers/pserver/" + hostname; + String genericVnfUri = "/aai/v14/network/generic-vnfs/generic-vnf/generic-vnf-notification"; + + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + String genericVnfResource = PayloadUtil.getResourcePayload("generic-vnf-notification.json"); + + Response response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(pserverUri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + assertEquals("Expecting the generic-vnf to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(genericVnfUri, genericVnfResource); + assertEquals("Expecting the generic-vnf to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), not(containsString(hostname))); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + + String relationship = PayloadUtil.getResourcePayload("pserver-to-gvnf-relationship-notification.json"); + + response = httpTestUtil.doPut(pserverUri + "/relationship-list/relationship", relationship); + assertEquals("Expecting the pserver to generic-vnf relationship to be created", 200, response.getStatus()); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + assertThat(notificationEvents.size(), is(2)); + + String expectedNotificationHeader = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-zero/expected-notification-header-create-edge-between-pserver-and-generic-vnf.json"); + String expectedNotificationBody = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-zero/expected-notification-body-create-edge-between-pserver-and-generic-vnf.json"); + + JSONAssert.assertEquals(expectedNotificationHeader, notificationEvents.get(0).getEventHeader().marshal(false), false); + JSONAssert.assertEquals(expectedNotificationBody, notificationEvents.get(0).getObj().marshal(false), false); + + response = httpTestUtil.doGet(genericVnfUri); + + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), containsString(hostname)); + } + + @Test + public void testExistingPserverWithChildAndGenericVnfAndCreateEdgeBetweenThemAndCheckChildrenIncludedWhenNotificationDepthIsAll() throws IOException, AAIException { + + String hostname = "example-hostname-val-85598"; + + String pserverUri = "/aai/v14/cloud-infrastructure/pservers/pserver/" + hostname; + String genericVnfUri = "/aai/v14/network/generic-vnfs/generic-vnf/generic-vnf-notification"; + + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + String genericVnfResource = PayloadUtil.getResourcePayload("generic-vnf-notification.json"); + + Response response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(pserverUri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + assertEquals("Expecting the generic-vnf to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(genericVnfUri, genericVnfResource); + assertEquals("Expecting the generic-vnf to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), not(containsString(hostname))); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + + String relationship = PayloadUtil.getResourcePayload("pserver-to-gvnf-relationship-notification.json"); + + response = httpTestUtil.doPut(pserverUri + "/relationship-list/relationship", relationship); + assertEquals("Expecting the pserver to generic-vnf relationship to be created", 200, response.getStatus()); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + assertThat(notificationEvents.size(), is(2)); + + String expectedNotificationHeader = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-all/expected-notification-header-create-edge-between-pserver-and-generic-vnf.json"); + String expectedNotificationBody = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-all/expected-notification-body-create-edge-between-pserver-and-generic-vnf.json"); + + System.out.println("Notification Body: " + notificationEvents.get(0).getObj().marshal(false)); + JSONAssert.assertEquals(expectedNotificationHeader, notificationEvents.get(0).getEventHeader().marshal(false), false); + JSONAssert.assertEquals(expectedNotificationBody, notificationEvents.get(0).getObj().marshal(false), false); + + response = httpTestUtil.doGet(genericVnfUri); + + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), containsString(hostname)); + } + + @Test + public void testExistingPserverWithChildAndGenericVnfAndExistingEdgeBetweenThemAndDeleteEdgeAndCheckNoChildWhenNotificationDepthIsZero() throws IOException, AAIException { + + String hostname = "example-hostname-val-85598"; + + String pserverUri = "/aai/v14/cloud-infrastructure/pservers/pserver/" + hostname; + String genericVnfUri = "/aai/v14/network/generic-vnfs/generic-vnf/generic-vnf-notification"; + + String relationship = PayloadUtil.getResourcePayload("pserver-to-gvnf-relationship-notification.json"); + + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + String genericVnfResource = PayloadUtil.getResourcePayload("generic-vnf-notification.json"); + + Response response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(pserverUri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + assertEquals("Expecting the generic-vnf to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(genericVnfUri, genericVnfResource); + assertEquals("Expecting the generic-vnf to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), not(containsString(hostname))); + + + response = httpTestUtil.doPut(pserverUri + "/relationship-list/relationship", relationship); + assertEquals("Expecting the pserver to generic-vnf relationship to be created", 200, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), containsString(hostname)); + + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), containsString(hostname)); + + response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject pserverJson = new JSONObject(response.getEntity().toString()); + String resourceVersion = pserverJson.getString("resource-version"); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MINIMUM_DEPTH); + + response = httpTestUtil.doDelete(pserverUri + "/relationship-list/relationship", resourceVersion, relationship); + assertThat("Expected the pserver relationship to generic-vnf to be deleted", response.getStatus(), is(204)); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + + assertThat(notificationEvents.size(), is(2)); + + String expectedNotificationHeader = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-zero/expected-notification-header-delete-edge-between-pserver-and-generic-vnf.json"); + String expectedNotificationBody = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-zero/expected-notification-body-delete-edge-between-pserver-and-generic-vnf.json"); + + JSONAssert.assertEquals(expectedNotificationHeader, notificationEvents.get(0).getEventHeader().marshal(false), false); + JSONAssert.assertEquals(expectedNotificationBody, notificationEvents.get(0).getObj().marshal(false), false); + + } + + @Test + public void testExistingPserverWithChildAndGenericVnfAndExistingEdgeBetweenThemAndDeleteEdgeAndCheckChildrenWhenNotificationDepthIsAll() throws IOException, AAIException { + + String hostname = "example-hostname-val-85598"; + + String pserverUri = "/aai/v14/cloud-infrastructure/pservers/pserver/" + hostname; + String genericVnfUri = "/aai/v14/network/generic-vnfs/generic-vnf/generic-vnf-notification"; + + String relationship = PayloadUtil.getResourcePayload("pserver-to-gvnf-relationship-notification.json"); + + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String resource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + String genericVnfResource = PayloadUtil.getResourcePayload("generic-vnf-notification.json"); + + Response response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(pserverUri, resource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + assertEquals("Expecting the generic-vnf to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(genericVnfUri, genericVnfResource); + assertEquals("Expecting the generic-vnf to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), not(containsString(hostname))); + + + response = httpTestUtil.doPut(pserverUri + "/relationship-list/relationship", relationship); + assertEquals("Expecting the pserver to generic-vnf relationship to be created", 200, response.getStatus()); + + response = httpTestUtil.doGet(genericVnfUri); + + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), containsString(hostname)); + + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + assertThat(response.getEntity().toString(), containsString(hostname)); + + response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject pserverJson = new JSONObject(response.getEntity().toString()); + String resourceVersion = pserverJson.getString("resource-version"); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + + response = httpTestUtil.doDelete(pserverUri + "/relationship-list/relationship", resourceVersion, relationship); + assertThat("Expected the pserver relationship to generic-vnf to be deleted", response.getStatus(), is(204)); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + assertThat(notificationEvents.size(), is(2)); + + String expectedNotificationHeader = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-all/expected-notification-header-delete-edge-between-pserver-and-generic-vnf.json"); + String expectedNotificationBody = PayloadUtil.getResourcePayload("notification-dmaap-events/depth-all/expected-notification-body-delete-edge-between-pserver-and-generic-vnf.json"); + + JSONAssert.assertEquals(expectedNotificationHeader, notificationEvents.get(0).getEventHeader().marshal(false), false); + JSONAssert.assertEquals(expectedNotificationBody, notificationEvents.get(0).getObj().marshal(false), false); + + } + + @Test + public void testDeleteOnExistingResourceVersionMismatchNoEventGeneratedFullDepth() throws IOException, AAIException { + String uri = "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598"; + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + String pserverResource = PayloadUtil.getResourcePayload("pserver-with-children-for-notification.json"); + + Response response = httpTestUtil.doGet(uri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(uri, pserverResource); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doGet(uri , "all"); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + + JSONObject pserverObject = new JSONObject(response.getEntity().toString()); + String resourceVersion = pserverObject.getString("resource-version"); + + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + response = httpTestUtil.doDelete(uri, resourceVersion+"123"); + assertEquals("Resource version mismatch exception", 412, response.getStatus()); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + assertThat(notificationEvents.size(), is(0)); + } + + @Test + public void testCreateVnfWithChildrenCreateCustomerWithChildrenAndCousinBetweenVlanAndServiceInstanceThenDeleteCustomerVerifyingVlanRV() throws IOException, AAIException { + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + JsonObject paylaods = new JsonParser().parse( + PayloadUtil.getResourcePayload("customer_with_children_and_generic-vnf_with_children_and_edge_between_service-instance_vlan.json")) + .getAsJsonObject(); + String gvnfPaylaod = paylaods.get("generic-vnf").toString(); + String custPaylaod = paylaods.get("customer").toString(); + String gvnfUri = "/aai/v14/network/generic-vnfs/generic-vnf/gvnf"; + String custUri = "/aai/v14/business/customers/customer/cust"; + String vlanUri = "/aai/v14/network/generic-vnfs/generic-vnf/gvnf/l-interfaces/l-interface/lint/vlans/vlan/vlan"; + + //Setup generic vnf + Response response = httpTestUtil.doGet(gvnfUri); + assertEquals("Expecting the generic-vnf to be not found", 404, response.getStatus()); + response = httpTestUtil.doPut(gvnfUri, gvnfPaylaod); + assertEquals("Expecting the generic-vnf to be created", 201, response.getStatus()); + response = httpTestUtil.doGet(gvnfUri , "all"); + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + response = httpTestUtil.doGet(vlanUri , "all"); + assertEquals("Expecting the vlan to be found", 200, response.getStatus()); + String vlanResourceVersion = new JSONObject(response.getEntity().toString()).getString("resource-version"); + + //Setup customer with service instance relation to vlan + response = httpTestUtil.doGet(custUri); + assertEquals("Expecting the customer to be not found", 404, response.getStatus()); + response = httpTestUtil.doPut(custUri, custPaylaod); + assertEquals("Expecting the customer to be created", 201, response.getStatus()); + response = httpTestUtil.doGet(custUri , "all"); + assertEquals("Expecting the customer to be found", 200, response.getStatus()); + String custResourceVersion = new JSONObject(response.getEntity().toString()).getString("resource-version"); + + //Verify vlan rv was updated + response = httpTestUtil.doGet(vlanUri , "all"); + assertEquals("Expecting the vlan to be found", 200, response.getStatus()); + String vlanResourceVersionAfterCustPut = new JSONObject(response.getEntity().toString()).getString("resource-version"); + assertThat("Expecting the vlan resource version to be updated", vlanResourceVersionAfterCustPut, not(is(vlanResourceVersion))); + + //Delete customer + notification.clearEvents(); + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + response = httpTestUtil.doDelete(custUri, custResourceVersion); + assertEquals("Expecting customer to be deleted", 204, response.getStatus()); + + //Verify vlan rv was updated + response = httpTestUtil.doGet(vlanUri , "all"); + assertEquals("Expecting the vlan to be found", 200, response.getStatus()); + String vlanResourceVersionAfterDelete = new JSONObject(response.getEntity().toString()).getString("resource-version"); + assertThat("Expecting the vlan resource version to be updated", vlanResourceVersionAfterDelete, not(is(vlanResourceVersionAfterCustPut))); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + assertThat("Expect the delete to generate 4 events customer, its children and vlan", notificationEvents.size(), is(4)); + } + + + @Test + public void testBulkCreateOfComplexAndPserverWithRelationshipThenBulkDeleteBoth() throws IOException, AAIException { + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + + JsonObject paylaods = new JsonParser().parse( + PayloadUtil.getResourcePayload("complex_pserver_with_relation.json")) + .getAsJsonObject(); + String complexPaylaod = paylaods.get("complex").toString(); + String pserverPaylaod = paylaods.get("pserver").toString(); + String complexUri = "/aai/v14/cloud-infrastructure/complexes/complex/complex-1"; + String pserverUri = "/aai/v14/cloud-infrastructure/pservers/pserver/pserver-1"; + + Response response = httpTestUtil.doGet(complexUri); + assertEquals("Expecting the complex to be not found", 404, response.getStatus()); + response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + Map<String,String> puts = new LinkedHashMap<>(); + puts.put(complexUri, complexPaylaod); + puts.put(pserverUri, pserverPaylaod); + + response = httpTestUtil.doPut(puts); + assertEquals("Expecting the puts request to succeed", 201, response.getStatus()); + assertEquals("Expect 2 messages to be created", 2, notification.getEvents().size()); + response = httpTestUtil.doGet(complexUri , "all"); + assertEquals("Expecting the complex to be found", 200, response.getStatus()); + String complexRV = new JSONObject(response.getEntity().toString()).getString("resource-version"); + response = httpTestUtil.doGet(pserverUri , "all"); + assertEquals("Expecting the pserver to be found", 200, response.getStatus()); + String pserverRv = new JSONObject(response.getEntity().toString()).getString("resource-version"); + assertThat("Resource versions match", complexRV, is(pserverRv)); + + Map<String, Pair<String, String>> deletes = new LinkedHashMap<>(); + deletes.put(pserverUri, new Pair<>(pserverRv, null)); + deletes.put(complexUri, new Pair<>(complexRV, null)); + notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + httpTestUtil.doDelete(deletes); + + response = httpTestUtil.doGet(complexUri); + assertEquals("Expecting the complex to be not found", 404, response.getStatus()); + response = httpTestUtil.doGet(pserverUri); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + } + + @Test + public void testCreateVnfWithChildrenCreateCustomerWithChildrenAndCousinBetweenVlanAndServiceInstanceThenImplicitDeleteVlanVerifyingServiceInstanceRV() throws IOException, AAIException { + UEBNotification notification = Mockito.spy(new UEBNotification(ModelType.MOXY, loaderFactory, schemaVersions)); + HttpTestUtil httpTestUtil = new HttpTestUtil(queryStyle); + + JsonObject paylaods = new JsonParser().parse( + PayloadUtil.getResourcePayload("customer_with_children_and_generic-vnf_with_children_and_edge_between_service-instance_vlan.json")) + .getAsJsonObject(); + String gvnfPaylaod = paylaods.get("generic-vnf").toString(); + String custPaylaod = paylaods.get("customer").toString(); + String custUri = "/aai/v14/business/customers/customer/cust"; + String ssUri = custUri + "/service-subscriptions/service-subscription/ss"; + String siUri = ssUri + "/service-instances/service-instance/si"; + String gvnfUri = "/aai/v14/network/generic-vnfs/generic-vnf/gvnf"; + String lintUri = gvnfUri + "/l-interfaces/l-interface/lint"; + String vlanUri = lintUri + "/vlans/vlan/vlan"; + + //Setup generic vnf + Response response = httpTestUtil.doGet(gvnfUri); + assertEquals("Expecting the generic-vnf to be not found", 404, response.getStatus()); + response = httpTestUtil.doPut(gvnfUri, gvnfPaylaod); + assertEquals("Expecting the generic-vnf to be created", 201, response.getStatus()); + response = httpTestUtil.doGet(gvnfUri , "all"); + assertEquals("Expecting the generic-vnf to be found", 200, response.getStatus()); + response = httpTestUtil.doGet(vlanUri , "all"); + assertEquals("Expecting the vlan to be found", 200, response.getStatus()); + String vlanResourceVersion = new JSONObject(response.getEntity().toString()).getString("resource-version"); + + //Setup customer with service instance relation to vlan + response = httpTestUtil.doGet(custUri); + assertEquals("Expecting the customer to be not found", 404, response.getStatus()); + response = httpTestUtil.doPut(custUri, custPaylaod); + assertEquals("Expecting the customer to be created", 201, response.getStatus()); + response = httpTestUtil.doGet(custUri , "all"); + assertEquals("Expecting the customer to be found", 200, response.getStatus()); + response = httpTestUtil.doGet(siUri , "all"); + assertEquals("Expecting the service-instance to be found", 200, response.getStatus()); + String serviceInstanceResourceVersion = new JSONObject(response.getEntity().toString()).getString("resource-version"); + + //Verify vlan rv was updated + response = httpTestUtil.doGet(vlanUri , "all"); + assertEquals("Expecting the vlan to be found", 200, response.getStatus()); + String vlanResourceVersionAfterCustPut = new JSONObject(response.getEntity().toString()).getString("resource-version"); + assertThat("Expecting the vlan resource version to be updated", vlanResourceVersionAfterCustPut, not(is(vlanResourceVersion))); + + //Get linterface, replace vlans with empty json (implicit delete) and put triggering implicit delete + response = httpTestUtil.doGet(lintUri , "all"); + assertEquals("Expecting the l-interface to be found", 200, response.getStatus()); + JSONObject lintJson = new JSONObject(response.getEntity().toString()); + lintJson.put("vlans", new JsonObject()); + notification.clearEvents(); + httpTestUtil = new HttpTestUtil(queryStyle, notification, AAIProperties.MAXIMUM_DEPTH); + response = httpTestUtil.doPut(lintUri, lintJson.toString()); + assertEquals("Expecting the l-interface to be updated", 200, response.getStatus()); + + List<NotificationEvent> notificationEvents = notification.getEvents(); + assertThat("Expect the implied delete to generate 2", notificationEvents.size(), is(2)); + + //Verify vlan is no longer there anf get service-instance and compare rv + response = httpTestUtil.doGet(vlanUri , "all"); + assertEquals("Expecting the vlan not to be found", 404, response.getStatus()); + response = httpTestUtil.doGet(siUri , "all"); + assertEquals("Expecting the service-instance to be found", 200, response.getStatus()); + String serviceInstanceResourceVersionAfterImplicitDelete = new JSONObject(response.getEntity().toString()).getString("resource-version"); + assertThat("Expecting the service-instance resource version to be updated after implicit delete of vlan", + serviceInstanceResourceVersionAfterImplicitDelete, + not(is(serviceInstanceResourceVersion))); + } + + @After + public void teardown() { + + JanusGraph janusGraph = AAIGraph.getInstance().getGraph(); + JanusGraphTransaction transaction = janusGraph.newTransaction(); + + GraphTraversalSource g = transaction.traversal(); + + g.V() + .has(AAIProperties.SOURCE_OF_TRUTH, "JUNIT") + .forEachRemaining(Vertex::remove); + + transaction.commit(); + } +} diff --git a/aai-core/src/test/java/org/onap/aai/rest/PrivateEdgeIntegrationTest.java b/aai-core/src/test/java/org/onap/aai/rest/PrivateEdgeIntegrationTest.java index d3452153..3bb017d6 100644 --- a/aai-core/src/test/java/org/onap/aai/rest/PrivateEdgeIntegrationTest.java +++ b/aai-core/src/test/java/org/onap/aai/rest/PrivateEdgeIntegrationTest.java @@ -29,8 +29,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.jayway.jsonpath.JsonPath; import java.util.*; @@ -55,7 +55,7 @@ import org.onap.aai.setup.SchemaVersion; @RunWith(value = Parameterized.class) public class PrivateEdgeIntegrationTest extends AAISetup { - private static EELFLogger logger = EELFManager.getInstance().getLogger(PserverTest.class); + private static Logger logger = LoggerFactory.getLogger(PserverTest.class); private HttpTestUtil httpTestUtil; private Map<String, String> relationshipMap; diff --git a/aai-core/src/test/java/org/onap/aai/rest/PserverDuplicateTest.java b/aai-core/src/test/java/org/onap/aai/rest/PserverDuplicateTest.java index 5fe3bd00..cdaf1010 100644 --- a/aai-core/src/test/java/org/onap/aai/rest/PserverDuplicateTest.java +++ b/aai-core/src/test/java/org/onap/aai/rest/PserverDuplicateTest.java @@ -24,8 +24,8 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; import java.util.UUID; @@ -52,7 +52,7 @@ import org.onap.aai.serialization.engines.QueryStyle; public class PserverDuplicateTest extends AAISetup { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(PserverDuplicateTest.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PserverDuplicateTest.class); private HttpTestUtil testUtil; diff --git a/aai-core/src/test/java/org/onap/aai/rest/PserverTest.java b/aai-core/src/test/java/org/onap/aai/rest/PserverTest.java index 8ede3c32..80ced5ea 100644 --- a/aai-core/src/test/java/org/onap/aai/rest/PserverTest.java +++ b/aai-core/src/test/java/org/onap/aai/rest/PserverTest.java @@ -20,20 +20,12 @@ package org.onap.aai.rest; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.jayway.jsonpath.JsonPath; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import javax.ws.rs.core.Response; - +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.janusgraph.core.JanusGraphTransaction; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -41,16 +33,31 @@ import org.junit.runners.Parameterized; import org.onap.aai.AAISetup; import org.onap.aai.HttpTestUtil; import org.onap.aai.PayloadUtil; -import org.onap.aai.introspection.*; +import org.onap.aai.dbmap.AAIGraph; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; import org.onap.aai.serialization.engines.QueryStyle; import org.skyscreamer.jsonassert.JSONAssert; import org.springframework.test.annotation.DirtiesContext; +import javax.ws.rs.core.Response; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static junit.framework.TestCase.fail; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + @RunWith(value = Parameterized.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class PserverTest extends AAISetup { - private static EELFLogger logger = EELFManager.getInstance().getLogger(PserverTest.class); + private static Logger logger = LoggerFactory.getLogger(PserverTest.class); private HttpTestUtil httpTestUtil; private Map<String, String> relationshipMap; @@ -69,6 +76,39 @@ public class PserverTest extends AAISetup { } @Test + public void testPutPserverCreateGetInXmlForFormats() throws Exception { + httpTestUtil = new HttpTestUtil(queryStyle, "application/xml"); + String pserverUri = "/aai/v12/cloud-infrastructure/pservers/pserver/test-pserver-xml"; + String cloudRegionUri = "/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/cloud-region-random1/cloud-region-random1-region"; + + Response response = httpTestUtil.doGet(pserverUri); + assertNotNull("Expected the response to be not null", response); + assertEquals("Expecting the pserver to be not found", 404, response.getStatus()); + + response = httpTestUtil.doPut(pserverUri, "{}"); + assertNotNull("Expected the response to be not null", response); + assertEquals("Expecting the pserver to be created", 201, response.getStatus()); + + response = httpTestUtil.doPut(cloudRegionUri, "{}"); + assertNotNull("Expected the response to be not null", response); + assertEquals("Expecting the cloud-region to be created", 201, response.getStatus()); + + relationshipMap.put("related-to", "pserver"); + relationshipMap.put("related-link", pserverUri); + + String pserverRelationshipPayload = PayloadUtil.getTemplatePayload("relationship.json", relationshipMap); + // Creates the relationship between cloud region and pserver + response = httpTestUtil.doPut(cloudRegionUri + "/relationship-list/relationship", pserverRelationshipPayload); + assertNotNull("Expected the response to be not null", response); + assertEquals("Expecting the cloud-region to pserver relationship to be created", 200, response.getStatus()); + + response = httpTestUtil.doGet(pserverUri , "0", "raw"); + assertNotNull("Expected the response to be not null", response); + assertEquals("Expecting the pserver to be created", 200, response.getStatus()); + assertThat(response.getEntity().toString(), containsString("<related-to><node><relationship-label>org.onap.relationships.inventory.LocatedIn</relationship-label><node-type>cloud-region</node-type>")); + } + + @Test public void testPutPServerCreateGetAndDeleteAndCreateRelationshipBetweenPserverAndCloudRegion() throws Exception { logger.info("Starting the pserver testPutServerCreateGetAndDelete"); @@ -148,4 +188,29 @@ public class PserverTest extends AAISetup { logger.info("Ending the pserver testPutServerCreateGetAndDelete"); } + @After + public void tearDown() { + + JanusGraphTransaction transaction = AAIGraph.getInstance().getGraph().newTransaction(); + boolean success = true; + + try { + + GraphTraversalSource g = transaction.traversal(); + + g.V().has("source-of-truth", "JUNIT").toList().forEach(v -> v.remove()); + + } catch (Exception ex) { + success = false; + logger.error("Unable to remove the vertexes", ex); + } finally { + if (success) { + transaction.commit(); + } else { + transaction.rollback(); + fail("Unable to teardown the graph"); + } + } + + } } diff --git a/aai-core/src/test/java/org/onap/aai/rest/RestHandlerTest.java b/aai-core/src/test/java/org/onap/aai/rest/RestHandlerTest.java index cba81d73..494d7e4e 100644 --- a/aai-core/src/test/java/org/onap/aai/rest/RestHandlerTest.java +++ b/aai-core/src/test/java/org/onap/aai/rest/RestHandlerTest.java @@ -35,7 +35,7 @@ public class RestHandlerTest { RestHandlerService secondInstance = RestHandlerService.getInstance(); assertNotNull(firstInstance); assertNotNull(secondInstance); - assertTrue(firstInstance == secondInstance); + assertSame(firstInstance, secondInstance); } } diff --git a/aai-core/src/test/java/org/onap/aai/rest/VnfcRelationshipIssueTest.java b/aai-core/src/test/java/org/onap/aai/rest/VnfcRelationshipIssueTest.java new file mode 100644 index 00000000..ae611717 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/rest/VnfcRelationshipIssueTest.java @@ -0,0 +1,111 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.rest; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.janusgraph.core.JanusGraphTransaction; +import org.junit.*; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.onap.aai.AAISetup; +import org.onap.aai.HttpTestUtil; +import org.onap.aai.PayloadUtil; +import org.onap.aai.dbmap.AAIGraph; +import org.onap.aai.serialization.engines.QueryStyle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.test.context.junit4.rules.SpringClassRule; +import org.springframework.test.context.junit4.rules.SpringMethodRule; + +import javax.ws.rs.core.Response; +import java.util.Arrays; +import java.util.Collection; + +import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertEquals; + +@RunWith(value = Parameterized.class) +public class VnfcRelationshipIssueTest extends AAISetup { + + private static final Logger LOGGER = LoggerFactory.getLogger(VnfcRelationshipIssueTest.class); + private HttpTestUtil httpTestUtil; + + @ClassRule + public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule(); + + @Rule + public final SpringMethodRule springMethodRule = new SpringMethodRule(); + + @Parameterized.Parameter(value = 0) + public QueryStyle queryStyle; + + @Parameterized.Parameters(name = "QueryStyle.{0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] {{QueryStyle.TRAVERSAL}, {QueryStyle.TRAVERSAL_URI}}); + } + + @Before + public void setUp() { + httpTestUtil = new HttpTestUtil(queryStyle); + } + + @Test + public void testCreateVnfWithVfModuleAndCreateVnfcRelatedToVfModule() throws Exception { + + String genericVnfUri = "/aai/v14/network/generic-vnfs/generic-vnf/test-vnf11"; + String genericVnfPayload = PayloadUtil.getResourcePayload("generic-vnf-with-vf-module.json"); + + Response response = httpTestUtil.doPut(genericVnfUri, genericVnfPayload); + assertEquals("Expected the generic vnf to be created", 201, response.getStatus()); + + String vnfcUri = "/aai/v14/network/vnfcs/vnfc/test-vnfc11"; + String vnfcPaylaod = PayloadUtil.getResourcePayload("vnfc-related-to-vf-module.json"); + + response = httpTestUtil.doPut(vnfcUri, vnfcPaylaod); + assertEquals("Expected the generic vnf to be created", 201, response.getStatus()); + } + + @After + public void tearDown() { + + JanusGraphTransaction transaction = AAIGraph.getInstance().getGraph().newTransaction(); + boolean success = true; + + try { + + GraphTraversalSource g = transaction.traversal(); + + g.V().has("source-of-truth", "JUNIT").toList().forEach(v -> v.remove()); + + } catch (Exception ex) { + success = false; + LOGGER.error("Unable to remove the vertexes", ex); + } finally { + if (success) { + transaction.commit(); + } else { + transaction.rollback(); + fail("Unable to teardown the graph"); + } + } + + } +} diff --git a/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java b/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java index c01d270e..95220b1f 100644 --- a/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java +++ b/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java @@ -20,23 +20,8 @@ package org.onap.aai.rest.db; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.when; - import com.google.gson.JsonObject; import com.google.gson.JsonParser; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.*; - -import javax.ws.rs.core.*; - import org.javatuples.Pair; import org.junit.Before; import org.junit.FixMethodOrder; @@ -47,11 +32,9 @@ import org.junit.runners.Parameterized; import org.mockito.Mockito; import org.onap.aai.AAISetup; import org.onap.aai.db.props.AAIProperties; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; -import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.introspection.ModelType; import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.rest.ueb.UEBNotification; @@ -60,6 +43,19 @@ import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.util.AAIConfig; +import javax.ws.rs.core.*; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.*; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; + @RunWith(value = Parameterized.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class HttpEntryTest extends AAISetup { @@ -139,7 +135,7 @@ public class HttpEntryTest extends AAISetup { if (uri.endsWith("relationship")) { objType = "relationship"; } - Introspector obj = null; + Introspector obj; if (method.equals(HttpMethod.GET)) { obj = loader.introspectorFromName(objType); } else { @@ -163,8 +159,7 @@ public class HttpEntryTest extends AAISetup { /* * TODO do the same with uri */ - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -178,8 +173,7 @@ public class HttpEntryTest extends AAISetup { @Test public void test2PutOnPserverNoPInterface() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -193,8 +187,7 @@ public class HttpEntryTest extends AAISetup { @Test public void test3PutOnPInterface() { try { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -212,14 +205,11 @@ public class HttpEntryTest extends AAISetup { @Test public void test4GetOnPserver() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); - URI uriObject = UriBuilder.fromPath("/cloud-infrastructure/pservers/pserver/junit-test1").build(); - String uri = "/cloud-infrastructure/pservers/pserver/junit-test1"; String content = "{\"hostname\":\"junit-test1\", \"equip-type\":\"junit-equip-type\"}"; Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, content); @@ -230,8 +220,7 @@ public class HttpEntryTest extends AAISetup { @Test public void test5MergePatchOnPserver() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -246,8 +235,7 @@ public class HttpEntryTest extends AAISetup { private int doDelete(String resourceVersion, String uri, String nodeType) throws UnsupportedEncodingException, AAIException { queryParameters.add("resource-version", resourceVersion); - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -274,12 +262,10 @@ public class HttpEntryTest extends AAISetup { @Test public void test6DeleteOnPserver() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); - URI uriObject = UriBuilder.fromPath("/cloud-infrastructure/pservers/pserver/junit-test1").build(); String uri = "/cloud-infrastructure/pservers/pserver/junit-test1"; String content = ""; Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, content); @@ -297,8 +283,7 @@ public class HttpEntryTest extends AAISetup { @Test public void test7DeleteOnPserverNoPinterface() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); // HttpEntry httpEntry = new HttpEntry(Version.getLatest(), ModelType.MOXY, queryStyle, type); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -320,8 +305,7 @@ public class HttpEntryTest extends AAISetup { @Test public void test8FailedGetOnPserver() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); // HttpEntry httpEntry = new HttpEntry(Version.getLatest(), ModelType.MOXY, queryStyle, type); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -337,8 +321,7 @@ public class HttpEntryTest extends AAISetup { @Test public void putEdgeTest() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); // HttpEntry httpEntry = new HttpEntry(Version.getLatest(), ModelType.MOXY, queryStyle, type); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -368,8 +351,7 @@ public class HttpEntryTest extends AAISetup { Loader ld = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); UEBNotification uebNotification = Mockito.spy(new UEBNotification(ld, loaderFactory, schemaVersions)); - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type, uebNotification); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), uebNotification); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -390,31 +372,32 @@ public class HttpEntryTest extends AAISetup { doNothing().when(uebNotification).triggerEvents(); Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT_EDGE, uri, content); - response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.DELETE_EDGE, uri, content); - dbEngine.rollback(); - assertEquals("Expected the pserver relationship to be deleted", 204, response.getStatus()); - assertEquals("Two notifications", 2, uebNotification.getEvents().size()); + assertEquals("Expected the pserver relationship to be deleted", 200, response.getStatus()); + assertEquals("Two notifications", 2, uebNotification.getEvents().size()); assertEquals("Notification generated for PUT edge", "UPDATE", uebNotification.getEvents().get(0).getEventHeader().getValue("action").toString()); assertThat("Event body for the edge create has the related to", uebNotification.getEvents().get(0).getObj().marshal(false), containsString("cloud-infrastructure/pservers/pserver/junit-edge-test-pserver")); + response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.DELETE_EDGE, uri, content); + assertEquals("Expected the pserver relationship to be deleted", 204, response.getStatus()); + assertEquals("Two notifications", 2, uebNotification.getEvents().size()); assertEquals("Notification generated for DELETE edge", "UPDATE", - uebNotification.getEvents().get(1).getEventHeader().getValue("action").toString()); + uebNotification.getEvents().get(0).getEventHeader().getValue("action").toString()); assertThat("Event body for the edge delete does not have the related to", - uebNotification.getEvents().get(1).getObj().marshal(false), + uebNotification.getEvents().get(0).getObj().marshal(false), not(containsString("cloud-infrastructure/pservers/pserver/junit-edge-test-pserver"))); + dbEngine.rollback(); } @Test public void putEdgeWrongLabelTest() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); // HttpEntry httpEntry = new HttpEntry(Version.getLatest(), ModelType.MOXY, queryStyle, type); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -449,8 +432,7 @@ public class HttpEntryTest extends AAISetup { final String testName = new Object() {}.getClass().getEnclosingMethod().getName(); - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); // HttpEntry httpEntry = new HttpEntry(schemaVersions.getDefaultVersion(), ModelType.MOXY, QueryStyle.TRAVERSAL, // type); Loader loader = traversalHttpEntry.getLoader(); @@ -496,9 +478,7 @@ public class HttpEntryTest extends AAISetup { final String testName = new Object() {}.getClass().getEnclosingMethod().getName(); - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); - // HttpEntry httpEntry = new HttpEntry(Version.getLatest(), ModelType.MOXY, QueryStyle.TRAVERSAL, type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -532,10 +512,7 @@ public class HttpEntryTest extends AAISetup { @Test public void testSetGetPaginationMethods() { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); - // HttpEntry httpEntry = new HttpEntry(schemaVersions.getDefaultVersion(), ModelType.MOXY, QueryStyle.TRAVERSAL, - // type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); traversalHttpEntry.setPaginationBucket(10); traversalHttpEntry.setPaginationIndex(1); traversalHttpEntry.setTotalsForPaging(101, traversalHttpEntry.getPaginationBucket()); @@ -549,9 +526,7 @@ public class HttpEntryTest extends AAISetup { @Test public void relatedToTest() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); - // HttpEntry httpEntry = new HttpEntry(schemaVersions.getDefaultVersion(), ModelType.MOXY, queryStyle, type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); @@ -585,14 +560,12 @@ public class HttpEntryTest extends AAISetup { } @Test - public void setDepthTest() throws UnsupportedEncodingException, AAIException { + public void setDepthTest() throws AAIException { System.setProperty("AJSC_HOME", "."); System.setProperty("BUNDLECONFIG_DIR", "src/main/test/resources"); String depthParam = AAIConfig.get("aai.rest.getall.depthparam"); - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); - // HttpEntry httpEntry = new HttpEntry(Version.getLatest(), ModelType.MOXY, QueryStyle.TRAVERSAL, type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); int depth = traversalHttpEntry.setDepth(null, depthParam); assertEquals(AAIProperties.MAXIMUM_DEPTH.intValue(), depth); } @@ -600,9 +573,7 @@ public class HttpEntryTest extends AAISetup { @Test public void getAbstractTest() throws UnsupportedEncodingException, AAIException { - DBConnectionType type = DBConnectionType.REALTIME; - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); - // HttpEntry httpEntry = new HttpEntry(Version.getLatest(), ModelType.MOXY, queryStyle, type); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); Loader loader = traversalHttpEntry.getLoader(); TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); diff --git a/aai-core/src/test/java/org/onap/aai/rest/ueb/UEBNotificationTest.java b/aai-core/src/test/java/org/onap/aai/rest/ueb/UEBNotificationTest.java new file mode 100644 index 00000000..58b96e49 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/rest/ueb/UEBNotificationTest.java @@ -0,0 +1,112 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.rest.ueb; + +import org.junit.Before; +import org.junit.Test; +import org.onap.aai.AAISetup; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.serialization.db.EdgeSerializer; +import org.onap.aai.serialization.engines.QueryStyle; +import org.onap.aai.setup.SchemaVersion; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; + +import javax.ws.rs.core.Response; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.UUID; + +import static org.junit.Assert.assertEquals; + +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class UEBNotificationTest extends AAISetup { + + public static final String BASE_PATH = "/aai"; + @Autowired + protected EdgeSerializer edgeSer; + @Autowired + protected EdgeIngestor ei; + + private SchemaVersion version; + private final ModelType introspectorFactoryType = ModelType.MOXY; + private Loader loader; + + public QueryStyle queryStyle = QueryStyle.TRAVERSAL_URI; + + + @Before + public void setup() throws Exception { + version = schemaVersions.getDefaultVersion(); + loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); + } + + @Test + public void verifyUriNoIssues() throws AAIException, URISyntaxException, UnsupportedEncodingException { + + Introspector pserver = loader.introspectorFromName("pserver"); + pserver.setValue("hostname", "hn"); + URI uri = new URI("/cloud-infrastructure/pservers/pserver/hn"); + UEBNotification uebNotification = new UEBNotification(loader, loaderFactory, schemaVersions); + uebNotification.createNotificationEvent( + UUID.randomUUID().toString(), + "JUNIT-SOT", + Response.Status.CREATED, + uri, + pserver, + new HashMap<>(), + BASE_PATH); + + assertEquals("One event created", 1, uebNotification.getEvents().size()); + assertEquals( + "Uri is correct", + BASE_PATH + "/" + schemaVersions.getDefaultVersion() + "/cloud-infrastructure/pservers/pserver/hn", + uebNotification.getEvents().get(0).getEventHeader().getValue("entity-link").toString()); + } + + @Test + public void verifyUriWithBaseAndUri() throws AAIException, URISyntaxException, UnsupportedEncodingException { + + Introspector pserver = loader.introspectorFromName("pserver"); + pserver.setValue("hostname", "hn"); + URI uri = new URI(BASE_PATH + "/v12/cloud-infrastructure/pservers/pserver/hn"); + UEBNotification uebNotification = new UEBNotification(loader, loaderFactory, schemaVersions); + uebNotification.createNotificationEvent( + UUID.randomUUID().toString(), + "JUNIT-SOT", + Response.Status.CREATED, + uri, + pserver, + new HashMap<>(), BASE_PATH); + + assertEquals("One event created", 1, uebNotification.getEvents().size()); + assertEquals( + "Uri is correct", + BASE_PATH + "/" + schemaVersions.getDefaultVersion() + "/cloud-infrastructure/pservers/pserver/hn", + uebNotification.getEvents().get(0).getEventHeader().getValue("entity-link").toString()); + } +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/DbAliasTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/DbAliasTest.java index 944a4067..454aa218 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/db/DbAliasTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/DbAliasTest.java @@ -20,20 +20,6 @@ package org.onap.aai.serialization.db; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import java.io.UnsupportedEncodingException; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; @@ -44,11 +30,12 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import org.onap.aai.AAISetup; import org.onap.aai.DataLinkSetup; -import org.onap.aai.dbmap.DBConnectionType; +import org.onap.aai.db.props.AAIProperties; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.introspection.*; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.schema.enums.PropertyMetadata; import org.onap.aai.serialization.engines.JanusGraphDBEngine; @@ -57,6 +44,18 @@ import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.setup.SchemaVersion; import org.springframework.test.annotation.DirtiesContext; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + @RunWith(value = Parameterized.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class DbAliasTest extends DataLinkSetup { @@ -65,11 +64,10 @@ public class DbAliasTest extends DataLinkSetup { private SchemaVersion version; private final ModelType introspectorFactoryType = ModelType.MOXY; - private final DBConnectionType type = DBConnectionType.REALTIME; private Loader loader; private TransactionalGraphEngine dbEngine; - @Parameterized.Parameter(value = 0) + @Parameterized.Parameter public QueryStyle queryStyle; @Parameterized.Parameters(name = "QueryStyle.{0}") @@ -78,11 +76,11 @@ public class DbAliasTest extends DataLinkSetup { } @Before - public void setup() throws Exception { + public void setup() { version = schemaVersions.getDepthVersion(); graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); - dbEngine = new JanusGraphDBEngine(queryStyle, type, loader); + dbEngine = new JanusGraphDBEngine(queryStyle, loader); } @After @@ -92,9 +90,7 @@ public class DbAliasTest extends DataLinkSetup { } @Test - public void checkOnWrite() throws AAIException, UnsupportedEncodingException, URISyntaxException, SecurityException, - IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, - NoSuchMethodException, InterruptedException { + public void checkOnWrite() throws AAIException, UnsupportedEncodingException, URISyntaxException, SecurityException, IllegalArgumentException { final String property = "persona-model-customization-id"; String dbPropertyName = property; TransactionalGraphEngine spy = spy(this.dbEngine); @@ -108,6 +104,13 @@ public class DbAliasTest extends DataLinkSetup { spy.getQueryBuilder().createQueryFromURI(new URI("network/generic-vnfs/generic-vnf/key1")); Introspector obj = loader.introspectorFromName("generic-vnf"); Vertex v = g.addVertex(); + v.property("aai-uri", "abc"); + v.property("aai-uuid", "b"); + v.property(AAIProperties.CREATED_TS, 123L); + v.property(AAIProperties.SOURCE_OF_TRUTH, "sot"); + v.property(AAIProperties.RESOURCE_VERSION, "123"); + v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot"); + v.property(AAIProperties.LAST_MOD_TS, 123L); Object id = v.id(); obj.setValue("vnf-id", "key1"); obj.setValue(property, "hello"); @@ -126,14 +129,12 @@ public class DbAliasTest extends DataLinkSetup { } @Test - public void checkOnRead() throws AAIException, UnsupportedEncodingException, URISyntaxException, SecurityException, - IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, - NoSuchMethodException, InterruptedException, MalformedURLException { + public void checkOnRead() throws AAIException, UnsupportedEncodingException, SecurityException, IllegalArgumentException { final String property = "persona-model-customization-id"; TransactionalGraphEngine spy = spy(dbEngine); TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin()); - Vertex v = graph.traversal().addV("vnf-id", "key1", "model-customization-id", "hello").next(); + Vertex v = graph.traversal().addV().property("vnf-id", "key1").property("model-customization-id", "hello").next(); graph.tx().commit(); Graph g = graph.newTransaction(); GraphTraversalSource traversal = g.traversal(); diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerDeltasTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerDeltasTest.java new file mode 100644 index 00000000..de8f2224 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerDeltasTest.java @@ -0,0 +1,764 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.db; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraphFactory; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.onap.aai.AAISetup; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.serialization.engines.JanusGraphDBEngine; +import org.onap.aai.serialization.engines.QueryStyle; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.setup.SchemaVersion; +import org.onap.aai.util.delta.DeltaAction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.TestPropertySource; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.*; + +@RunWith(value = Parameterized.class) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +@TestPropertySource(properties = { + "delta.events.enabled=true", + }) +public class DbSerializerDeltasTest extends AAISetup { + + // to use, set thrown.expect to whatever your test needs + // this line establishes default of expecting no exception to be thrown + @Rule + public ExpectedException thrown = ExpectedException.none(); + + protected static Graph graph; + + @Autowired + protected EdgeSerializer edgeSer; + @Autowired + protected EdgeIngestor ei; + + private SchemaVersion version; + private final ModelType introspectorFactoryType = ModelType.MOXY; + private Loader loader; + private TransactionalGraphEngine dbEngine; + private TransactionalGraphEngine engine; // for tests that aren't mocking the engine + + @Parameterized.Parameter(value = 0) + public QueryStyle queryStyle; + + @Parameterized.Parameters(name = "QueryStyle.{0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] {{QueryStyle.TRAVERSAL}, {QueryStyle.TRAVERSAL_URI}}); + } + + @BeforeClass + public static void init() throws Exception { + graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + + } + + @Before + public void setup() throws Exception { + // createGraph(); + version = schemaVersions.getDefaultVersion(); + loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); + dbEngine = new JanusGraphDBEngine(queryStyle, loader); + engine = new JanusGraphDBEngine(queryStyle, loader); + } + + @Test + public void createTopLevelThenUpdateTest() throws AAIException, UnsupportedEncodingException, URISyntaxException { + engine.startTransaction(); + + DBSerializer dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST", AAIProperties.MINIMUM_DEPTH); + Introspector gvnf = loader.introspectorFromName("generic-vnf"); + Vertex gvnfVert = dbserLocal.createNewVertex(gvnf); + QueryParser uriQuery = + dbEngine.getQueryBuilder().createQueryFromURI(new URI("/network/generic-vnfs/generic-vnf/myvnf")); + + gvnf.setValue("vnf-id", "myvnf"); + gvnf.setValue("vnf-type", "typo"); + dbserLocal.serializeToDb(gvnf, gvnfVert, uriQuery, "generic-vnf", gvnf.marshal(false)); + assertTrue("Original created vertex exists", engine.tx().traversal().V() + .has("aai-node-type", "generic-vnf") + .has("vnf-id", "myvnf") + .has("vnf-type", "typo") + .hasNext()); + + + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get("/network/generic-vnfs/generic-vnf/myvnf").getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get("/network/generic-vnfs/generic-vnf/myvnf").getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(5L, dbserLocal.getObjectDeltas().get("/network/generic-vnfs/generic-vnf/myvnf").getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + gvnf = dbserLocal.getLatestVersionView(gvnfVert); + gvnf.setValue("vnf-type", "new-typo"); + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST", AAIProperties.MINIMUM_DEPTH); + dbserLocal.serializeToDb(gvnf, gvnfVert, uriQuery, "generic-vnf", gvnf.marshal(false)); + assertTrue("Vertex is updated", engine.tx().traversal().V() + .has("aai-node-type", "generic-vnf") + .has("vnf-id", "myvnf") + .has("vnf-type", "new-typo") + .hasNext()); + + + assertEquals(DeltaAction.UPDATE, dbserLocal.getObjectDeltas().get("/network/generic-vnfs/generic-vnf/myvnf").getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get("/network/generic-vnfs/generic-vnf/myvnf").getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(4L, dbserLocal.getObjectDeltas().get("/network/generic-vnfs/generic-vnf/myvnf").getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.UPDATE)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + } + + @Test + public void createTopLevelThenCreateChildTest() throws AAIException, UnsupportedEncodingException, URISyntaxException { + engine.startTransaction(); + + DBSerializer dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST", AAIProperties.MINIMUM_DEPTH); + Introspector gvnf = loader.introspectorFromName("generic-vnf"); + Vertex gvnfVert = dbserLocal.createNewVertex(gvnf); + final String vnfUri = "/network/generic-vnfs/generic-vnf/myvnf"; + QueryParser uriQuery = + dbEngine.getQueryBuilder().createQueryFromURI(new URI(vnfUri)); + + gvnf.setValue("vnf-id", "myvnf"); + gvnf.setValue("vnf-type", "typo"); + dbserLocal.serializeToDb(gvnf, gvnfVert, uriQuery, "generic-vnf", gvnf.marshal(false)); + assertTrue("Original created vertex exists", engine.tx().traversal().V() + .has("aai-node-type", "generic-vnf") + .has("vnf-id", "myvnf") + .has("vnf-type", "typo") + .hasNext()); + + + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(vnfUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(vnfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(5L, dbserLocal.getObjectDeltas().get(vnfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST", AAIProperties.MINIMUM_DEPTH); + Introspector vf = loader.introspectorFromName("vf-module"); + Vertex vfVertex = dbserLocal.createNewVertex(vf); + final String vfUri = "/network/generic-vnfs/generic-vnf/myvnf/vf-modules/vf-module/myvf"; + uriQuery = engine.getQueryBuilder(gvnfVert).createQueryFromURI(new URI(vfUri)); + + vf.setValue("vf-module-id", "myvf"); + dbserLocal.serializeToDb(vf, vfVertex, uriQuery, "vf-module", vf.marshal(false)); + assertTrue("Vertex is creted", engine.tx().traversal().V() + .has("aai-node-type", "vf-module") + .has("vf-module-id", "myvf") + .hasNext()); + assertTrue("Vf module has edge to gvnf", engine.tx().traversal().V() + .has("aai-node-type", "vf-module") + .has("vf-module-id", "myvf") + .both() + .has("aai-node-type", "generic-vnf") + .has("vnf-id", "myvnf") + .hasNext()); + + + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(vfUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(vfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(vfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + } + + @Test + public void createTopWithChildThenDeleteTopTest() throws AAIException, UnsupportedEncodingException, URISyntaxException { + engine.startTransaction(); + + DBSerializer dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST", AAIProperties.MINIMUM_DEPTH); + Introspector gvnf = loader.introspectorFromName("generic-vnf"); + Vertex gvnfVert = dbserLocal.createNewVertex(gvnf); + final String vnfUri = "/network/generic-vnfs/generic-vnf/myvnf"; + QueryParser uriQuery = + dbEngine.getQueryBuilder().createQueryFromURI(new URI(vnfUri)); + + gvnf.setValue("vnf-id", "myvnf"); + gvnf.setValue("vnf-type", "typo"); + + Introspector vf = loader.introspectorFromName("vf-module"); + vf.setValue("vf-module-id", "myvf"); + final String vfUri = "/network/generic-vnfs/generic-vnf/myvnf/vf-modules/vf-module/myvf"; + + Introspector vfs = loader.introspectorFromName("vf-modules"); + vfs.setValue("vf-module", Collections.singletonList(vf.getUnderlyingObject())); + gvnf.setValue("vf-modules", vfs.getUnderlyingObject()); + + dbserLocal.serializeToDb(gvnf, gvnfVert, uriQuery, "generic-vnf", gvnf.marshal(false)); + + Gson gson = new GsonBuilder().create(); + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + + assertTrue("Original created vertex exists", engine.tx().traversal().V() + .has("aai-node-type", "generic-vnf") + .has("vnf-id", "myvnf") + .has("vnf-type", "typo") + .hasNext()); + assertTrue("Vertex is creted", engine.tx().traversal().V() + .has("aai-node-type", "vf-module") + .has("vf-module-id", "myvf") + .hasNext()); + assertTrue("Vf module has edge to gvnf", engine.tx().traversal().V() + .has("aai-node-type", "vf-module") + .has("vf-module-id", "myvf") + .both() + .has("aai-node-type", "generic-vnf") + .has("vnf-id", "myvnf") + .hasNext()); + + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(vnfUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(vnfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(5L, dbserLocal.getObjectDeltas().get(vnfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(vfUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(vfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(vfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + assertEquals(1L, dbserLocal.getObjectDeltas().get(vfUri).getRelationshipDeltas().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE_REL)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST", AAIProperties.MINIMUM_DEPTH); + gvnf = dbserLocal.getLatestVersionView(gvnfVert); + String rv = gvnf.getValue(AAIProperties.RESOURCE_VERSION); + dbserLocal.delete(engine.tx().traversal().V(gvnfVert).next(), rv, true); + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + + assertFalse("generic-vnf no longer exists", engine.tx().traversal().V() + .has("aai-node-type", "generic-vnf") + .hasNext()); + assertFalse("vf-module no longer exists", engine.tx().traversal().V() + .has("aai-node-type", "vf-module") + .hasNext()); + + assertEquals(DeltaAction.DELETE, dbserLocal.getObjectDeltas().get(vnfUri).getAction()); + assertEquals(12L, dbserLocal.getObjectDeltas().get(vnfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.DELETE)).count());assertEquals(DeltaAction.DELETE, dbserLocal.getObjectDeltas().get(vfUri).getAction()); + assertEquals(11L, dbserLocal.getObjectDeltas().get(vfUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.DELETE)).count()); + } + + + + @Test + public void createComplexPserverWithRelDeleteRel() throws AAIException, UnsupportedEncodingException, URISyntaxException { + engine.startTransaction(); + + DBSerializer dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST", AAIProperties.MINIMUM_DEPTH); + Introspector complex = loader.introspectorFromName("complex"); + Vertex complexV = dbserLocal.createNewVertex(complex); + final String complexUri = "/cloud-infrastructure/complexes/complex/c-id"; + QueryParser uriQuery = + dbEngine.getQueryBuilder().createQueryFromURI(new URI(complexUri)); + + complex.setValue("physical-location-id", "c-id"); + complex.setValue("physical-location-type", "type"); + complex.setValue("street1", "streetA"); + complex.setValue("city", "cityA"); + complex.setValue("postal-code", "11111"); + complex.setValue("country", "abc"); + complex.setValue("region", "ef"); + dbserLocal.serializeToDb(complex, complexV, uriQuery, "complex", complex.marshal(false)); + assertTrue("Complex created", engine.tx().traversal().V() + .has("aai-node-type", "complex") + .has("physical-location-id", "c-id") + .hasNext()); + + + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(complexUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(complexUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(10L, dbserLocal.getObjectDeltas().get(complexUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST", AAIProperties.MINIMUM_DEPTH); + Introspector pserver = loader.introspectorFromName("pserver"); + Vertex pserverV = dbserLocal.createNewVertex(pserver); + final String pserverUri = "/cloud-infrastructure/pservers/pserver/ps"; + uriQuery = + dbEngine.getQueryBuilder().createQueryFromURI(new URI(pserverUri)); + + Introspector relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-to", "complex"); + relationship.setValue("related-link", complexUri); + Introspector relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", Collections.singletonList(relationship.getUnderlyingObject())); + + pserver.setValue("relationship-list", relationshipList.getUnderlyingObject()); + pserver.setValue("hostname", "ps"); + + System.out.println(pserver.marshal(true)); + + dbserLocal.serializeToDb(pserver, pserverV, uriQuery, "pserver", pserver.marshal(false)); + assertTrue("Pserver created", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps") + .hasNext()); + assertTrue("Pserver has edge to complex", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps") + .bothE() + .otherV() + .has("aai-node-type", "complex") + .hasNext()); + + + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(pserverUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(pserverUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(pserverUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + assertEquals(1L, dbserLocal.getObjectDeltas().get(pserverUri).getRelationshipDeltas().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE_REL)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST", AAIProperties.MINIMUM_DEPTH); + dbserLocal.touchStandardVertexProperties(pserverV, false); + dbserLocal.deleteEdge(relationship, pserverV); + assertFalse("Pserver no longer has edge to complex", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps") + .bothE() + .otherV() + .has("aai-node-type", "complex") + .hasNext()); + + + assertEquals(DeltaAction.UPDATE, dbserLocal.getObjectDeltas().get(pserverUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(pserverUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(3L, dbserLocal.getObjectDeltas().get(pserverUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.UPDATE)).count()); + assertEquals(1L, dbserLocal.getObjectDeltas().get(pserverUri).getRelationshipDeltas().stream().filter(d -> d.getAction().equals(DeltaAction.DELETE_REL)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + } + + @Test + public void createComplexPserverWithRelUpdatePserverToDeleteRelAddPinterfaceThenDeleteComplex() throws AAIException, UnsupportedEncodingException, URISyntaxException { + engine.startTransaction(); + + Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) + .create(); + + DBSerializer dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "create-complex", AAIProperties.MINIMUM_DEPTH); + Introspector complex = loader.introspectorFromName("complex"); + Vertex complexV = dbserLocal.createNewVertex(complex); + final String complexUri = "/cloud-infrastructure/complexes/complex/c-id-b"; + QueryParser uriQuery = + dbEngine.getQueryBuilder().createQueryFromURI(new URI(complexUri)); + + complex.setValue("physical-location-id", "c-id-b"); + complex.setValue("physical-location-type", "type"); + complex.setValue("street1", "streetA"); + complex.setValue("city", "cityA"); + complex.setValue("postal-code", "11111"); + complex.setValue("country", "abc"); + complex.setValue("region", "ef"); + dbserLocal.serializeToDb(complex, complexV, uriQuery, "complex", complex.marshal(false)); + + System.out.println("Create Complex"); + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + + assertTrue("Complex created", engine.tx().traversal().V() + .has("aai-node-type", "complex") + .has("physical-location-id", "c-id-b") + .hasNext()); + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(complexUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(complexUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(10L, dbserLocal.getObjectDeltas().get(complexUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "create-pserver", AAIProperties.MINIMUM_DEPTH); + Introspector pserver = loader.introspectorFromName("pserver"); + Vertex pserverV = dbserLocal.createNewVertex(pserver); + final String pserverUri = "/cloud-infrastructure/pservers/pserver/ps-b"; + uriQuery = + dbEngine.getQueryBuilder().createQueryFromURI(new URI(pserverUri)); + + Introspector relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-to", "complex"); + relationship.setValue("related-link", complexUri); + Introspector relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", Collections.singletonList(relationship.getUnderlyingObject())); + + pserver.setValue("relationship-list", relationshipList.getUnderlyingObject()); + pserver.setValue("hostname", "ps-b"); + pserver.setValue("number-of-cpus", 20); + + Introspector pint = loader.introspectorFromName("p-interface"); + pint.setValue("interface-name", "pint-1"); + final String pintUri = pserverUri + "/p-interfaces/p-interface/pint-1"; + + Introspector pints = loader.introspectorFromName("p-interfaces"); + pints.setValue("p-interface", Collections.singletonList(pint.getUnderlyingObject())); + pserver.setValue("p-interfaces", pints.getUnderlyingObject()); + + dbserLocal.serializeToDb(pserver, pserverV, uriQuery, "pserver", pserver.marshal(false)); + + System.out.println("Create Pserver with pinterface and relationship to complex "); + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + + assertTrue("Pserver created", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .hasNext()); + assertTrue("Pserver has edge to complex", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .bothE() + .otherV() + .has("aai-node-type", "complex") + .hasNext()); + assertTrue("Pserver has edge to pinterface", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .bothE() + .otherV() + .has("aai-node-type", "p-interface") + .hasNext()); + + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(pserverUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(pserverUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(5L, dbserLocal.getObjectDeltas().get(pserverUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + assertEquals(1L, dbserLocal.getObjectDeltas().get(pserverUri).getRelationshipDeltas().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE_REL)).count()); + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(pintUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(pintUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(pintUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + assertEquals(1L, dbserLocal.getObjectDeltas().get(pintUri).getRelationshipDeltas().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE_REL)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "update-pserver", AAIProperties.MINIMUM_DEPTH); + pserver = dbserLocal.getLatestVersionView(pserverV); + relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", Collections.emptyList()); + pserver.setValue("relationship-list", relationshipList.getUnderlyingObject()); + pserver.setValue("equip-type", "server-a"); + pserver.setValue("number-of-cpus", 99); + + dbserLocal.serializeToDb(pserver, pserverV, uriQuery, "pserver", pserver.marshal(false)); + + System.out.println("Update pserver removing relationship to complex"); + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + + assertFalse("Pserver no longer has edge to complex", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .bothE() + .otherV() + .has("aai-node-type", "complex") + .hasNext()); + + assertEquals(DeltaAction.UPDATE, dbserLocal.getObjectDeltas().get(pserverUri).getAction()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(pserverUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(4L, dbserLocal.getObjectDeltas().get(pserverUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.UPDATE)).count()); + assertEquals(1L, dbserLocal.getObjectDeltas().get(pserverUri).getRelationshipDeltas().stream().filter(d -> d.getAction().equals(DeltaAction.DELETE_REL)).count()); + assertFalse(dbserLocal.getObjectDeltas().containsKey(pintUri)); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "delete-pserver", AAIProperties.MINIMUM_DEPTH); + pserver = dbserLocal.getLatestVersionView(pserverV); + String rv = pserver.getValue(AAIProperties.RESOURCE_VERSION); + dbserLocal.delete(engine.tx().traversal().V(pserverV).next(), rv, true); + + System.out.println("Delete pserver"); + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + + assertFalse("pserver no longer exists", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .hasNext()); + + assertEquals(DeltaAction.DELETE, dbserLocal.getObjectDeltas().get(pserverUri).getAction()); + assertEquals(12L, dbserLocal.getObjectDeltas().get(pserverUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.DELETE)).count()); + assertEquals(DeltaAction.DELETE, dbserLocal.getObjectDeltas().get(pintUri).getAction()); + assertEquals(10L, dbserLocal.getObjectDeltas().get(pintUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.DELETE)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + } + + + // /network/ipsec-configurations/ipsec-configuration/{ipsec-configuration-id}/vig-servers/vig-server/{vig-address-type} + // ipaddress-v4-vig + @Test + public void createNodeWithListTest() throws AAIException, UnsupportedEncodingException, URISyntaxException { + Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) + .create(); + + engine.startTransaction(); + + /* + * Create the parent ipsec-configuration + */ + DBSerializer dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "create-ipsec", AAIProperties.MINIMUM_DEPTH); + Introspector ipsec = loader.introspectorFromName("ipsec-configuration"); + Vertex ipsecVert = dbserLocal.createNewVertex(ipsec); + final String ipsecUri = "/network/ipsec-configurations/ipsec-configuration/ipsec"; + QueryParser uriQuery = + dbEngine.getQueryBuilder().createQueryFromURI(new URI(ipsecUri)); + + ipsec.setValue("ipsec-configuration-id", "ipsec"); + dbserLocal.serializeToDb(ipsec, ipsecVert, uriQuery, "generic-vnf", ipsec.marshal(false)); + assertTrue("Original created vertex exists", engine.tx().traversal().V() + .has("aai-node-type", "ipsec-configuration") + .has("ipsec-configuration-id", "ipsec") + .hasNext()); + + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(ipsecUri).getAction()); + assertEquals(4L, + dbserLocal.getObjectDeltas().get(ipsecUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(4L, + dbserLocal.getObjectDeltas().get(ipsecUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + /* + * Create child vig-server with list property vig-address-type + */ + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "create-child-vig-server", AAIProperties.MINIMUM_DEPTH); + Introspector vig = loader.introspectorFromName("vig-server"); + Vertex vigVertex = dbserLocal.createNewVertex(vig); + final String vigUri = "/network/ipsec-configurations/ipsec-configuration/ipsec/vig-servers/vig-server/vig"; + uriQuery = engine.getQueryBuilder(ipsecVert).createQueryFromURI(new URI(vigUri)); + + vig.setValue("vig-address-type", "vig"); + List<String> list = new ArrayList<>(); + list.add("address-1"); + list.add("address-2"); + vig.setValue("ipaddress-v4-vig", list); + dbserLocal.serializeToDb(vig, vigVertex, uriQuery, "vf-module", vig.marshal(false)); + assertTrue("Vertex is creted", engine.tx().traversal().V() + .has("aai-node-type", "vig-server") + .has("vig-address-type", "vig") + .hasNext()); + assertTrue("Vf module has edge to gvnf", engine.tx().traversal().V() + .has("aai-node-type", "vig-server") + .has("vig-address-type", "vig") + .both() + .has("aai-node-type", "ipsec-configuration") + .has("ipsec-configuration-id", "ipsec") + .hasNext()); + + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + assertEquals(DeltaAction.CREATE, dbserLocal.getObjectDeltas().get(vigUri).getAction()); + assertEquals(4L, + dbserLocal.getObjectDeltas().get(vigUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(5L, + dbserLocal.getObjectDeltas().get(vigUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.CREATE)).count()); + assertThat(dbserLocal.getObjectDeltas().get(vigUri).getPropertyDeltas().get("ipaddress-v4-vig").getValue(), instanceOf(List.class)); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + + /* + * Update child vig-server with new list for vig-address-type + */ + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "update-child-vig-server", AAIProperties.MINIMUM_DEPTH); + vig = dbserLocal.getLatestVersionView(vigVertex); + uriQuery = engine.getQueryBuilder(ipsecVert).createQueryFromURI(new URI(vigUri)); + + new ArrayList<>(); + list.add("address-3"); + list.add("address-4"); + vig.setValue("ipaddress-v4-vig", list); + dbserLocal.serializeToDb(vig, vigVertex, uriQuery, "vf-module", vig.marshal(false)); + assertTrue("Vertex is still there", engine.tx().traversal().V() + .has("aai-node-type", "vig-server") + .has("vig-address-type", "vig") + .hasNext()); + assertTrue("Vf module has edge to gvnf", engine.tx().traversal().V() + .has("aai-node-type", "vig-server") + .has("vig-address-type", "vig") + .both() + .has("aai-node-type", "ipsec-configuration") + .has("ipsec-configuration-id", "ipsec") + .hasNext()); + + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + assertEquals(DeltaAction.UPDATE, dbserLocal.getObjectDeltas().get(vigUri).getAction()); + assertEquals(4L, + dbserLocal.getObjectDeltas().get(vigUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.STATIC)).count()); + assertEquals(4L, + dbserLocal.getObjectDeltas().get(vigUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.UPDATE)).count()); + assertThat(dbserLocal.getObjectDeltas().get(vigUri).getPropertyDeltas().get("ipaddress-v4-vig").getValue(), instanceOf(List.class)); + assertThat(dbserLocal.getObjectDeltas().get(vigUri).getPropertyDeltas().get("ipaddress-v4-vig").getOldValue(), instanceOf(List.class)); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + /* + * Delete top level + */ + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "delete-ipsec", AAIProperties.MINIMUM_DEPTH); + ipsec = dbserLocal.getLatestVersionView(ipsecVert); + String rv = ipsec.getValue(AAIProperties.RESOURCE_VERSION); + dbserLocal.delete(engine.tx().traversal().V(ipsecVert).next(), rv, true); + System.out.println(gson.toJsonTree(dbserLocal.getObjectDeltas().values())); + + assertFalse("ipsec-configuration no longer exists", engine.tx().traversal().V() + .has("aai-node-type", "ipsec-configuration") + .hasNext()); + assertFalse("vig-server no longer exists", engine.tx().traversal().V() + .has("aai-node-type", "vig-server") + .hasNext()); + + assertEquals(DeltaAction.DELETE, dbserLocal.getObjectDeltas().get(ipsecUri).getAction()); + assertEquals(9L, dbserLocal.getObjectDeltas().get(ipsecUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.DELETE)).count());assertEquals(DeltaAction.DELETE, dbserLocal.getObjectDeltas().get(vigUri).getAction()); + assertEquals(10L, dbserLocal.getObjectDeltas().get(vigUri).getPropertyDeltas().values().stream().filter(d -> d.getAction().equals(DeltaAction.DELETE)).count()); + dbserLocal.getObjectDeltas().values().forEach(od -> { + if (!od.getPropertyDeltas().containsKey(AAIProperties.AAI_UUID) ) { + fail(od.getUri() + " is missing " + AAIProperties.AAI_UUID); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID) == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " is null"); + } else if (od.getPropertyDeltas().get(AAIProperties.AAI_UUID).getValue() == null) { + fail(od.getUri() + " " + AAIProperties.AAI_UUID + " value is null"); + } + }); + } + +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerNotificationEventsTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerNotificationEventsTest.java new file mode 100644 index 00000000..cc1fc03d --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerNotificationEventsTest.java @@ -0,0 +1,330 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.db; + +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraphFactory; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.onap.aai.AAISetup; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.serialization.engines.JanusGraphDBEngine; +import org.onap.aai.serialization.engines.QueryStyle; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.setup.SchemaVersion; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.stream.Collectors; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.*; + +@RunWith(value = Parameterized.class) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class DbSerializerNotificationEventsTest extends AAISetup { + + // to use, set thrown.expect to whatever your test needs + // this line establishes default of expecting no exception to be thrown + @Rule + public ExpectedException thrown = ExpectedException.none(); + + protected static Graph graph; + + @Autowired + protected EdgeSerializer edgeSer; + @Autowired + protected EdgeIngestor ei; + + private SchemaVersion version; + private final ModelType introspectorFactoryType = ModelType.MOXY; + private Loader loader; + private TransactionalGraphEngine engine; // for tests that aren't mocking the engine + + @Parameterized.Parameter(value = 0) + public QueryStyle queryStyle; + + @Parameterized.Parameters(name = "QueryStyle.{0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] {{QueryStyle.TRAVERSAL}, {QueryStyle.TRAVERSAL_URI}}); + } + + @BeforeClass + public static void init() throws Exception { + graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + + } + + @Before + public void setup() throws Exception { + // createGraph(); + version = schemaVersions.getDefaultVersion(); + loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); + engine = new JanusGraphDBEngine(queryStyle, loader); + } + + /* + Create Complex + Create Pserver with pinterface and relationship to complex + Update pserver removing relationship to complex + Update pserver adding a second p-interface + Add l-interface directly to the 2nd p-interface + Delete pserver + */ + @Test + public void createComplexPserverWithRelUpdatePserverToDeleteRelAddPinterfaceThenDeleteComplexCheckingUpdatedListTest() throws AAIException, UnsupportedEncodingException, URISyntaxException { + engine.startTransaction(); + + System.out.println("Create Complex"); + DBSerializer dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "create-complex", AAIProperties.MINIMUM_DEPTH); + Introspector complex = loader.introspectorFromName("complex"); + Vertex complexV = dbserLocal.createNewVertex(complex); + final String complexUri = "/cloud-infrastructure/complexes/complex/c-id-b"; + QueryParser uriQuery = + engine.getQueryBuilder().createQueryFromURI(new URI(complexUri)); + + complex.setValue("physical-location-id", "c-id-b"); + complex.setValue("physical-location-type", "type"); + complex.setValue("street1", "streetA"); + complex.setValue("city", "cityA"); + complex.setValue("postal-code", "11111"); + complex.setValue("country", "abc"); + complex.setValue("region", "ef"); + dbserLocal.serializeToDb(complex, complexV, uriQuery, "complex", complex.marshal(false)); + + assertTrue("Complex created", engine.tx().traversal().V() + .has("aai-node-type", "complex") + .has("physical-location-id", "c-id-b") + .hasNext()); + Map<Vertex, Boolean> updated = getUpdatedVertexes(dbserLocal); + assertEquals("Number of updated vertexes", 1, updated.size()); + assertThat("Only modified vertexes are in the updated set", + updated.keySet().stream().map(v -> v.<String>value(AAIProperties.AAI_URI)).collect(Collectors.toSet()), + is(Collections.singleton(complexUri))); + List<String> didNotUpdateStandardVertexProps = updated.entrySet().stream() + .filter(e -> !e.getValue()) + .map(e -> e.getKey().<String>value(AAIProperties.AAI_URI)).collect(Collectors.toList()); + assertThat("Vertexes should all have their standard props updated", didNotUpdateStandardVertexProps, is(Collections.emptyList())); + + + + + System.out.println("Create Pserver with pinterface and relationship to complex "); + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "create-pserver", AAIProperties.MINIMUM_DEPTH); + Introspector pserver = loader.introspectorFromName("pserver"); + Vertex pserverV = dbserLocal.createNewVertex(pserver); + final String pserverUri = "/cloud-infrastructure/pservers/pserver/ps-b"; + uriQuery = + engine.getQueryBuilder().createQueryFromURI(new URI(pserverUri)); + + Introspector relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-to", "complex"); + relationship.setValue("related-link", complexUri); + Introspector relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", Collections.singletonList(relationship.getUnderlyingObject())); + + pserver.setValue("relationship-list", relationshipList.getUnderlyingObject()); + pserver.setValue("hostname", "ps-b"); + pserver.setValue("number-of-cpus", 20); + + Introspector pint = loader.introspectorFromName("p-interface"); + pint.setValue("interface-name", "pint-1"); + final String pintUri = pserverUri + "/p-interfaces/p-interface/pint-1"; + + Introspector pints = loader.introspectorFromName("p-interfaces"); + pints.setValue("p-interface", Collections.singletonList(pint.getUnderlyingObject())); + pserver.setValue("p-interfaces", pints.getUnderlyingObject()); + dbserLocal.serializeToDb(pserver, pserverV, uriQuery, "pserver", pserver.marshal(false)); + + assertTrue("Pserver created", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .hasNext()); + assertTrue("Pserver has edge to complex", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .bothE() + .otherV() + .has("aai-node-type", "complex") + .hasNext()); + assertTrue("Pserver has edge to pinterface", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .bothE() + .otherV() + .has("aai-node-type", "p-interface") + .hasNext()); + updated = getUpdatedVertexes(dbserLocal); + assertEquals("Number of updated vertexes", 3, updated.size()); + assertThat("Only modified vertexes are in the updated set", + updated.keySet().stream().map(v -> v.<String>value(AAIProperties.AAI_URI)).collect(Collectors.toSet()), + is(new HashSet<>(Arrays.asList(pserverUri, pintUri, complexUri)))); + didNotUpdateStandardVertexProps = updated.entrySet().stream() + .filter(e -> !e.getValue()) + .map(e -> e.getKey().<String>value(AAIProperties.AAI_URI)).collect(Collectors.toList()); + assertThat("Vertexes should all have their standard props updated", didNotUpdateStandardVertexProps, is(Collections.emptyList())); + + + System.out.println("Update pserver removing relationship to complex"); + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "update-pserver", AAIProperties.MINIMUM_DEPTH); + pserver = dbserLocal.getLatestVersionView(pserverV); + relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", Collections.emptyList()); + pserver.setValue("relationship-list", relationshipList.getUnderlyingObject()); + pserver.setValue("equip-type", "server-a"); + pserver.setValue("number-of-cpus", 99); + dbserLocal.serializeToDb(pserver, pserverV, uriQuery, "pserver", pserver.marshal(false)); + + assertFalse("Pserver no longer has edge to complex", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .bothE() + .otherV() + .has("aai-node-type", "complex") + .hasNext()); + updated = getUpdatedVertexes(dbserLocal); + assertEquals("Number of updated vertexes", 2, updated.size()); + assertThat("Only modified vertexes are in the updated set", + updated.keySet().stream().map(v -> v.<String>value(AAIProperties.AAI_URI)).collect(Collectors.toSet()), + is(new HashSet<>(Arrays.asList(pserverUri, complexUri)))); + didNotUpdateStandardVertexProps = updated.entrySet().stream() + .filter(e -> !e.getValue()) + .map(e -> e.getKey().<String>value(AAIProperties.AAI_URI)).collect(Collectors.toList()); + assertThat("Vertexes should all have their standard props updated", didNotUpdateStandardVertexProps, is(Collections.emptyList())); + + + + System.out.println("Update pserver adding a second p-interface"); + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "update-pserver", AAIProperties.MINIMUM_DEPTH); + pserver = dbserLocal.getLatestVersionView(pserverV); + Introspector pint2 = loader.introspectorFromName("p-interface"); + pint2.setValue("interface-name", "pint-2"); + pints = pserver.getWrappedValue("p-interfaces"); + List<Object> pintList = pserver.getWrappedValue("p-interfaces").getWrappedListValue("p-interface") + .stream().map(Introspector::getUnderlyingObject).collect(Collectors.toList()); + pintList.add(pint2.getUnderlyingObject()); + pints.setValue("p-interface", pintList); + pserver.setValue("p-interfaces", pints.getUnderlyingObject()); + final String pint2Uri = pserverUri + "/p-interfaces/p-interface/pint-2"; + dbserLocal.serializeToDb(pserver, pserverV, uriQuery, "pserver", pserver.marshal(false)); + + assertTrue("Pserver has edge to pinterface 2", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .in() + .has("aai-node-type", "p-interface") + .has("interface-name","pint-2") + .hasNext()); + assertTrue("p-interface 2 created", engine.tx().traversal().V() + .has("aai-node-type", "p-interface") + .has("interface-name", "pint-2") + .has(AAIProperties.AAI_URI, pint2Uri) + .hasNext()); + updated = getUpdatedVertexes(dbserLocal); + assertEquals("Number of updated vertexes", 1, updated.size()); + assertThat("Only modified vertexes are in the updated set", + updated.keySet().stream().map(v -> v.<String>value(AAIProperties.AAI_URI)).collect(Collectors.toSet()), + is(Collections.singleton(pint2Uri))); + didNotUpdateStandardVertexProps = updated.entrySet().stream() + .filter(e -> !e.getValue()) + .map(e -> e.getKey().<String>value(AAIProperties.AAI_URI)).collect(Collectors.toList()); + assertThat("Vertexes should all have their standard props updated", didNotUpdateStandardVertexProps, is(Collections.emptyList())); + + + System.out.println("Add l-interface directly to the 2nd p-interface"); + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "create-pserver", AAIProperties.MINIMUM_DEPTH); + Introspector lInt = loader.introspectorFromName("l-interface"); + Vertex lIntV = dbserLocal.createNewVertex(lInt); + final String lIntUri = pint2Uri + "/l-interfaces/l-interface/lint-1"; + uriQuery = + engine.getQueryBuilder().createQueryFromURI(new URI(lIntUri)); + lInt.setValue("interface-name", "lint-1"); + dbserLocal.serializeToDb(lInt, lIntV, uriQuery, "l-interface", lInt.marshal(false)); + + assertTrue("l-interface created", engine.tx().traversal().V() + .has("aai-node-type", "l-interface") + .has("interface-name", "lint-1") + .hasNext()); + + assertTrue("Pserver has edge to pinterface to l-interface", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .has("hostname", "ps-b") + .bothE() + .otherV() + .has("aai-node-type", "p-interface") + .bothE() + .otherV() + .has("aai-node-type", "l-interface") + .hasNext()); + updated = getUpdatedVertexes(dbserLocal); + assertEquals("Number of updated vertexes", 1, updated.size()); + assertThat("Only modified vertexes are in the updated set", + updated.keySet().stream().map(v -> v.<String>value(AAIProperties.AAI_URI)).collect(Collectors.toSet()), + is(new HashSet<>(Collections.singletonList(lIntUri)))); + didNotUpdateStandardVertexProps = updated.entrySet().stream() + .filter(e -> !e.getValue()) + .map(e -> e.getKey().<String>value(AAIProperties.AAI_URI)).collect(Collectors.toList()); + assertThat("Vertexes should all have their standard props updated", didNotUpdateStandardVertexProps, is(Collections.emptyList())); + + + System.out.println("Delete pserver"); + dbserLocal = new DBSerializer(version, engine, introspectorFactoryType, "delete-pserver", AAIProperties.MINIMUM_DEPTH); + pserver = dbserLocal.getLatestVersionView(pserverV); + String rv = pserver.getValue(AAIProperties.RESOURCE_VERSION); + dbserLocal.delete(engine.tx().traversal().V(pserverV).next(), rv, true); + + assertFalse("pserver no longer exists", engine.tx().traversal().V() + .has("aai-node-type", "pserver") + .hasNext()); + updated = getUpdatedVertexes(dbserLocal); + assertEquals("Number of updated vertexes", 0, updated.size()); + didNotUpdateStandardVertexProps = updated.entrySet().stream() + .filter(e -> !e.getValue()) + .map(e -> e.getKey().<String>value(AAIProperties.AAI_URI)).collect(Collectors.toList()); + assertThat("Vertexes should all have their standard props updated", didNotUpdateStandardVertexProps, is(Collections.emptyList())); + + + } + + private Map<Vertex, Boolean> getUpdatedVertexes(DBSerializer dbserLocal) { + Map<Vertex, Boolean> updated = new LinkedHashMap<>(dbserLocal.getUpdatedVertexes()); + dbserLocal.touchStandardVertexPropertiesForEdges().forEach(v -> updated.putIfAbsent(v, true)); + return updated; + } + + +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerTest.java index b50adf2a..dd4454d5 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerTest.java @@ -20,18 +20,11 @@ package org.onap.aai.serialization.db; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; - import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.*; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; import org.janusgraph.core.JanusGraphFactory; import org.junit.*; @@ -40,11 +33,12 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.onap.aai.AAISetup; import org.onap.aai.db.props.AAIProperties; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.edges.enums.EdgeType; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.introspection.*; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.serialization.engines.JanusGraphDBEngine; import org.onap.aai.serialization.engines.QueryStyle; @@ -54,6 +48,16 @@ import org.onap.aai.util.AAIConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.*; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + @RunWith(value = Parameterized.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class DbSerializerTest extends AAISetup { @@ -72,15 +76,14 @@ public class DbSerializerTest extends AAISetup { private SchemaVersion version; private final ModelType introspectorFactoryType = ModelType.MOXY; - private final DBConnectionType type = DBConnectionType.REALTIME; private Loader loader; private TransactionalGraphEngine dbEngine; private TransactionalGraphEngine engine; // for tests that aren't mocking the engine private DBSerializer dbser; - TransactionalGraphEngine spy; - TransactionalGraphEngine.Admin adminSpy; + private TransactionalGraphEngine spy; + private TransactionalGraphEngine.Admin adminSpy; - @Parameterized.Parameter(value = 0) + @Parameterized.Parameter public QueryStyle queryStyle; @Parameterized.Parameters(name = "QueryStyle.{0}") @@ -89,7 +92,7 @@ public class DbSerializerTest extends AAISetup { } @BeforeClass - public static void init() throws Exception { + public static void init() { graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); } @@ -99,11 +102,11 @@ public class DbSerializerTest extends AAISetup { // createGraph(); version = schemaVersions.getDefaultVersion(); loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); - dbEngine = new JanusGraphDBEngine(queryStyle, type, loader); + dbEngine = new JanusGraphDBEngine(queryStyle, loader); spy = spy(dbEngine); adminSpy = spy(dbEngine.asAdmin()); - engine = new JanusGraphDBEngine(queryStyle, type, loader); + engine = new JanusGraphDBEngine(queryStyle, loader); dbser = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST"); } @@ -146,7 +149,7 @@ public class DbSerializerTest extends AAISetup { } @After - public void tearDown() throws Exception { + public void tearDown() { engine.rollback(); } @@ -155,46 +158,124 @@ public class DbSerializerTest extends AAISetup { graph.close(); } - public void subnetSetup() throws AAIException { + private void subnetSetup() throws AAIException, UnsupportedEncodingException { /* * This setus up the test graph, For future junits , add more vertices * and edges */ - Vertex l3interipv4addresslist_1 = graph.traversal().addV("aai-node-type", "l3-interface-ipv4-address-list", - "l3-interface-ipv4-address", "l3-interface-ipv4-address-1").next(); - Vertex subnet_2 = graph.traversal().addV("aai-node-type", "subnet", "subnet-id", "subnet-id-2").next(); - Vertex l3interipv6addresslist_3 = graph.traversal().addV("aai-node-type", "l3-interface-ipv6-address-list", - "l3-interface-ipv6-address", "l3-interface-ipv6-address-3").next(); - Vertex subnet_4 = graph.traversal().addV("aai-node-type", "subnet", "subnet-id", "subnet-id-4").next(); - Vertex subnet_5 = graph.traversal().addV("aai-node-type", "subnet", "subnet-id", "subnet-id-5").next(); - Vertex l3network_6 = graph.traversal() - .addV("aai-node-type", "l3-network", "network-id", "network-id-6", "network-name", "network-name-6") - .next(); + Vertex l3interipv4addresslist_1 = graph.addVertex("aai-node-type", "l3-interface-ipv4-address-list", + "l3-interface-ipv4-address", "l3-interface-ipv4-address-1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex subnet_2 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-2", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex l3interipv6addresslist_3 = graph.addVertex("aai-node-type", "l3-interface-ipv6-address-list", + "l3-interface-ipv6-address", "l3-interface-ipv6-address-3", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex subnet_4 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-4", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex subnet_5 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-5", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex l3network_6 = graph.addVertex("aai-node-type", "l3-network", "network-id", "network-id-6", "network-name", "network-name-6", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); GraphTraversalSource g = graph.traversal(); edgeSer.addEdge(g, l3interipv4addresslist_1, subnet_2); edgeSer.addEdge(g, l3interipv6addresslist_3, subnet_4); edgeSer.addTreeEdge(g, subnet_5, l3network_6); + + l3interipv4addresslist_1.property(AAIProperties.AAI_URI, dbser.getURIForVertex(l3interipv4addresslist_1).toString()); + subnet_2.property(AAIProperties.AAI_URI, dbser.getURIForVertex(subnet_2).toString()); + l3interipv6addresslist_3.property(AAIProperties.AAI_URI, dbser.getURIForVertex(l3interipv6addresslist_3).toString()); + subnet_4.property(AAIProperties.AAI_URI, dbser.getURIForVertex(subnet_4).toString()); + subnet_5.property(AAIProperties.AAI_URI, dbser.getURIForVertex(subnet_5).toString()); + l3network_6.property(AAIProperties.AAI_URI, dbser.getURIForVertex(l3network_6).toString()); + } - public void l3NetworkSetup() throws AAIException { + private void l3NetworkSetup() throws AAIException, UnsupportedEncodingException { /* * This setus up the test graph, For future junits , add more vertices * and edges */ Vertex l3network1 = graph.addVertex("aai-node-type", "l3-network", "network-id", "network-id-v1", - "network-name", "network-name-v1"); + "network-name", "network-name-v1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); Vertex l3network2 = graph.addVertex("aai-node-type", "l3-network", "network-id", "network-id-v2", - "network-name", "network-name-v2"); - Vertex subnet1 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-v1"); - Vertex subnet2 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-v2"); + "network-name", "network-name-v2", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex subnet1 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-v1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex subnet2 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-v2", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); Vertex l3interipv4addresslist_1 = graph.addVertex("aai-node-type", "l3-interface-ipv4-address-list", - "l3-interface-ipv4-address", "l3-intr-v1"); + "l3-interface-ipv4-address", "l3-intr-v1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); Vertex l3interipv6addresslist_1 = graph.addVertex("aai-node-type", "l3-interface-ipv6-address-list", - "l3-interface-ipv6-address", "l3-interface-ipv6-v1"); + "l3-interface-ipv6-address", "l3-interface-ipv6-v1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); GraphTraversalSource g = graph.traversal(); edgeSer.addTreeEdge(g, subnet1, l3network1); @@ -203,28 +284,77 @@ public class DbSerializerTest extends AAISetup { edgeSer.addTreeEdge(g, subnet2, l3network2); + subnet1.property(AAIProperties.AAI_URI, dbser.getURIForVertex(subnet1).toString()); + l3interipv4addresslist_1.property(AAIProperties.AAI_URI, dbser.getURIForVertex(l3interipv4addresslist_1).toString()); + l3network1.property(AAIProperties.AAI_URI, dbser.getURIForVertex(l3network1).toString()); + subnet2.property(AAIProperties.AAI_URI, dbser.getURIForVertex(subnet2).toString()); + l3network2.property(AAIProperties.AAI_URI, dbser.getURIForVertex(l3network2).toString()); + + + } - public void vserverSetup() throws AAIException { + private void vserverSetup() throws AAIException, UnsupportedEncodingException { /* * This setus up the test graph, For future junits , add more vertices * and edges */ Vertex vserver1 = graph.addVertex("aai-node-type", "vserver", "vserver-id", "vss1", - AAIProperties.AAI_URI.toString(), - "/cloud-infrastructure/cloud-regions/cloud-region/me/123/tenants/tenant/453/vservers/vserver/vss1"); - - Vertex lInterface1 = graph.addVertex("aai-node-type", "l-interface", "interface-name", "lIntr1"); - Vertex lInterface2 = graph.addVertex("aai-node-type", "l-interface", "interface-name", "lIntr2"); - - Vertex logicalLink1 = graph.addVertex("aai-node-type", "logical-link", "link-name", "logLink1"); - Vertex logicalLink2 = graph.addVertex("aai-node-type", "logical-link", "link-name", "logLink2"); + AAIProperties.AAI_URI, "/cloud-infrastructure/cloud-regions/cloud-region/me/123/tenants/tenant/453/vservers/vserver/vss1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + + Vertex lInterface1 = graph.addVertex("aai-node-type", "l-interface", "interface-name", "lIntr1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex lInterface2 = graph.addVertex("aai-node-type", "l-interface", "interface-name", "lIntr2", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + + Vertex logicalLink1 = graph.addVertex("aai-node-type", "logical-link", "link-name", "logLink1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex logicalLink2 = graph.addVertex("aai-node-type", "logical-link", "link-name", "logLink2", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); Vertex l3interipv4addresslist_1 = graph.addVertex("aai-node-type", "l3-interface-ipv4-address-list", - "l3-interface-ipv4-address", "l3-intr-ipv4-address-1"); + "l3-interface-ipv4-address", "l3-intr-ipv4-address-1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); Vertex l3interipv6addresslist_2 = graph.addVertex("aai-node-type", "l3-interface-ipv6-address-list", - "l3-interface-ipv4-address", "l3-intr-ipv6-address-1"); + "l3-interface-ipv4-address", "l3-intr-ipv6-address-1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); GraphTraversalSource g = graph.traversal(); @@ -235,10 +365,18 @@ public class DbSerializerTest extends AAISetup { edgeSer.addEdge(g, lInterface1, logicalLink1); edgeSer.addEdge(g, lInterface2, logicalLink2); + + vserver1.property(AAIProperties.AAI_URI, dbser.getURIForVertex(vserver1).toString()); + lInterface1.property(AAIProperties.AAI_URI, dbser.getURIForVertex(lInterface1).toString()); + lInterface2.property(AAIProperties.AAI_URI, dbser.getURIForVertex(lInterface2).toString()); + l3interipv4addresslist_1.property(AAIProperties.AAI_URI, dbser.getURIForVertex(l3interipv4addresslist_1).toString()); + l3interipv6addresslist_2.property(AAIProperties.AAI_URI, dbser.getURIForVertex(l3interipv6addresslist_2).toString()); + logicalLink1.property(AAIProperties.AAI_URI, dbser.getURIForVertex(logicalLink1).toString()); + logicalLink2.property(AAIProperties.AAI_URI, dbser.getURIForVertex(logicalLink2).toString()); } @Test - public void subnetDelWithInEdgesIpv4Test() throws AAIException { + public void subnetDelWithInEdgesIpv4Test() throws AAIException, UnsupportedEncodingException { subnetSetup(); String expected_message = "Object is being reference by additional objects preventing it from being deleted. Please clean up references from the following types [l3-interface-ipv4-address-list]"; @@ -254,7 +392,7 @@ public class DbSerializerTest extends AAISetup { } @Test - public void subnetDelWithInEdgesIpv6Test() throws AAIException { + public void subnetDelWithInEdgesIpv6Test() throws AAIException, UnsupportedEncodingException { subnetSetup(); String expected_message = "Object is being reference by additional objects preventing it from being deleted. Please clean up references from the following types [l3-interface-ipv6-address-list]"; @@ -269,7 +407,7 @@ public class DbSerializerTest extends AAISetup { } @Test - public void subnetDelWithInEdgesL3network() throws AAIException { + public void subnetDelWithInEdgesL3network() throws AAIException, UnsupportedEncodingException { subnetSetup(); String expected_message = ""; @@ -283,7 +421,7 @@ public class DbSerializerTest extends AAISetup { } - public String testCascadeDelete(Vertex v) throws AAIException { + private String testCascadeDelete(Vertex v) throws AAIException { GraphTraversalSource traversal = graph.traversal(); when(spy.asAdmin()).thenReturn(adminSpy); @@ -297,25 +435,7 @@ public class DbSerializerTest extends AAISetup { try { serializer.delete(v, deletableVertices, "resourceVersion", false); } catch (AAIException exception) { - exceptionMessage = exception.getMessage(); - } - return exceptionMessage; - - } - - public String testDelete(Vertex v) throws AAIException { - - GraphTraversalSource traversal = graph.traversal(); - when(spy.asAdmin()).thenReturn(adminSpy); - when(adminSpy.getTraversalSource()).thenReturn(traversal); - when(adminSpy.getReadOnlyTraversalSource()).thenReturn(traversal); - - String exceptionMessage = ""; - DBSerializer serializer = new DBSerializer(version, spy, introspectorFactoryType, "AAI_TEST"); - - try { - serializer.delete(v, "resourceVersion", false); - } catch (AAIException exception) { + exception.printStackTrace(); exceptionMessage = exception.getMessage(); } return exceptionMessage; @@ -331,7 +451,7 @@ public class DbSerializerTest extends AAISetup { Vertex testVertex = dbser.createNewVertex(testObj); Vertex fromGraph = engine.tx().traversal().V().has("aai-node-type", "generic-vnf").toList().get(0); assertEquals(testVertex.id(), fromGraph.id()); - assertEquals("AAI-TEST", fromGraph.property(AAIProperties.SOURCE_OF_TRUTH.toString()).value()); + assertEquals("AAI-TEST", fromGraph.property(AAIProperties.SOURCE_OF_TRUTH).value()); } @@ -343,17 +463,17 @@ public class DbSerializerTest extends AAISetup { // different value Thread.sleep(2); DBSerializer dbser2 = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST-2"); - Vertex vert = graph.addVertex("aai-node-type", "generic-vnf"); + Vertex vert = graph.addVertex("aai-node-type", "generic-vnf", "aai-uri", "a"); // Upon first creation of the Vertex and the DBSerializer // the source of truth and created-ts should be the same as their modified counterparts dbser2.touchStandardVertexProperties(vert, true); - String createTS = (String) vert.property(AAIProperties.CREATED_TS).value(); - String modTS = (String) vert.property(AAIProperties.LAST_MOD_TS).value(); + String createTS = String.valueOf(vert.property(AAIProperties.CREATED_TS).value()); + String modTS = String.valueOf(vert.property(AAIProperties.LAST_MOD_TS).value()); String sot = (String) vert.property(AAIProperties.SOURCE_OF_TRUTH).value(); String lastModSOT = (String) vert.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value(); - assertTrue(createTS.equals(modTS)); - assertTrue(sot.equals(lastModSOT)); + assertEquals(createTS, modTS); + assertEquals(sot, lastModSOT); // if this test runs through too fast the value may not change, causing the test to fail. sleeping ensures a // different value @@ -363,12 +483,12 @@ public class DbSerializerTest extends AAISetup { // Here the vertex will be modified by a different source of truth DBSerializer dbser3 = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST-3"); dbser3.touchStandardVertexProperties(vert, false); - createTS = (String) vert.property(AAIProperties.CREATED_TS).value(); - modTS = (String) vert.property(AAIProperties.LAST_MOD_TS).value(); + createTS = String.valueOf(vert.property(AAIProperties.CREATED_TS).value()); + modTS = String.valueOf(vert.property(AAIProperties.LAST_MOD_TS).value()); sot = (String) vert.property(AAIProperties.SOURCE_OF_TRUTH).value(); lastModSOT = (String) vert.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value(); - assertFalse(createTS.equals(modTS)); - assertFalse(sot.equals(lastModSOT)); + assertNotEquals(createTS, modTS); + assertNotEquals(sot, lastModSOT); // if this test runs through too fast the value may not change, causing the test to fail. sleeping ensures a // different value @@ -380,10 +500,10 @@ public class DbSerializerTest extends AAISetup { // Using an existing vertex, but treating it as new && using an older DBSerializer dbser.touchStandardVertexProperties(vert, true); String resverStart = (String) vert.property(AAIProperties.RESOURCE_VERSION).value(); - String lastModTimeStart = (String) vert.property(AAIProperties.LAST_MOD_TS).value(); - createTS = (String) vert.property(AAIProperties.CREATED_TS).value(); - modTS = (String) vert.property(AAIProperties.LAST_MOD_TS).value(); - assertTrue(createTS.equals(modTS)); + String lastModTimeStart = String.valueOf(vert.property(AAIProperties.LAST_MOD_TS).value()); + createTS = String.valueOf(vert.property(AAIProperties.CREATED_TS).value()); + modTS = String.valueOf(vert.property(AAIProperties.LAST_MOD_TS).value()); + assertEquals(createTS, modTS); assertEquals("AAI-TEST", vert.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value()); // if this test runs through too fast the value may not change, causing the test to fail. sleeping ensures a @@ -392,16 +512,16 @@ public class DbSerializerTest extends AAISetup { dbser2.touchStandardVertexProperties(vert, false); String resourceVer = (String) vert.property(AAIProperties.RESOURCE_VERSION).value(); - String lastModTs = (String) vert.property(AAIProperties.LAST_MOD_TS).value(); + String lastModTs = String.valueOf(vert.property(AAIProperties.LAST_MOD_TS).value()); String lastModSoT = (String) vert.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value(); - assertFalse(resverStart.equals(resourceVer)); - assertFalse(lastModTimeStart.equals(lastModTs)); + assertNotEquals(resverStart, resourceVer); + assertNotEquals(lastModTimeStart, lastModTs); assertEquals("AAI-TEST-2", lastModSoT); } @Test - public void touchStandardVertexPropertiesAAIUUIDTest() throws AAIException, InterruptedException { + public void touchStandardVertexPropertiesAAIUUIDTest() { engine.startTransaction(); Graph graph = TinkerGraph.open(); @@ -466,7 +586,7 @@ public class DbSerializerTest extends AAISetup { } @Test - public void trimClassNameTest() throws AAIException { + public void trimClassNameTest() { assertEquals("GenericVnf", dbser.trimClassName("GenericVnf")); assertEquals("GenericVnf", dbser.trimClassName("org.onap.aai.GenericVnf")); } @@ -526,9 +646,21 @@ public class DbSerializerTest extends AAISetup { engine.startTransaction(); Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "myvnf", "aai-uri", - "/network/generic-vnfs/generic-vnf/myvnf"); + "/network/generic-vnfs/generic-vnf/myvnf", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); Vertex vnfc = engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", - "/network/vnfcs/vnfc/a-name"); + "/network/vnfcs/vnfc/a-name", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); edgeSer.addEdge(engine.tx().traversal(), gvnf, vnfc); @@ -540,7 +672,7 @@ public class DbSerializerTest extends AAISetup { relationship.setValue("related-link", "/network/vnfcs/vnfc/a-name"); relationship.setValue("relationship-data", relData); - assertTrue(dbser.deleteEdge(relationship, gvnf)); + assertTrue(dbser.deleteEdge(relationship, gvnf).isPresent()); assertFalse(engine.tx().traversal().V(gvnf).both("uses").hasNext()); assertFalse(engine.tx().traversal().V(vnfc).both("uses").hasNext()); @@ -552,9 +684,9 @@ public class DbSerializerTest extends AAISetup { engine.startTransaction(); Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "myvnf", "aai-uri", - "/network/generic-vnfs/generic-vnf/myvnf"); + "/network/generic-vnfs/generic-vnf/myvnf", "aai-uuid", "a"); Vertex vnfc = engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", - "/network/vnfcs/vnfc/a-name"); + "/network/vnfcs/vnfc/a-name", "aai-uuid", "b"); // sunny day case Introspector relData = loader.introspectorFromName("relationship-data"); @@ -565,7 +697,7 @@ public class DbSerializerTest extends AAISetup { relationship.setValue("related-link", "/network/vnfcs/vnfc/a-name"); relationship.setValue("relationship-data", relData); - assertTrue(dbser.createEdge(relationship, gvnf)); + assertNotNull(dbser.createEdge(relationship, gvnf)); assertTrue(engine.tx().traversal().V(gvnf).both("org.onap.relationships.inventory.BelongsTo").hasNext()); assertTrue(engine.tx().traversal().V(vnfc).both("org.onap.relationships.inventory.BelongsTo").hasNext()); @@ -634,9 +766,9 @@ public class DbSerializerTest extends AAISetup { Vertex gvnfVert = dbser.createNewVertex(gvnf); gvnf.setValue("vnf-id", "myvnf"); + gvnf.setValue("vnf-type", "typo"); dbser.serializeSingleVertex(gvnfVert, gvnf, "test"); assertTrue(engine.tx().traversal().V().has("aai-node-type", "generic-vnf").has("vnf-id", "myvnf").hasNext()); - } @Test @@ -666,19 +798,14 @@ public class DbSerializerTest extends AAISetup { engine.startTransaction(); Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "vnf-123", "aai-uri", - "/network/generic-vnfs/generic-vnf/vnf-123"); + "/network/generic-vnfs/generic-vnf/vnf-123", "aai-uuid", "a"); Vertex vnfc = engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "vnfc-123", "aai-uri", - "/network/vnfcs/vnfc/vnfc-123"); + "/network/vnfcs/vnfc/vnfc-123", "aai-uuid", "b"); edgeSer.addEdge(engine.tx().traversal(), gvnf, vnfc); Introspector obj = loader.introspectorFromName("generic-vnf"); - obj = this.dbser.dbToObject(Arrays.asList(gvnf), obj, AAIProperties.MAXIMUM_DEPTH, false, "false"); - - MarshallerProperties properties = - new MarshallerProperties.Builder(org.onap.aai.restcore.MediaType.getEnum("application/json")) - .formatted(true).build(); - System.out.println(obj.marshal(properties)); + obj = this.dbser.dbToObject(Collections.singletonList(gvnf), obj, AAIProperties.MAXIMUM_DEPTH, false, "false"); assertEquals("edge label between generic-vnf and vnfs is uses", "org.onap.relationships.inventory.BelongsTo", obj.getWrappedValue("relationship-list").getWrappedListValue("relationship").get(0) @@ -704,22 +831,21 @@ public class DbSerializerTest extends AAISetup { edgeSer.addEdge(engine.tx().traversal(), gvnf, vnfc); Introspector obj = loader.introspectorFromName("generic-vnf"); - obj = dbser.dbToObject(Arrays.asList(gvnf), obj, AAIProperties.MAXIMUM_DEPTH, false, "false"); + obj = dbser.dbToObject(Collections.singletonList(gvnf), obj, AAIProperties.MAXIMUM_DEPTH, false, "false"); - assertEquals("Relationship does not contain edge-property", false, obj.getWrappedValue("relationship-list") - .getWrappedListValue("relationship").get(0).hasProperty("relationship-label")); + assertFalse("Relationship does not contain edge-property", obj.getWrappedValue("relationship-list").getWrappedListValue("relationship").get(0).hasProperty("relationship-label")); } @Test public void createEdgeWithInvalidLabelTest() throws AAIException, UnsupportedEncodingException, - NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + SecurityException, IllegalArgumentException { engine.startTransaction(); Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "myvnf", "aai-uri", - "/network/generic-vnfs/generic-vnf/myvnf"); - engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name"); + "/network/generic-vnfs/generic-vnf/myvnf", "aai-uuid", "a"); + engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name", "aai-uuid", "b"); Introspector relData = loader.introspectorFromName("relationship-data"); relData.setValue("relationship-key", "vnfc.vnfc-name"); @@ -738,6 +864,26 @@ public class DbSerializerTest extends AAISetup { } @Test + public void createEdgeUsingIntrospectorTest() throws AAIException, UnsupportedEncodingException, SecurityException, IllegalArgumentException { + + engine.startTransaction(); + + Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "myvnf", "aai-uri", + "/network/generic-vnfs/generic-vnf/myvnf", "aai-uuid", "a"); + engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name", "aai-uuid", "b"); + + Introspector relData = loader.introspectorFromName("relationship-data"); + relData.setValue("relationship-key", "vnfc.vnfc-name"); + relData.setValue("relationship-value", "a-name"); + Introspector relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-to", "vnfc"); + relationship.setValue("related-link", "/network/vnfcs/vnfc/a-name"); + relationship.setValue("relationship-data", relData); + + dbser.createEdge(relationship, gvnf); + } + + @Test public void addRelatedToPropertyTest() throws AAIException { engine.startTransaction(); @@ -789,7 +935,7 @@ public class DbSerializerTest extends AAISetup { Introspector res = dbser.dbToObject(vertices, gvContainer, 0, true, "true"); List<Introspector> gvs = res.getWrappedListValue("generic-vnf"); - assertTrue(gvs.size() == 2); + assertEquals(2, gvs.size()); for (Introspector i : gvs) { String vnfId = i.getValue("vnf-id"); assertTrue("id1".equals(vnfId) || "id2".equals(vnfId)); @@ -814,16 +960,31 @@ public class DbSerializerTest extends AAISetup { public void deleteItemsWithTraversal() throws AAIException { DBSerializer dbser = new DBSerializer(version, engine, ModelType.MOXY, "AAI-TEST"); engine.startTransaction(); - Vertex gv = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "id1"); - Vertex lint = engine.tx().addVertex("aai-node-type", "l-interface", "interface-name", "name1"); + Vertex gv = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "id1", + AAIProperties.AAI_URI, "/network/generic-vnfs/generic-vnf/id1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex lint = engine.tx().addVertex("aai-node-type", "l-interface", "interface-name", "name1", + AAIProperties.AAI_URI, "/network/generic-vnfs/generic-vnf/id1/l-interfaces/l-interface/name1", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); assertTrue(engine.tx().traversal().V().has("vnf-id", "id1").hasNext()); assertTrue(engine.tx().traversal().V().has("interface-name", "name1").hasNext()); - dbser.deleteItemsWithTraversal(Arrays.asList(gv, lint)); + dbser.deleteWithTraversal(gv); + dbser.deleteWithTraversal(lint); - assertTrue(!engine.tx().traversal().V().has("vnf-id", "id1").hasNext()); - assertTrue(!engine.tx().traversal().V().has("interface-name", "name1").hasNext()); + assertFalse(engine.tx().traversal().V().has("vnf-id", "id1").hasNext()); + assertFalse(engine.tx().traversal().V().has("interface-name", "name1").hasNext()); } @@ -832,8 +993,20 @@ public class DbSerializerTest extends AAISetup { DBSerializer dbser = new DBSerializer(version, engine, ModelType.MOXY, "AAI-TEST"); engine.startTransaction(); Vertex gv = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "id1", "aai-uri", - "/network/generic-vnfs/generic-vnf/id1"); - Vertex lint = engine.tx().addVertex("aai-node-type", "l-interface"); + "/network/generic-vnfs/generic-vnf/id1", "aai-uuid", "a", + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); + Vertex lint = engine.tx().addVertex("aai-node-type", "l-interface", + "aai-uri", "abc", + "aai-uuid", "b", + AAIProperties.CREATED_TS, 123L, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333L); edgeSer.addTreeEdge(engine.tx().traversal(), gv, lint); Introspector lintIntro = loader.introspectorFromName("l-interface"); @@ -855,13 +1028,13 @@ public class DbSerializerTest extends AAISetup { "very-fast", "service-provider-bandwidth-up-units", "things"); Introspector res = dbser.getLatestVersionView(phys); - assertTrue("zaldo".equals(res.getValue("link-name"))); - assertTrue("very-fast".equals(res.getValue("speed-value"))); - assertTrue("things".equals(res.getValue("service-provider-bandwidth-up-units"))); + assertEquals("zaldo", res.getValue("link-name")); + assertEquals("very-fast", res.getValue("speed-value")); + assertEquals("things", res.getValue("service-provider-bandwidth-up-units")); } @Test - public void cascadeVserverDeleteTest() throws AAIException { + public void cascadeVserverDeleteTest() throws AAIException, UnsupportedEncodingException { vserverSetup(); String expected_message = ""; @@ -877,7 +1050,7 @@ public class DbSerializerTest extends AAISetup { } @Test - public void cascadeL3NetworkPreventDeleteTest() throws AAIException { + public void cascadeL3NetworkPreventDeleteTest() throws AAIException, UnsupportedEncodingException { l3NetworkSetup(); ArrayList expected_messages = new ArrayList<String>(); expected_messages.add( @@ -898,7 +1071,7 @@ public class DbSerializerTest extends AAISetup { } @Test - public void cascadeL3NetworkDeleteTest() throws AAIException { + public void cascadeL3NetworkDeleteTest() throws AAIException, UnsupportedEncodingException { l3NetworkSetup(); String expected_message = ""; @@ -913,4 +1086,5 @@ public class DbSerializerTest extends AAISetup { assertEquals(expected_message, exceptionMessage); } + } diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializer_needsFakeRulesTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializer_needsFakeRulesTest.java index 808dd631..9a78a433 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializer_needsFakeRulesTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializer_needsFakeRulesTest.java @@ -20,17 +20,10 @@ package org.onap.aai.serialization.db; -import static org.junit.Assert.*; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; - import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.*; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; import org.janusgraph.core.JanusGraphFactory; import org.junit.*; import org.junit.rules.ExpectedException; @@ -38,18 +31,20 @@ import org.junit.runner.RunWith; import org.onap.aai.config.ConfigConfiguration; import org.onap.aai.config.IntrospectionConfig; import org.onap.aai.config.SpringContextAware; +import org.onap.aai.config.XmlFormatTransformerConfiguration; import org.onap.aai.db.props.AAIProperties; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.introspection.*; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.LoaderFactory; +import org.onap.aai.introspection.ModelType; import org.onap.aai.nodes.NodeIngestor; import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.serialization.engines.JanusGraphDBEngine; import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.serialization.queryformats.QueryFormatTestHelper; -import org.onap.aai.setup.SchemaLocationsBean; import org.onap.aai.setup.SchemaVersion; import org.onap.aai.setup.SchemaVersions; import org.onap.aai.util.AAIConstants; @@ -58,11 +53,23 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + //@RunWith(value = Parameterized.class) TODO replace this functionality @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( classes = {ConfigConfiguration.class, AAICoreFakeEdgesConfigTranslator.class, NodeIngestor.class, - EdgeIngestor.class, EdgeSerializer.class, SpringContextAware.class, IntrospectionConfig.class}) + EdgeIngestor.class, EdgeSerializer.class, SpringContextAware.class, IntrospectionConfig.class, XmlFormatTransformerConfiguration.class}) @TestPropertySource( properties = {"schema.translator.list = config", "schema.nodes.location=src/test/resources/onap/oxm", "schema.edges.location=src/test/resources/onap/dbedgerules"}) @@ -84,7 +91,6 @@ public class DbSerializer_needsFakeRulesTest { private SchemaVersion version; private final ModelType introspectorFactoryType = ModelType.MOXY; - private final DBConnectionType type = DBConnectionType.REALTIME; private Loader loader; private TransactionalGraphEngine dbEngine; private TransactionalGraphEngine engine; // for tests that aren't mocking the engine @@ -92,19 +98,8 @@ public class DbSerializer_needsFakeRulesTest { TransactionalGraphEngine spy; TransactionalGraphEngine.Admin adminSpy; - // @Parameterized.Parameter(value = 0) public QueryStyle queryStyle = QueryStyle.TRAVERSAL; - /* - * @Parameterized.Parameters(name = "QueryStyle.{0}") - * public static Collection<Object[]> data() { - * return Arrays.asList(new Object[][]{ - * {QueryStyle.TRAVERSAL}, - * {QueryStyle.TRAVERSAL_URI} - * }); - * } - */ - @BeforeClass public static void init() throws Exception { graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); @@ -117,15 +112,14 @@ public class DbSerializer_needsFakeRulesTest { @Before public void setup() throws Exception { - // createGraph(); version = schemaVersions.getDefaultVersion(); loader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectorFactoryType, version); - dbEngine = new JanusGraphDBEngine(queryStyle, type, loader); + dbEngine = new JanusGraphDBEngine(queryStyle, loader); spy = spy(dbEngine); adminSpy = spy(dbEngine.asAdmin()); - engine = new JanusGraphDBEngine(queryStyle, type, loader); + engine = new JanusGraphDBEngine(queryStyle, loader); dbser = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST"); } @@ -145,16 +139,14 @@ public class DbSerializer_needsFakeRulesTest { * and edges */ - Vertex l3interipv4addresslist_1 = graph.traversal().addV("aai-node-type", "l3-interface-ipv4-address-list", - "l3-interface-ipv4-address", "l3-interface-ipv4-address-1").next(); - Vertex subnet_2 = graph.traversal().addV("aai-node-type", "subnet", "subnet-id", "subnet-id-2").next(); - Vertex l3interipv6addresslist_3 = graph.traversal().addV("aai-node-type", "l3-interface-ipv6-address-list", - "l3-interface-ipv6-address", "l3-interface-ipv6-address-3").next(); - Vertex subnet_4 = graph.traversal().addV("aai-node-type", "subnet", "subnet-id", "subnet-id-4").next(); - Vertex subnet_5 = graph.traversal().addV("aai-node-type", "subnet", "subnet-id", "subnet-id-5").next(); - Vertex l3network_6 = graph.traversal() - .addV("aai-node-type", "l3-network", "network-id", "network-id-6", "network-name", "network-name-6") - .next(); + Vertex l3interipv4addresslist_1 = graph.addVertex("aai-node-type", "l3-interface-ipv4-address-list", + "l3-interface-ipv4-address", "l3-interface-ipv4-address-1"); + Vertex subnet_2 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-2"); + Vertex l3interipv6addresslist_3 = graph.addVertex("aai-node-type", "l3-interface-ipv6-address-list", + "l3-interface-ipv6-address", "l3-interface-ipv6-address-3"); + Vertex subnet_4 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-4"); + Vertex subnet_5 = graph.addVertex("aai-node-type", "subnet", "subnet-id", "subnet-id-5"); + Vertex l3network_6 = graph.addVertex("aai-node-type", "l3-network", "network-id", "network-id-6", "network-name", "network-name-6"); GraphTraversalSource g = graph.traversal(); edgeSer.addEdge(g, l3interipv4addresslist_1, subnet_2); @@ -190,7 +182,13 @@ public class DbSerializer_needsFakeRulesTest { engine.startTransaction(); engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "vnfc-" + testName, AAIProperties.AAI_URI, - "/network/vnfcs/vnfc/vnfc-" + testName); + "/network/vnfcs/vnfc/vnfc-" + testName, + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Introspector relationship = loader.introspectorFromName("relationship"); relationship.setValue("related-to", "vnfc"); @@ -222,9 +220,19 @@ public class DbSerializer_needsFakeRulesTest { engine.startTransaction(); Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "myvnf", "aai-uri", - "/network/generic-vnfs/generic-vnf/myvnf"); + "/network/generic-vnfs/generic-vnf/myvnf", "aai-uuid", "a", + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Vertex vnfc = engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", - "/network/vnfcs/vnfc/a-name"); + "/network/vnfcs/vnfc/a-name", "aai-uuid", "b", + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); // sunny day case Introspector relData = loader.introspectorFromName("relationship-data"); @@ -236,7 +244,7 @@ public class DbSerializer_needsFakeRulesTest { relationship.setValue("relationship-data", relData); relationship.setValue("relationship-label", "over-uses"); - assertTrue(localDbser.createEdge(relationship, gvnf)); + assertNotNull(dbser.createEdge(relationship, gvnf)); assertTrue(engine.tx().traversal().V(gvnf).both("over-uses").hasNext()); assertTrue(engine.tx().traversal().V(vnfc).both("over-uses").hasNext()); @@ -264,7 +272,7 @@ public class DbSerializer_needsFakeRulesTest { relationship.setValue("relationship-data", relData); relationship.setValue("relationship-label", "re-uses"); - assertTrue(localDbser.createEdge(relationship, gvnf)); + assertNotNull(dbser.createEdge(relationship, gvnf)); assertTrue(engine.tx().traversal().V(gvnf).both("re-uses").hasNext()); assertTrue(engine.tx().traversal().V(vnfc).both("re-uses").hasNext()); assertEquals("Number of edges between vertexes is 1", Long.valueOf(1), @@ -280,9 +288,21 @@ public class DbSerializer_needsFakeRulesTest { engine.startTransaction(); Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "myvnf", "aai-uri", - "/network/generic-vnfs/generic-vnf/myvnf"); + "/network/generic-vnfs/generic-vnf/myvnf", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Vertex vnfc = engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", - "/network/vnfcs/vnfc/a-name"); + "/network/vnfcs/vnfc/a-name", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); edgeSer.addEdge(graph.traversal(), gvnf, vnfc, "uses"); Introspector relData = loader.introspectorFromName("relationship-data"); @@ -297,7 +317,7 @@ public class DbSerializer_needsFakeRulesTest { relationship.setValue("relationship-label", "re-uses"); - assertTrue(localDbser.createEdge(relationship, gvnf)); + assertNotNull(dbser.createEdge(relationship, gvnf)); assertTrue(engine.tx().traversal().V(gvnf).both("re-uses").hasNext()); assertTrue(engine.tx().traversal().V(vnfc).both("re-uses").hasNext()); assertTrue(engine.tx().traversal().V(gvnf).both("uses").hasNext()); @@ -317,9 +337,21 @@ public class DbSerializer_needsFakeRulesTest { engine.startTransaction(); Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "myvnf", "aai-uri", - "/network/generic-vnfs/generic-vnf/myvnf"); + "/network/generic-vnfs/generic-vnf/myvnf", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Vertex vnfc = engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", - "/network/vnfcs/vnfc/a-name"); + "/network/vnfcs/vnfc/a-name", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Introspector relData = loader.introspectorFromName("relationship-data"); relData.setValue("relationship-key", "vnfc.vnfc-name"); @@ -330,7 +362,7 @@ public class DbSerializer_needsFakeRulesTest { relationship.setValue("relationship-data", relData); localDbser.createEdge(relationship, gvnf); - assertTrue(localDbser.createEdge(relationship, gvnf)); + assertNotNull(dbser.createEdge(relationship, gvnf)); assertTrue(engine.tx().traversal().V(gvnf).both("uses").hasNext()); assertTrue(engine.tx().traversal().V(vnfc).both("uses").hasNext()); assertEquals("Number of edges between vertexes is 1", Long.valueOf(1), @@ -348,9 +380,21 @@ public class DbSerializer_needsFakeRulesTest { engine.startTransaction(); Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "myvnf", "aai-uri", - "/network/generic-vnfs/generic-vnf/myvnf"); + "/network/generic-vnfs/generic-vnf/myvnf", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Vertex vnfc = engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", - "/network/vnfcs/vnfc/a-name"); + "/network/vnfcs/vnfc/a-name", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); edgeSer.addEdge(graph.traversal(), gvnf, vnfc, "uses"); edgeSer.addEdge(graph.traversal(), gvnf, vnfc, "re-uses"); edgeSer.addEdge(graph.traversal(), gvnf, vnfc, "over-uses"); @@ -363,7 +407,7 @@ public class DbSerializer_needsFakeRulesTest { relationship.setValue("related-link", "/network/vnfcs/vnfc/a-name"); relationship.setValue("relationship-data", relData); - assertTrue(localDbser.deleteEdge(relationship, gvnf)); + assertTrue(localDbser.deleteEdge(relationship, gvnf).isPresent()); assertFalse("generic-vnf has no edge uses", engine.tx().traversal().V(gvnf).both("uses").hasNext()); assertFalse("vnfc has no edge uses", engine.tx().traversal().V(vnfc).both("uses").hasNext()); assertTrue("generic-vnf has edge re-uses", engine.tx().traversal().V(gvnf).both("re-uses").hasNext()); @@ -386,9 +430,21 @@ public class DbSerializer_needsFakeRulesTest { engine.startTransaction(); Vertex gvnf = engine.tx().addVertex("aai-node-type", "generic-vnf", "vnf-id", "myvnf", "aai-uri", - "/network/generic-vnfs/generic-vnf/myvnf"); + "/network/generic-vnfs/generic-vnf/myvnf", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Vertex vnfc = engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", - "/network/vnfcs/vnfc/a-name"); + "/network/vnfcs/vnfc/a-name", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); edgeSer.addEdge(graph.traversal(), gvnf, vnfc, "uses"); edgeSer.addEdge(graph.traversal(), gvnf, vnfc, "re-uses"); edgeSer.addEdge(graph.traversal(), gvnf, vnfc, "over-uses"); @@ -402,7 +458,7 @@ public class DbSerializer_needsFakeRulesTest { relationship.setValue("relationship-data", relData); relationship.setValue("relationship-label", "re-uses"); - assertTrue(localDbser.deleteEdge(relationship, gvnf)); + assertTrue(localDbser.deleteEdge(relationship, gvnf).isPresent()); assertTrue("generic-vnf has edge uses", engine.tx().traversal().V(gvnf).both("uses").hasNext()); assertTrue("vnfc has edge uses", engine.tx().traversal().V(vnfc).both("uses").hasNext()); assertFalse("generic-vnf has no edge re-uses", engine.tx().traversal().V(gvnf).both("re-uses").hasNext()); @@ -456,7 +512,12 @@ public class DbSerializer_needsFakeRulesTest { engine.startTransaction(); - engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name"); + engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name", "aai-uuid", "b", + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Introspector relationship = loader.introspectorFromName("relationship"); relationship.setValue("related-to", "vnfc"); @@ -505,7 +566,13 @@ public class DbSerializer_needsFakeRulesTest { engine.startTransaction(); - engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name"); + engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Introspector relationship = loader.introspectorFromName("relationship"); relationship.setValue("related-to", "vnfc"); @@ -585,7 +652,13 @@ public class DbSerializer_needsFakeRulesTest { DBSerializer localDbser = getDBSerializerWithSpecificEdgeRules(); engine.startTransaction(); - engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name"); + engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Introspector relationship; Introspector relationshipList; @@ -652,7 +725,13 @@ public class DbSerializer_needsFakeRulesTest { DBSerializer localDbser = getDBSerializerWithSpecificEdgeRules(); engine.startTransaction(); - engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name"); + engine.tx().addVertex("aai-node-type", "vnfc", "vnfc-name", "a-name", "aai-uri", "/network/vnfcs/vnfc/a-name", + AAIProperties.AAI_UUID, UUID.randomUUID().toString(), + AAIProperties.CREATED_TS, 123, + AAIProperties.SOURCE_OF_TRUTH, "sot", + AAIProperties.RESOURCE_VERSION, "123", + AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot", + AAIProperties.LAST_MOD_TS, 333); Introspector relationship; Introspector relationshipList; @@ -713,10 +792,8 @@ public class DbSerializer_needsFakeRulesTest { } - private DBSerializer getDBSerializerWithSpecificEdgeRules() - throws NoSuchFieldException, AAIException, IllegalAccessException { + private DBSerializer getDBSerializerWithSpecificEdgeRules() throws AAIException { - DBSerializer localDbser = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST"); - return localDbser; + return new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST"); } } diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/EdgerPairCanBeBothCousinAndParentChildTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/EdgerPairCanBeBothCousinAndParentChildTest.java new file mode 100644 index 00000000..d00408e8 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/EdgerPairCanBeBothCousinAndParentChildTest.java @@ -0,0 +1,234 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.db; + +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraphFactory; +import org.junit.*; +import org.junit.rules.ExpectedException; +import org.onap.aai.AAISetup; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.serialization.engines.JanusGraphDBEngine; +import org.onap.aai.serialization.engines.QueryStyle; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.setup.SchemaVersion; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; + +import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class EdgerPairCanBeBothCousinAndParentChildTest extends AAISetup { + + // to use, set thrown.expect to whatever your test needs + // this line establishes default of expecting no exception to be thrown + @Rule + public ExpectedException thrown = ExpectedException.none(); + + protected static Graph graph; + + @Autowired + protected EdgeSerializer edgeSer; + @Autowired + protected EdgeIngestor ei; + + private SchemaVersion version; + private final ModelType introspectorFactoryType = ModelType.MOXY; + private Loader loader; + private TransactionalGraphEngine engine; + + public QueryStyle queryStyle = QueryStyle.TRAVERSAL_URI; + + public static final String SOURCE_OF_TRUTH = "EdgerPairCanBeBothCousinAndParentChildTest"; + private static final String gvnfAUri = "/network/generic-vnfs/generic-vnf/gvnf-a" + SOURCE_OF_TRUTH; + private static final String lagIntAUri = gvnfAUri + "/lag-interfaces/lag-interface/lagint-a"; + private static final String lintUri = lagIntAUri + "/l-interfaces/l-interface/lint"; + + private static final String gvnfBUri = "/network/generic-vnfs/generic-vnf/gvnf-b" + SOURCE_OF_TRUTH; + private static final String lagIntBUri = gvnfBUri + "/lag-interfaces/lag-interface/lagint-b"; + + @BeforeClass + public static void init() { + graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + + } + + @Before + public void setup() throws UnsupportedEncodingException, AAIException, URISyntaxException { + version = schemaVersions.getDefaultVersion(); + loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); + engine = new JanusGraphDBEngine(queryStyle, loader); + initData(); + } + + @After + public void cleanup() { + engine.rollback(); + } + + /** + * Using latest version (see schema-ingest.properties) + * Create generic-vnf with lag-interface that has an l-interface + * Create generic-vnf with lag-interface relationship the l-interface + */ + private void initData() throws UnsupportedEncodingException, AAIException, URISyntaxException { + engine.startTransaction(); + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + + Introspector gvnf = loader.introspectorFromName("generic-vnf"); + gvnf.setValue("vnf-id", "gvnf-a" + SOURCE_OF_TRUTH); + gvnf.setValue("vnf-name", "gvnf" + SOURCE_OF_TRUTH + "-name"); + + Introspector lagInt = loader.introspectorFromName("lag-interface"); + lagInt.setValue("interface-name", "lagint-a"); + + Introspector lint = loader.introspectorFromName("l-interface"); + lint.setValue("interface-name", "lint"); + + Introspector lagints = loader.introspectorFromName("lag-interfaces"); + Introspector lints = loader.introspectorFromName("l-interfaces"); + + lints.setValue("l-interface", Collections.singletonList(lint.getUnderlyingObject())); + lagInt.setValue("l-interfaces", lints.getUnderlyingObject()); + lagints.setValue("lag-interface", Collections.singletonList(lagInt.getUnderlyingObject())); + gvnf.setValue("lag-interfaces", lagints.getUnderlyingObject()); + + + + Vertex gvnfV = serializer.createNewVertex(gvnf); + QueryParser uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(gvnfAUri)); + serializer.serializeToDb(gvnf, gvnfV, uriQuery, "generic-vnf", gvnf.marshal(false)); + + assertTrue("generic-vnf-a created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, gvnfAUri) + .hasNext()); + assertTrue("lag-int-a created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lagIntAUri) + .hasNext()); + assertTrue("l-int created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lintUri) + .hasNext()); + + + + gvnf = loader.introspectorFromName("generic-vnf"); + gvnf.setValue("vnf-id", "gvnf-b" + SOURCE_OF_TRUTH); + gvnf.setValue("vnf-name", "gvnf" + SOURCE_OF_TRUTH + "-name"); + + lagInt = loader.introspectorFromName("lag-interface"); + lagInt.setValue("interface-name", "lagint-b"); + Introspector relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-link", lintUri); + Introspector relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", Collections.singletonList(relationship.getUnderlyingObject())); + lagInt.setValue("relationship-list", relationshipList.getUnderlyingObject()); + + lagints = loader.introspectorFromName("lag-interfaces"); + lagints.setValue("lag-interface", Collections.singletonList(lagInt.getUnderlyingObject())); + gvnf.setValue("lag-interfaces", lagints.getUnderlyingObject()); + + gvnfV = serializer.createNewVertex(gvnf); + uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(gvnfAUri)); + serializer.serializeToDb(gvnf, gvnfV, uriQuery, "generic-vnf", gvnf.marshal(false)); + + engine.tx().traversal().V().forEachRemaining(v -> System.out.println(v.<String>value(AAIProperties.AAI_URI))); + assertTrue("generic-vnf-b created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, gvnfBUri) + .hasNext()); + assertTrue("lag-int-b created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lagIntBUri) + .hasNext()); + assertTrue("lag-interface relationship l-interface created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lagIntBUri) + .both() + .has(AAIProperties.AAI_URI, lintUri) + .hasNext()); + } + + + @Test + public void verifyReadOfGenericVnfATest() throws AAIException, UnsupportedEncodingException { + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String gvnfALatestView = serializer.getLatestVersionView( + engine.tx().traversal().V().has(AAIProperties.AAI_URI, gvnfAUri).next()).marshal(false); + + assertThat(gvnfALatestView, + hasJsonPath( + "$.lag-interfaces.lag-interface[*]", + hasSize(1) + )); + assertThat(gvnfALatestView, + hasJsonPath( + "$.lag-interfaces.lag-interface[*].l-interfaces.l-interface[*]", + hasSize(1) + )); + assertThat(gvnfALatestView, + hasJsonPath( + "$.lag-interfaces.lag-interface[*].l-interfaces.l-interface[*].relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + schemaVersions.getDefaultVersion() + lagIntBUri + ) + )); + } + + @Test + public void verifyReadOfGenericVnfBTest() throws AAIException, UnsupportedEncodingException { + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String gvnfBLatestView = serializer.getLatestVersionView( + engine.tx().traversal().V().has(AAIProperties.AAI_URI, gvnfBUri).next()).marshal(false); + + assertThat(gvnfBLatestView, + hasJsonPath( + "$.lag-interfaces.lag-interface[*]", + hasSize(1) + )); + assertThat(gvnfBLatestView, + not(hasJsonPath( + "$.lag-interfaces.lag-interface[*].l-interfaces.l-interface[*]" + ))); + assertThat(gvnfBLatestView, + hasJsonPath( + "$.lag-interfaces.lag-interface[*].relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + schemaVersions.getDefaultVersion() + lintUri + ) + )); + } + +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/ImpliedDeleteUnitTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/ImpliedDeleteUnitTest.java new file mode 100644 index 00000000..20e300a1 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/ImpliedDeleteUnitTest.java @@ -0,0 +1,331 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.serialization.db; + +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.hamcrest.CoreMatchers; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.serialization.engines.query.QueryEngine; +import org.onap.aai.util.AAIConstants; +import org.springframework.boot.test.rule.OutputCapture; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Matchers.eq; + +public class ImpliedDeleteUnitTest { + + private TransactionalGraphEngine mockEngine; + private DBSerializer mockSerializer; + + private ImpliedDelete impliedDelete; + + @Rule + public final OutputCapture outputCapture = new OutputCapture(); + + @Before + public void setup(){ + mockEngine = Mockito.mock(TransactionalGraphEngine.class); + mockSerializer = Mockito.mock(DBSerializer.class); + impliedDelete = Mockito.spy(new ImpliedDelete(mockEngine, mockSerializer)); + } + + // aai.implied.delete.whitelist.sdnc=* + @Test + public void testImpliedDeleteWhenUserIsAllowedToInvokeAnyMethod() throws AAIException { + + QueryEngine mockQueryEngine = Mockito.mock(QueryEngine.class); + + Mockito + .doReturn("*") + .when(impliedDelete) + .get(AAIConstants.AAI_IMPLIED_DELETE_WHITELIST + "sdnc",""); + + Mockito.when(mockEngine.getQueryEngine()).thenReturn(mockQueryEngine); + + TinkerGraph graph = TinkerGraph.open(); + + Vertex vserver = graph.addVertex("vertex"); + vserver.property("vserver-id", "some-id"); + + Vertex volume = graph.addVertex("vertex"); + volume.property("volume-id", "some-id"); + + List<Vertex> vertices = new ArrayList<>(); + vertices.add(volume); + + impliedDelete.execute(vserver.id(), "SDNC", "vserver", vertices); + + } + + // aai.implied.delete.whitelist.sdnc='vserver' + @Test + public void testImpliedDeleteWhenUserIsAllowedToInvokeCertainMethod() throws AAIException { + + QueryEngine mockQueryEngine = Mockito.mock(QueryEngine.class); + + Mockito + .doReturn("'vserver'") + .when(impliedDelete) + .get(AAIConstants.AAI_IMPLIED_DELETE_WHITELIST + "sdnc",""); + + Mockito.when(mockEngine.getQueryEngine()).thenReturn(mockQueryEngine); + + TinkerGraph graph = TinkerGraph.open(); + + Vertex vserver = graph.addVertex("vertex"); + vserver.property("vserver-id", "some-id"); + + Vertex volume = graph.addVertex("vertex"); + volume.property("volume-id", "some-id"); + + List<Vertex> vertices = new ArrayList<>(); + vertices.add(volume); + + impliedDelete.execute(vserver.id(), "SDNC", "vserver", vertices); + } + + // aai.implied.delete.whitelist.sdnc='vserver' + @Test + public void testImpliedDeleteWhenUserIsAllowedAndTryVariationsOfSOTValueSDNC() throws AAIException { + + QueryEngine mockQueryEngine = Mockito.mock(QueryEngine.class); + + Mockito + .doReturn("'vserver'") + .when(impliedDelete) + .get(AAIConstants.AAI_IMPLIED_DELETE_WHITELIST + "sdnc",""); + + Mockito.when(mockEngine.getQueryEngine()).thenReturn(mockQueryEngine); + + TinkerGraph graph = TinkerGraph.open(); + + Vertex vserver = graph.addVertex("vertex"); + vserver.property("vserver-id", "some-id"); + + Vertex volume = graph.addVertex("vertex"); + volume.property("volume-id", "some-id"); + + List<Vertex> vertices = new ArrayList<>(); + vertices.add(volume); + + impliedDelete.execute(vserver.id(), "SDNC", "vserver", vertices); + impliedDelete.execute(vserver.id(), "sDNC", "vserver", vertices); + impliedDelete.execute(vserver.id(), "sdNC", "vserver", vertices); + impliedDelete.execute(vserver.id(), "sdnC", "vserver", vertices); + impliedDelete.execute(vserver.id(), "sdnc", "vserver", vertices); + } + + // aai.implied.delete.whitelist.sdnc='vserver','vce','pserver' + @Test + public void testImpliedDeleteWhenUserIsAllowedToInvokeMultipleMethods() throws AAIException { + + QueryEngine mockQueryEngine = Mockito.mock(QueryEngine.class); + + Mockito + .doReturn("'vce','pserver','vserver','cloud-region'") + .when(impliedDelete) + .get(AAIConstants.AAI_IMPLIED_DELETE_WHITELIST + "sdnc",""); + + Mockito.when(mockEngine.getQueryEngine()).thenReturn(mockQueryEngine); + + TinkerGraph graph = TinkerGraph.open(); + + Vertex vserver = graph.addVertex("vertex"); + vserver.property("vserver-id", "some-id"); + + Vertex volume = graph.addVertex("vertex"); + volume.property("volume-id", "some-id"); + + List<Vertex> vertices = new ArrayList<>(); + vertices.add(volume); + + impliedDelete.execute(vserver.id(), "SDNC", "vserver", vertices); + } + + // aai.implied.delete.whitelist.sdnc='vserver','vce','pserver' + @Test + public void testImpliedDeleteWhenUserIsAllowedToInvokeMultipleMethodsAndDeletableReturnsMultipleVertexes() + throws AAIException, UnsupportedEncodingException { + + QueryEngine mockQueryEngine = Mockito.mock(QueryEngine.class); + + // On a spy the syntax should be doReturn => when => method to spy + // On a mock the syntax should be when => thenReturn|thenAnswer + Mockito + .doReturn("'vserver'") + .when(impliedDelete) + .get(AAIConstants.AAI_IMPLIED_DELETE_WHITELIST + "sdnc",""); + + + Introspector mockIntrospector = Mockito.mock(Introspector.class); + + Mockito.when(mockEngine.getQueryEngine()).thenReturn(mockQueryEngine); + + TinkerGraph graph = TinkerGraph.open(); + + Vertex vserver = graph.addVertex("vertex"); + vserver.property("vserver-id", "some-id"); + + Vertex volume1 = graph.addVertex("vertex"); + volume1.property("volume-id", "volume-1"); + + Vertex volume2 = graph.addVertex("vertex"); + volume1.property("volume-id", "volume-2"); + + Vertex volume3 = graph.addVertex("vertex"); + volume1.property("volume-id", "volume-3"); + + Vertex volume4 = graph.addVertex("vertex"); + volume1.property("volume-id", "volume-4"); + + List<Vertex> vertices = new ArrayList<>(); + + vertices.add(volume1); + vertices.add(volume2); + vertices.add(volume3); + vertices.add(volume4); + + Mockito + .when(mockQueryEngine.findDeletable(Mockito.anyList())) + .thenReturn(vertices); + + Mockito + .when(mockSerializer.getLatestVersionView(Mockito.anyObject())) + .thenReturn(mockIntrospector); + + Mockito + .when(mockIntrospector.marshal(false)) + .thenReturn("{\"volume-id\":\"volume-1\"}") + .thenReturn("{\"volume-id\":\"volume-2\"}") + .thenReturn("{\"volume-id\":\"volume-3\"}") + .thenReturn("{\"volume-id\":\"volume-4\"}"); + + impliedDelete.execute(vserver.id(), "SDNC", "vserver", vertices); + } + + // aai.implied.delete.whitelist.sdnc= + @Test(expected = AAIException.class) + public void testImpliedDeleteWhenUserIsNotAllowedToDelete() throws AAIException { + + QueryEngine mockQueryEngine = Mockito.mock(QueryEngine.class); + + Mockito + .doReturn("") + .when(impliedDelete) + .get(AAIConstants.AAI_IMPLIED_DELETE_WHITELIST + "sdnc",""); + + Mockito.when(mockEngine.getQueryEngine()).thenReturn(mockQueryEngine); + + TinkerGraph graph = TinkerGraph.open(); + + Vertex vserver = graph.addVertex("vertex"); + vserver.property("vserver-id", "some-id"); + + Vertex volume = graph.addVertex("vertex"); + volume.property("volume-id", "some-id"); + + List<Vertex> vertices = new ArrayList<>(); + vertices.add(volume); + + impliedDelete.execute(vserver.id(), "SDNC", "vserver", vertices); + } + + // aai.implied.delete.whitelist.sdnc='vce' + @Test(expected = AAIException.class) + public void testImpliedDeleteWhenUserIsAllowedToDeleteVceChildrenButRequestedToDeleteVserverChildren() throws AAIException { + + QueryEngine mockQueryEngine = Mockito.mock(QueryEngine.class); + + Mockito + .doReturn("'vce'") + .when(impliedDelete) + .get(AAIConstants.AAI_IMPLIED_DELETE_WHITELIST + "sdnc",""); + + Mockito.when(mockEngine.getQueryEngine()).thenReturn(mockQueryEngine); + + TinkerGraph graph = TinkerGraph.open(); + + Vertex vserver = graph.addVertex("vertex"); + vserver.property("vserver-id", "some-id"); + + Vertex volume = graph.addVertex("vertex"); + volume.property("volume-id", "some-id"); + + List<Vertex> vertices = new ArrayList<>(); + vertices.add(volume); + + impliedDelete.execute(vserver.id(), "SDNC", "vserver", vertices); + } + + @Test + public void testImpliedDeleteWhenUserIsAllowedToDeleteAndPrintingDeletingVertexItThrowsExceptionVerifyLog() throws AAIException, UnsupportedEncodingException { + + QueryEngine mockQueryEngine = Mockito.mock(QueryEngine.class); + + // On a spy the syntax should be doReturn => when => method to spy + // On a mock the syntax should be when => thenReturn|thenAnswer + Mockito + .doReturn("'vserver'") + .when(impliedDelete) + .get(AAIConstants.AAI_IMPLIED_DELETE_WHITELIST + "sdnc",""); + + + Introspector mockIntrospector = Mockito.mock(Introspector.class); + + Mockito.when(mockEngine.getQueryEngine()).thenReturn(mockQueryEngine); + + TinkerGraph graph = TinkerGraph.open(); + + Vertex vserver = graph.addVertex("vertex"); + vserver.property("vserver-id", "some-id"); + + Vertex volume1 = graph.addVertex("vertex"); + volume1.property("volume-id", "volume-1"); + + List<Vertex> vertices = new ArrayList<>(); + + vertices.add(volume1); + + Mockito + .when(mockQueryEngine.findDeletable(Mockito.anyList())) + .thenReturn(vertices); + + Mockito + .when(mockSerializer.getLatestVersionView(Mockito.anyObject())) + .thenThrow(new RuntimeException("Unable to find node")); + + impliedDelete.execute(vserver.id(), "SDNC", "vserver", vertices); + + outputCapture.expect( + CoreMatchers.containsString("Encountered an exception during retrieval of vertex properties with vertex-id " + vserver.id()) + ); + } +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/OneToOneEdgeUpdateTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/OneToOneEdgeUpdateTest.java new file mode 100644 index 00000000..0c90c735 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/OneToOneEdgeUpdateTest.java @@ -0,0 +1,300 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.db; + +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraphFactory; +import org.junit.*; +import org.junit.rules.ExpectedException; +import org.onap.aai.AAISetup; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.serialization.engines.JanusGraphDBEngine; +import org.onap.aai.serialization.engines.QueryStyle; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.setup.SchemaVersion; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Collections; + +import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class OneToOneEdgeUpdateTest extends AAISetup { + + // to use, set thrown.expect to whatever your test needs + // this line establishes default of expecting no exception to be thrown + @Rule + public ExpectedException thrown = ExpectedException.none(); + + protected static Graph graph; + + @Autowired + protected EdgeSerializer edgeSer; + @Autowired + protected EdgeIngestor ei; + + private SchemaVersion version; + private final ModelType introspectorFactoryType = ModelType.MOXY; + private Loader loader; + private TransactionalGraphEngine engine; + + public QueryStyle queryStyle = QueryStyle.TRAVERSAL_URI; + + public static final String SOURCE_OF_TRUTH = "EdgerPairCanBeBothCousinAndParentChildTest"; + private static final String gvnfAUri = "/network/generic-vnfs/generic-vnf/gvnf-a" + SOURCE_OF_TRUTH; + private static final String lintUri = gvnfAUri + "/l-interfaces/l-interface/lint"; + private static final String lintAUri = gvnfAUri + "/l-interfaces/l-interface/lint-a"; + private static final String sriovVfUri = lintUri + "/sriov-vfs/sriov-vf/sriov-vf"; + private static final String sriovVfAUri = lintAUri + "/sriov-vfs/sriov-vf/sriov-vf-a"; + + private static final String gvnfBUri = "/network/generic-vnfs/generic-vnf/gvnf-b" + SOURCE_OF_TRUTH; + private static final String lIntBUri = gvnfBUri + "/l-interfaces/l-interface/lint-b"; + + @BeforeClass + public static void init() { + graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + + } + + @Before + public void setup() throws UnsupportedEncodingException, AAIException, URISyntaxException { + version = schemaVersions.getDefaultVersion(); + loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); + engine = new JanusGraphDBEngine(queryStyle, loader); + initData(); + } + + @After + public void cleanup() { + engine.rollback(); + } + + /** + * Using latest version (see schema-ingest.properties) - sriov-vf to l-interface is one ot one + * Create generic-vnf with l-interface that has an sriov-vf + * Create generic-vnf with l-interface relationship the sriov-vf + */ + private void initData() throws UnsupportedEncodingException, AAIException, URISyntaxException { + engine.startTransaction(); + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + + Introspector gvnf = loader.introspectorFromName("generic-vnf"); + gvnf.setValue("vnf-id", "gvnf-a" + SOURCE_OF_TRUTH); + gvnf.setValue("vnf-name", "gvnf" + SOURCE_OF_TRUTH + "-name"); + + Introspector lint = loader.introspectorFromName("l-interface"); + lint.setValue("interface-name", "lint"); + + Introspector sriovVf = loader.introspectorFromName("sriov-vf"); + sriovVf.setValue("pci-id", "sriov-vf"); + + Introspector sriovVfs = loader.introspectorFromName("sriov-vfs"); + sriovVfs.setValue("sriov-vf", Collections.singletonList(sriovVf.getUnderlyingObject())); + lint.setValue("sriov-vfs", sriovVfs.getUnderlyingObject()); + + Introspector lintA = loader.introspectorFromName("l-interface"); + lintA.setValue("interface-name", "lint-a"); + + Introspector sriovVfA = loader.introspectorFromName("sriov-vf"); + sriovVfA.setValue("pci-id", "sriov-vf-a"); + + sriovVfs = loader.introspectorFromName("sriov-vfs"); + sriovVfs.setValue("sriov-vf", Collections.singletonList(sriovVfA.getUnderlyingObject())); + lintA.setValue("sriov-vfs", sriovVfs.getUnderlyingObject()); + + Introspector lints = loader.introspectorFromName("l-interfaces"); + lints.setValue("l-interface", Arrays.asList(lint.getUnderlyingObject(), lintA.getUnderlyingObject())); + gvnf.setValue("l-interfaces", lints.getUnderlyingObject()); + + + System.out.println(gvnf.marshal(true)); + Vertex gvnfV = serializer.createNewVertex(gvnf); + QueryParser uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(gvnfAUri)); + serializer.serializeToDb(gvnf, gvnfV, uriQuery, "generic-vnf", gvnf.marshal(false)); + + assertTrue("generic-vnf-a created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, gvnfAUri) + .hasNext()); + assertTrue("l-int created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lintUri) + .hasNext()); + assertTrue("l-int-a created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lintAUri) + .hasNext()); + assertTrue("sriov-vf created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, sriovVfUri) + .hasNext()); + assertTrue("sriov-vf-a created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, sriovVfAUri) + .hasNext()); + + + gvnf = loader.introspectorFromName("generic-vnf"); + gvnf.setValue("vnf-id", "gvnf-b" + SOURCE_OF_TRUTH); + gvnf.setValue("vnf-name", "gvnf" + SOURCE_OF_TRUTH + "-name"); + + lint = loader.introspectorFromName("l-interface"); + lint.setValue("interface-name", "lint-b"); + Introspector relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-link", sriovVfUri); + Introspector relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", Collections.singletonList(relationship.getUnderlyingObject())); + lint.setValue("relationship-list", relationshipList.getUnderlyingObject()); + + lints = loader.introspectorFromName("l-interfaces"); + lints.setValue("l-interface", Collections.singletonList(lint.getUnderlyingObject())); + gvnf.setValue("l-interfaces", lints.getUnderlyingObject()); + + gvnfV = serializer.createNewVertex(gvnf); + uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(gvnfAUri)); + serializer.serializeToDb(gvnf, gvnfV, uriQuery, "generic-vnf", gvnf.marshal(false)); + + engine.tx().traversal().V().forEachRemaining(v -> System.out.println(v.<String>value(AAIProperties.AAI_URI))); + assertTrue("generic-vnf-b created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, gvnfBUri) + .hasNext()); + assertTrue("l-int-b created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lIntBUri) + .hasNext()); + assertTrue("l-interface relationship sriov-vf created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lIntBUri) + .both() + .has(AAIProperties.AAI_URI, sriovVfUri) + .hasNext()); + + } + + + @Test + public void verifyReadOfGenericVnfATest() throws AAIException, UnsupportedEncodingException { + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String gvnfALatestView = serializer.getLatestVersionView( + engine.tx().traversal().V().has(AAIProperties.AAI_URI, gvnfAUri).next()).marshal(false); + + assertThat(gvnfALatestView, + hasJsonPath( + "$.l-interfaces.l-interface[*]", + hasSize(2) + )); + assertThat(gvnfALatestView, + hasJsonPath( + "$.l-interfaces.l-interface[*].sriov-vfs.sriov-vf[*]", + hasSize(2) + )); + assertThat(gvnfALatestView, + hasJsonPath( + "$.l-interfaces.l-interface[*].sriov-vfs.sriov-vf[*].relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + schemaVersions.getDefaultVersion() + lIntBUri + ) + )); + } + + @Test + public void verifyReadOfGenericVnfBTest() throws AAIException, UnsupportedEncodingException { + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String gvnfBLatestView = serializer.getLatestVersionView( + engine.tx().traversal().V().has(AAIProperties.AAI_URI, gvnfBUri).next()).marshal(false); + + assertThat(gvnfBLatestView, + hasJsonPath( + "$.l-interfaces.l-interface[*]", + hasSize(1) + )); + assertThat(gvnfBLatestView, + not(hasJsonPath( + "$.l-interfaces.l-interface[*].sriov-vfs.sriov-vf[*]" + ))); + assertThat(gvnfBLatestView, + hasJsonPath( + "$.l-interfaces.l-interface[*].relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + schemaVersions.getDefaultVersion() + sriovVfUri + ) + )); + } + + @Test + public void replaceRelationshipToSriovVfTest() throws AAIException, UnsupportedEncodingException, URISyntaxException { + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + Introspector lint = serializer.getLatestVersionView( + engine.tx().traversal().V().has(AAIProperties.AAI_URI, lIntBUri).next()); + String lintView = lint.marshal(false); + + assertThat(lintView, + hasJsonPath( + "$.relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + schemaVersions.getDefaultVersion() + sriovVfUri + ) + )); + + Introspector relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-link", sriovVfAUri); + Introspector relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", Collections.singletonList(relationship.getUnderlyingObject())); + lint.setValue("relationship-list", relationshipList.getUnderlyingObject()); + + QueryParser uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(lIntBUri)); + serializer.serializeToDb(lint, engine.tx().traversal().V().has(AAIProperties.AAI_URI, lIntBUri).next(), + uriQuery, "generic-vnf", lint.marshal(false)); + } + + + @Test + public void createRelationshipForNonExistentRuleTest() throws AAIException, UnsupportedEncodingException, URISyntaxException { + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + Vertex gvnfAV = engine.tx().traversal().V().has(AAIProperties.AAI_URI, gvnfAUri).next(); + Introspector gvnfA = serializer.getLatestVersionView(gvnfAV); + Introspector relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-link", gvnfBUri); + Introspector relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", Collections.singletonList(relationship.getUnderlyingObject())); + gvnfA.setValue("relationship-list", relationshipList.getUnderlyingObject()); + QueryParser uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(gvnfAUri)); + try { + serializer.serializeToDb(gvnfA, gvnfAV, uriQuery, "generic-vnf", gvnfA.marshal(false)); + } catch (AAIException e) { + assertEquals("AAI_6120", e.getCode()); + assertThat(e.getMessage(), containsString("generic-vnf")); + } + } + +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/VersionedScenariosTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/VersionedScenariosTest.java new file mode 100644 index 00000000..8e77c549 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/VersionedScenariosTest.java @@ -0,0 +1,426 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.db; + +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraphFactory; +import org.junit.*; +import org.junit.rules.ExpectedException; +import org.onap.aai.AAISetup; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.serialization.engines.JanusGraphDBEngine; +import org.onap.aai.serialization.engines.QueryStyle; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.setup.SchemaVersion; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class VersionedScenariosTest extends AAISetup { + + // to use, set thrown.expect to whatever your test needs + // this line establishes default of expecting no exception to be thrown + @Rule + public ExpectedException thrown = ExpectedException.none(); + + protected static Graph graph; + + @Autowired + protected EdgeSerializer edgeSer; + @Autowired + protected EdgeIngestor ei; + + private SchemaVersion version; + private final ModelType introspectorFactoryType = ModelType.MOXY; + private Loader loader; + private TransactionalGraphEngine engine; + + public QueryStyle queryStyle = QueryStyle.TRAVERSAL_URI; + + public static final String SOURCE_OF_TRUTH = "VersionedScenariosTest"; + private static final String gvnfUri = "/network/generic-vnfs/generic-vnf/gvnf" + SOURCE_OF_TRUTH; + private static final String llDefaultUri = "/network/logical-links/logical-link/llDefault"; + private static final String lintSourceUri = gvnfUri + "/l-interfaces/l-interface/source"; + private static final String lintDestinationUri = gvnfUri + "/l-interfaces/l-interface/destination"; + private static final String llLabeledUri = "/network/logical-links/logical-link/llLabeled"; + + @BeforeClass + public static void init() { + graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + + } + + @Before + public void setup() throws UnsupportedEncodingException, AAIException, URISyntaxException { + version = schemaVersions.getDefaultVersion(); + loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version); + engine = new JanusGraphDBEngine(queryStyle, loader); + initData(); + } + + @After + public void cleanup() { + engine.rollback(); + } + + /** + * Using latest version (see schema-ingest.properties) + * Create generic-vnf with l-interfaces source, destination + * Create logical-link with relationship to interfaces source, destination (will use the default labels) + * Create logical-link with relationship to interfaces source, destination with specific labels + */ + private void initData() throws UnsupportedEncodingException, AAIException, URISyntaxException { + engine.startTransaction(); + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + + Introspector gvnf = loader.introspectorFromName("generic-vnf"); + gvnf.setValue("vnf-id", "gvnf" + SOURCE_OF_TRUTH); + gvnf.setValue("vnf-name", "gvnf" + SOURCE_OF_TRUTH + "-name"); + + Introspector lintSource = loader.introspectorFromName("l-interface"); + lintSource.setValue("interface-name", "source"); + + Introspector lintDestination = loader.introspectorFromName("l-interface"); + lintDestination.setValue("interface-name", "destination"); + + List<Object> lIntList = new ArrayList<>(); + lIntList.add(lintSource.getUnderlyingObject()); + lIntList.add(lintDestination.getUnderlyingObject()); + Introspector lints = loader.introspectorFromName("l-interfaces"); + lints.setValue("l-interface", lIntList); + gvnf.setValue("l-interfaces", lints.getUnderlyingObject()); + + Vertex gvnfV = serializer.createNewVertex(gvnf); + QueryParser uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(gvnfUri)); + serializer.serializeToDb(gvnf, gvnfV, uriQuery, "generic-vnf", gvnf.marshal(false)); + + assertTrue("generic-vnf created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, gvnfUri) + .hasNext()); + assertTrue("source created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lintSourceUri) + .hasNext()); + assertTrue("destination created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, lintDestinationUri) + .hasNext()); + + + + Introspector llDefault = loader.introspectorFromName("logical-link"); + llDefault.setValue("link-name", "llDefault"); + List<Object> relList = new ArrayList<>(); + Introspector relationship = loader.introspectorFromName("relationship"); + //relationship.setValue("related-to", "l-interface"); + relationship.setValue("related-link", lintSourceUri); + relList.add(relationship.getUnderlyingObject()); + relationship = loader.introspectorFromName("relationship"); + //relationship.setValue("related-to", "l-interface"); + relationship.setValue("related-link", lintDestinationUri); + relList.add(relationship.getUnderlyingObject()); + Introspector relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", relList); + llDefault.setValue("relationship-list", relationshipList.getUnderlyingObject()); + + Vertex llDefaultV = serializer.createNewVertex(llDefault); + uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(llDefaultUri)); + serializer.serializeToDb(llDefault, llDefaultV, uriQuery, "logical-link", llDefault.marshal(false)); + + assertTrue("logical-link created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, llDefaultUri) + .hasNext()); + assertTrue("default source relationship created",engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, llDefaultUri) + .both() + .has(AAIProperties.AAI_URI, lintSourceUri) + .hasNext()); + assertTrue("default destination relationship created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, llDefaultUri) + .both() + .has(AAIProperties.AAI_URI, lintDestinationUri) + .hasNext()); + + + Introspector llLabeled = loader.introspectorFromName("logical-link"); + llLabeled.setValue("link-name", "llLabeled"); + relList = new ArrayList<>(); + relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-to", "l-interface"); + relationship.setValue("relationship-label", "org.onap.relationships.inventory.Source"); + relationship.setValue("related-link", lintSourceUri); + relList.add(relationship.getUnderlyingObject()); + relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-to", "l-interface"); + relationship.setValue("relationship-label", "org.onap.relationships.inventory.Destination"); + relationship.setValue("related-link", lintDestinationUri); + relList.add(relationship.getUnderlyingObject()); + relationshipList = loader.introspectorFromName("relationship-list"); + relationshipList.setValue("relationship", relList); + llLabeled.setValue("relationship-list", relationshipList.getUnderlyingObject()); + + Vertex llLabeledV = serializer.createNewVertex(llLabeled); + uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(llLabeledUri)); + serializer.serializeToDb(llLabeled, llLabeledV, uriQuery, "logical-link", llLabeled.marshal(false)); + + assertTrue("logical-link created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, llLabeledUri) + .hasNext()); + assertTrue("labeled source relationship created",engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, llLabeledUri) + .both("org.onap.relationships.inventory.Source") + .has(AAIProperties.AAI_URI, lintSourceUri) + .hasNext()); + assertTrue("labeled destination relationship created", engine.tx().traversal().V() + .has(AAIProperties.AAI_URI, llLabeledUri) + .both("org.onap.relationships.inventory.Destination") + .has(AAIProperties.AAI_URI, lintDestinationUri) + .hasNext()); + } + + + @Test + public void verifyRelsOfLatestViewOfGenericVnf() throws AAIException, UnsupportedEncodingException { + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String gvnfLatestView = serializer.getLatestVersionView( + engine.tx().traversal().V().has(AAIProperties.AAI_URI, gvnfUri).next()).marshal(false); + assertThat(gvnfLatestView, + hasJsonPath( + "$.l-interfaces.l-interface[*].relationship-list.relationship[*]", + hasSize(4) + )); + assertThat(gvnfLatestView, + hasJsonPath( + "$.l-interfaces.l-interface[*].relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + schemaVersions.getDefaultVersion() + llDefaultUri, + "/aai/" + schemaVersions.getDefaultVersion() + llDefaultUri, + "/aai/" + schemaVersions.getDefaultVersion() + llLabeledUri, + "/aai/" + schemaVersions.getDefaultVersion() + llLabeledUri + ) + )); + assertThat(gvnfLatestView, + hasJsonPath( + "$.l-interfaces.l-interface[*].relationship-list.relationship[*].relationship-label", + containsInAnyOrder( + "tosca.relationships.network.LinksTo", + "tosca.relationships.network.LinksTo", + "org.onap.relationships.inventory.Source", + "org.onap.relationships.inventory.Destination") + )); + } + + @Test + public void verifyRelsOfLatestViewOfLLDefault() throws AAIException, UnsupportedEncodingException { + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String llDefaultLatestView = serializer.getLatestVersionView( + engine.tx().traversal().V().has(AAIProperties.AAI_URI, llDefaultUri).next()).marshal(false); + assertThat(llDefaultLatestView, + hasJsonPath( + "$.relationship-list.relationship[*]", + hasSize(2) + )); + assertThat(llDefaultLatestView, + hasJsonPath( + "$.relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + schemaVersions.getDefaultVersion() + lintSourceUri, + "/aai/" + schemaVersions.getDefaultVersion() + lintDestinationUri + ) + )); + assertThat(llDefaultLatestView, + hasJsonPath( + "$.relationship-list.relationship[*].relationship-label", + containsInAnyOrder("tosca.relationships.network.LinksTo","tosca.relationships.network.LinksTo") + )); + assertThat(llDefaultLatestView, + hasJsonPath( + "$.relationship-list.relationship[*].relationship-label", + not(contains("org.onap.relationships.inventory.Source", "org.onap.relationships.inventory.Destination")) + )); + + } + + @Test + public void verifyRelsOfLatestViewOfLLLabeled() throws AAIException, UnsupportedEncodingException { + DBSerializer serializer = new DBSerializer(version, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String llLabeledLatestView = serializer.getLatestVersionView( + engine.tx().traversal().V().has(AAIProperties.AAI_URI, llLabeledUri).next()).marshal(false); + assertThat(llLabeledLatestView, + hasJsonPath( + "$.relationship-list.relationship[*]", + hasSize(2) + )); + assertThat(llLabeledLatestView, + hasJsonPath( + "$.relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + schemaVersions.getDefaultVersion() + lintSourceUri, + "/aai/" + schemaVersions.getDefaultVersion() + lintDestinationUri + ) + )); + assertThat(llLabeledLatestView, + hasJsonPath( + "$.relationship-list.relationship[*].relationship-label", + not(containsInAnyOrder("tosca.relationships.network.LinksTo","tosca.relationships.network.LinksTo")) + )); + assertThat(llLabeledLatestView, + hasJsonPath( + "$.relationship-list.relationship[*].relationship-label", + contains("org.onap.relationships.inventory.Source", "org.onap.relationships.inventory.Destination") + )); + + } + + + @Test + public void verifyRelsOfOldViewOfGenericVnf() throws AAIException, UnsupportedEncodingException { + SchemaVersion oldVersion = new SchemaVersion("v11"); + Loader oldLoader = loaderFactory.getLoaderStrategy(introspectorFactoryType, oldVersion); + DBSerializer oldSerializer = new DBSerializer(oldVersion, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String gvnfOldView = oldSerializer.dbToObject( + Collections.singletonList(engine.tx().traversal().V().has(AAIProperties.AAI_URI, gvnfUri).next()), + oldLoader.introspectorFromName("generic-vnf"), + AAIProperties.MAXIMUM_DEPTH, false, "false") + .marshal(false); + assertThat(gvnfOldView, + hasJsonPath( + "$.l-interfaces.l-interface[*].relationship-list.relationship[*]", + hasSize(2) + )); + assertThat(gvnfOldView, + hasJsonPath( + "$.l-interfaces.l-interface[*].relationship-list.relationship[*].relationship-label", + emptyCollectionOf(String.class) + )); + assertThat(gvnfOldView, + hasJsonPath( + "$.l-interfaces.l-interface[*].relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + oldVersion + llDefaultUri, + "/aai/" + oldVersion + llDefaultUri + ) + )); + } + + @Test + public void verifyRelsOfOldViewOfLLDefault() throws AAIException, UnsupportedEncodingException { + SchemaVersion oldVersion = new SchemaVersion("v11"); + Loader oldLoader = loaderFactory.getLoaderStrategy(introspectorFactoryType, oldVersion); + DBSerializer oldSerializer = new DBSerializer(oldVersion, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String llDefaultOldView = oldSerializer.dbToObject( + Collections.singletonList(engine.tx().traversal().V().has(AAIProperties.AAI_URI, llDefaultUri).next()), + oldLoader.introspectorFromName("logical-link"), + AAIProperties.MAXIMUM_DEPTH, false, "false") + .marshal(false); + assertThat(llDefaultOldView, + hasJsonPath( + "$.relationship-list.relationship[*]", + hasSize(2) + )); + assertThat(llDefaultOldView, + hasJsonPath( + "$.relationship-list.relationship[*].relationship-label", + emptyCollectionOf(String.class) + )); + assertThat(llDefaultOldView, + hasJsonPath( + "$.relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + oldVersion + lintSourceUri, + "/aai/" + oldVersion + lintDestinationUri + ) + )); + + } + + @Test + public void verifyRelsOfOldViewOfLLLabeled() throws AAIException, UnsupportedEncodingException { + SchemaVersion oldVersion = new SchemaVersion("v11"); + Loader oldLoader = loaderFactory.getLoaderStrategy(introspectorFactoryType, oldVersion); + DBSerializer oldSerializer = new DBSerializer(oldVersion, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + String llLabeledtOldView = oldSerializer.dbToObject( + Collections.singletonList(engine.tx().traversal().V().has(AAIProperties.AAI_URI, llLabeledUri).next()), + oldLoader.introspectorFromName("logical-link"), + AAIProperties.MAXIMUM_DEPTH, false, "false") + .marshal(false); + assertThat(llLabeledtOldView, + not(hasJsonPath( + "$.relationship-list.relationship[*]" + ))); + } + + + @Test + public void useOldVersionToUpdatedGenericVnfAndVerifyLatestVersionRels() throws AAIException, UnsupportedEncodingException, URISyntaxException { + SchemaVersion oldVersion = new SchemaVersion("v11"); + Loader oldLoader = loaderFactory.getLoaderStrategy(introspectorFactoryType, oldVersion); + DBSerializer oldSerializer = new DBSerializer(oldVersion, engine, introspectorFactoryType, SOURCE_OF_TRUTH, AAIProperties.MINIMUM_DEPTH); + + Vertex oldGvnfV = engine.tx().traversal().V().has(AAIProperties.AAI_URI, gvnfUri).next(); + Introspector oldGvnf = oldSerializer.dbToObject( + Collections.singletonList(oldGvnfV), + oldLoader.introspectorFromName("generic-vnf"), + AAIProperties.MAXIMUM_DEPTH, false, "false"); + assertThat(oldGvnf.marshal(false), + hasJsonPath( + "$.l-interfaces.l-interface[*].relationship-list.relationship[*].related-link", + containsInAnyOrder( + "/aai/" + oldVersion + llDefaultUri, + "/aai/" + oldVersion + llDefaultUri + ) + )); + oldGvnf.setValue("in-maint", true); + QueryParser uriQuery = engine.getQueryBuilder().createQueryFromURI(new URI(gvnfUri)); + oldSerializer.serializeToDb(oldGvnf, oldGvnfV, uriQuery, "generic-vnf", oldGvnf.marshal(false)); + + verifyRelsOfLatestViewOfGenericVnf(); + verifyRelsOfOldViewOfGenericVnf(); + } + + + + +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/AggregateFormatTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/AggregateFormatTest.java new file mode 100644 index 00000000..0b6ffd9e --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/AggregateFormatTest.java @@ -0,0 +1,136 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.serialization.queryformats; + +import com.google.gson.JsonObject; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.aai.AAISetup; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.serialization.db.DBSerializer; +import org.onap.aai.serialization.db.EdgeSerializer; +import org.onap.aai.serialization.engines.JanusGraphDBEngine; +import org.onap.aai.serialization.engines.QueryStyle; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.onap.aai.serialization.queryformats.utils.UrlBuilder; +import org.onap.aai.setup.SchemaVersion; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; + +import java.util.*; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class AggregateFormatTest extends AAISetup { + + @Mock + private UrlBuilder urlBuilder; + + private Graph graph; + private TransactionalGraphEngine dbEngine; + private Loader loader; + private Aggregate aggregate; + private final ModelType factoryType = ModelType.MOXY; + + @Autowired + private EdgeSerializer rules; + + private SchemaVersion version; + private Vertex pserver; + private Vertex complex; + + @Before + public void setUp() throws Exception { + + version = schemaVersions.getDefaultVersion(); + + MockitoAnnotations.initMocks(this); + + graph = TinkerGraph.open(); + + Vertex pserver1 = + graph.addVertex(T.label, "pserver", T.id, "2", "aai-node-type", "pserver", "hostname", "hostname-1"); + Vertex complex1 = graph.addVertex(T.label, "complex", T.id, "3", "aai-node-type", "complex", + "physical-location-id", "physical-location-id-1", "country", "US"); + + GraphTraversalSource g = graph.traversal(); + rules.addEdge(g, pserver1, complex1); + + pserver = pserver1; + complex = complex1; + + System.setProperty("AJSC_HOME", "."); + System.setProperty("BUNDLECONFIG_DIR", "src/test/resources/bundleconfig-local"); + + createLoaderEngineSetup(); + } + + private void createLoaderEngineSetup() throws AAIException { + + if (loader == null) { + loader = loaderFactory.createLoaderForVersion(factoryType, version); + dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader)); + DBSerializer serializer = new DBSerializer(version, dbEngine, factoryType, "Junit"); + aggregate = new Aggregate.Builder(loader, serializer, urlBuilder).build(); + + TransactionalGraphEngine.Admin spyAdmin = spy(dbEngine.asAdmin()); + + when(dbEngine.tx()).thenReturn(graph); + when(dbEngine.asAdmin()).thenReturn(spyAdmin); + + when(spyAdmin.getReadOnlyTraversalSource()) + .thenReturn(graph.traversal().withStrategies(ReadOnlyStrategy.instance())); + when(spyAdmin.getTraversalSource()).thenReturn(graph.traversal()); + } + } + + @Test + public void run() throws AAIFormatVertexException { + assertNotNull(dbEngine.tx()); + System.out.println(dbEngine.tx()); + assertNotNull(graph.traversal()); + JsonObject json = aggregate.createPropertiesObject(pserver).get(); + json.entrySet().forEach((System.out::println)); + assertTrue(json.has("hostname")); + assertFalse(json.has("node-type")); + Map<String, List<String>> propMap = new HashMap<>(); + List<String> selectedProps = new ArrayList<String>( Arrays.asList("'physical-location-id'")); + propMap.put("complex",selectedProps); + JsonObject json1 = aggregate.createSelectedPropertiesObject(complex, propMap).get(); + json1.entrySet().forEach((System.out::println)); + assertFalse(json1.has("country")); + assertTrue(json1.has("physical-location-id")); + } +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/CountQuerySupportTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/CountQuerySupportTest.java index a2976e0c..e128c2f6 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/CountQuerySupportTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/CountQuerySupportTest.java @@ -20,15 +20,7 @@ package org.onap.aai.serialization.queryformats; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - import com.google.gson.JsonObject; - -import java.util.Arrays; -import java.util.List; - import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; import org.apache.tinkerpop.gremlin.structure.Graph; @@ -38,10 +30,8 @@ import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.AAISetup; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.ModelType; @@ -52,10 +42,16 @@ import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; -import org.onap.aai.serialization.queryformats.utils.UrlBuilder; import org.onap.aai.setup.SchemaVersion; import org.springframework.beans.factory.annotation.Autowired; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + public class CountQuerySupportTest extends AAISetup { @Autowired @@ -147,7 +143,7 @@ public class CountQuerySupportTest extends AAISetup { if (loader == null) { loader = loaderFactory.createLoaderForVersion(factoryType, version); // loader = LoaderFactory.createLoaderForVersion(factoryType, version); - dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, DBConnectionType.CACHED, loader)); + dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader)); serializer = new DBSerializer(version, dbEngine, factoryType, "Junit"); ff = new FormatFactory(loader, serializer, schemaVersions, basePath); @@ -159,7 +155,7 @@ public class CountQuerySupportTest extends AAISetup { when(dbEngine.asAdmin()).thenReturn(spyAdmin); when(spyAdmin.getReadOnlyTraversalSource()) - .thenReturn(graph.traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance()))); + .thenReturn(graph.traversal().withStrategies(ReadOnlyStrategy.instance())); when(spyAdmin.getTraversalSource()).thenReturn(graph.traversal()); } } diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/GraphSONTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/GraphSONTest.java index 847a45ed..22b500f8 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/GraphSONTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/GraphSONTest.java @@ -26,8 +26,8 @@ import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -63,7 +63,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @DirtiesContext public class GraphSONTest { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(GraphSONTest.class); + private static final Logger LOGGER = LoggerFactory.getLogger(GraphSONTest.class); private Graph graph; private Vertex v1; @@ -111,7 +111,7 @@ public class GraphSONTest { /** * Case where there is only one private edge - * + * * <pre> * { * "id": 21, @@ -167,7 +167,7 @@ public class GraphSONTest { /** * Case where there is one private edge and regular edge * with the same edge label name - * + * * <pre> * { * "id": 21, @@ -230,7 +230,7 @@ public class GraphSONTest { /** * Case where there is one private edge and regular edge to same label * And another regular edge to a different label - * + * * <pre> * { * "id": 21, @@ -328,7 +328,7 @@ public class GraphSONTest { /** * Case where there is one private edge and regular edge to same label * And another regular edge to a different label - * + * * <pre> * { * "id": 21, @@ -395,7 +395,7 @@ public class GraphSONTest { /** * Case where there is one private edge and regular edge to same label * And another regular edge to a different label - * + * * <pre> * { * "id": 21, diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/MultiFormatTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/MultiFormatTest.java index 9ac79ca8..a59b1147 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/MultiFormatTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/MultiFormatTest.java @@ -20,15 +20,8 @@ package org.onap.aai.serialization.queryformats; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.*; - import com.google.gson.JsonObject; import com.google.gson.JsonParser; - -import java.io.UnsupportedEncodingException; - import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; @@ -42,10 +35,10 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.AAISetup; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.ModelType; +import org.onap.aai.serialization.db.DBSerializer; import org.onap.aai.serialization.db.EdgeSerializer; import org.onap.aai.serialization.engines.JanusGraphDBEngine; import org.onap.aai.serialization.engines.QueryStyle; @@ -57,6 +50,13 @@ import org.onap.aai.setup.SchemaVersion; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; +import javax.ws.rs.core.MultivaluedHashMap; +import java.io.UnsupportedEncodingException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.*; + @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class MultiFormatTest extends AAISetup { @@ -79,7 +79,12 @@ public class MultiFormatTest extends AAISetup { private JsonObject expectedPathIdFormat = new JsonParser().parse( "{\"path\":[{\"resource-type\":\"generic-vnf\"},{\"resource-type\":\"vserver\"},{\"resource-type\":\"pserver\"},{\"resource-type\":\"complex\"}]}") .getAsJsonObject(); - + private JsonObject expectedAsTreeWithResourceFormat = new JsonParser().parse( + "{\"results\":[{\"generic-vnf\":{\"vnf-id\":\"vnf-id-1\",\"vnf-name\":\"vnf-name-1\",\"related-nodes\":[{\"vserver\":{\"vserver-id\":\"vserver-id-1\",\"vserver-name\":\"vserver-name-1\",\"related-nodes\":[{\"pserver\":{\"hostname\":\"hostname-1\"}}]}},{\"pserver\":{\"hostname\":\"hostname-2\",\"related-nodes\":[{\"complex\":{\"physical-location-id\":\"physical-location-id-2\",\"country\":\"US\"}}]}}]}}]}") + .getAsJsonObject(); + private JsonObject expectedAsTreeWithSimpleFormat = new JsonParser().parse( + "{\"results\":[{\"id\":\"0\",\"node-type\":\"generic-vnf\",\"url\":null,\"properties\":{\"vnf-id\":\"vnf-id-1\",\"vnf-name\":\"vnf-name-1\"},\"related-to\":[{\"id\":\"1\",\"relationship-label\":\"tosca.relationships.HostedOn\",\"node-type\":\"vserver\",\"url\":null},{\"id\":\"5\",\"relationship-label\":\"tosca.relationships.HostedOn\",\"node-type\":\"pserver\",\"url\":null}],\"related-nodes\":[{\"id\":\"1\",\"node-type\":\"vserver\",\"url\":null,\"properties\":{\"vserver-id\":\"vserver-id-1\",\"vserver-name\":\"vserver-name-1\"},\"related-to\":[{\"id\":\"0\",\"relationship-label\":\"tosca.relationships.HostedOn\",\"node-type\":\"generic-vnf\",\"url\":null},{\"id\":\"2\",\"relationship-label\":\"tosca.relationships.HostedOn\",\"node-type\":\"pserver\",\"url\":null}],\"related-nodes\":[{\"id\":\"2\",\"node-type\":\"pserver\",\"url\":null,\"properties\":{\"hostname\":\"hostname-1\"},\"related-to\":[{\"id\":\"1\",\"relationship-label\":\"tosca.relationships.HostedOn\",\"node-type\":\"vserver\",\"url\":null},{\"id\":\"3\",\"relationship-label\":\"org.onap.relationships.inventory.LocatedIn\",\"node-type\":\"complex\",\"url\":null}]}]},{\"id\":\"5\",\"node-type\":\"pserver\",\"url\":null,\"properties\":{\"hostname\":\"hostname-2\"},\"related-to\":[{\"id\":\"0\",\"relationship-label\":\"tosca.relationships.HostedOn\",\"node-type\":\"generic-vnf\",\"url\":null},{\"id\":\"6\",\"relationship-label\":\"org.onap.relationships.inventory.LocatedIn\",\"node-type\":\"complex\",\"url\":null}],\"related-nodes\":[{\"id\":\"6\",\"node-type\":\"complex\",\"url\":null,\"properties\":{\"physical-location-id\":\"physical-location-id-2\",\"country\":\"US\"},\"related-to\":[{\"id\":\"5\",\"relationship-label\":\"org.onap.relationships.inventory.LocatedIn\",\"node-type\":\"pserver\",\"url\":null}]}]}]}]}") + .getAsJsonObject(); @Before public void setUp() throws Exception { @@ -130,6 +135,42 @@ public class MultiFormatTest extends AAISetup { } @Test + public void testAsTreeParamAndSimpleFormat() + throws AAIFormatVertexException, AAIException, AAIFormatQueryResultFormatNotSupported { + + createLoaderEngineSetup(); + DBSerializer serializer = new DBSerializer(version, dbEngine, factoryType, "Junit"); + MultivaluedHashMap<String, String> params = new MultivaluedHashMap<>(); + params.add("as-tree", "true"); + SimpleFormat sf = new SimpleFormat(new RawFormat.Builder(loader, serializer, urlBuilder).isTree(true)); + + assertNotNull(dbEngine.tx()); + assertNotNull(dbEngine.asAdmin()); + + JsonObject json = sf.formatObject(resultTree).get(); + assertEquals(this.expectedAsTreeWithSimpleFormat, json); + + } + + @Test + public void testAsTreeParamAndResourceFormat() + throws AAIFormatVertexException, AAIException, AAIFormatQueryResultFormatNotSupported { + + createLoaderEngineSetup(); + DBSerializer serializer = new DBSerializer(version, dbEngine, factoryType, "Junit"); + MultivaluedHashMap<String, String> params = new MultivaluedHashMap<>(); + params.add("as-tree", "true"); + Resource sf = new Resource(new Resource.Builder(loader, serializer, urlBuilder, params).isTree(true)); + + assertNotNull(dbEngine.tx()); + assertNotNull(dbEngine.asAdmin()); + + JsonObject json = sf.formatObject(resultTree).get(); + assertEquals(this.expectedAsTreeWithResourceFormat, json); + } + + + @Test public void testPathResultQueryIdFormat() throws AAIFormatVertexException, AAIException, AAIFormatQueryResultFormatNotSupported { @@ -159,7 +200,7 @@ public class MultiFormatTest extends AAISetup { if (loader == null) { loader = loaderFactory.createLoaderForVersion(factoryType, version); // loader = LoaderFactory.createLoaderForVersion(factoryType, version); - dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, DBConnectionType.CACHED, loader)); + dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader)); TransactionalGraphEngine.Admin spyAdmin = spy(dbEngine.asAdmin()); @@ -167,7 +208,7 @@ public class MultiFormatTest extends AAISetup { when(dbEngine.asAdmin()).thenReturn(spyAdmin); when(spyAdmin.getReadOnlyTraversalSource()) - .thenReturn(graph.traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance()))); + .thenReturn(graph.traversal().withStrategies(ReadOnlyStrategy.instance())); when(spyAdmin.getTraversalSource()).thenReturn(graph.traversal()); } } diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/QueryFormatTestHelper.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/QueryFormatTestHelper.java index 03990b1d..f05e36dd 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/QueryFormatTestHelper.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/QueryFormatTestHelper.java @@ -46,7 +46,7 @@ public class QueryFormatTestHelper { public static void mockPathed(UrlBuilder mock) throws AAIFormatVertexException { Answer<String> answer = new Answer<String>() { public String answer(InvocationOnMock invocation) throws Throwable { - Vertex v = invocation.getArgument(0); + Vertex v = invocation.getArgumentAt(0, Vertex.class); return v.<String>property(AAIProperties.AAI_URI).orElse("urimissing"); } diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/RawFormatTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/RawFormatTest.java index 2d8c66c3..f88de4fb 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/RawFormatTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/RawFormatTest.java @@ -20,10 +20,7 @@ package org.onap.aai.serialization.queryformats; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - +import com.google.gson.JsonObject; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; import org.apache.tinkerpop.gremlin.structure.Graph; @@ -35,7 +32,6 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.AAISetup; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.ModelType; @@ -44,13 +40,18 @@ import org.onap.aai.serialization.db.EdgeSerializer; import org.onap.aai.serialization.engines.JanusGraphDBEngine; import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; -import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported; import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; import org.onap.aai.serialization.queryformats.utils.UrlBuilder; import org.onap.aai.setup.SchemaVersion; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; +import java.util.*; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class RawFormatTest extends AAISetup { @@ -70,8 +71,6 @@ public class RawFormatTest extends AAISetup { private Vertex pserver; private Vertex complex; - private DBSerializer serializer; - @Before public void setUp() throws Exception { @@ -100,39 +99,34 @@ public class RawFormatTest extends AAISetup { @Test public void verifyPserverRelatedToHasEdgeLabel() - throws AAIFormatVertexException, AAIException, AAIFormatQueryResultFormatNotSupported { - assertTrue(rawFormat.createRelationshipObject(pserver).get(0).getAsJsonObject().get("relationship-label") - .getAsString().equals("org.onap.relationships.inventory.LocatedIn")); + throws AAIFormatVertexException { + assertEquals("org.onap.relationships.inventory.LocatedIn", rawFormat.createRelationshipObject(pserver).get(0).getAsJsonObject().get("relationship-label").getAsString()); } @Test public void verifyPserverRelatedToComplexLabel() - throws AAIFormatVertexException, AAIException, AAIFormatQueryResultFormatNotSupported { - assertTrue(rawFormat.createRelationshipObject(pserver).get(0).getAsJsonObject().get("node-type").getAsString() - .equals("complex")); + throws AAIFormatVertexException { + assertEquals("complex", rawFormat.createRelationshipObject(pserver).get(0).getAsJsonObject().get("node-type").getAsString()); } @Test public void verifyComplexRelatedToHasEdgeLabel() - throws AAIFormatVertexException, AAIException, AAIFormatQueryResultFormatNotSupported { - assertTrue(rawFormat.createRelationshipObject(complex).get(0).getAsJsonObject().get("relationship-label") - .getAsString().equals("org.onap.relationships.inventory.LocatedIn")); + throws AAIFormatVertexException { + assertEquals("org.onap.relationships.inventory.LocatedIn", rawFormat.createRelationshipObject(complex).get(0).getAsJsonObject().get("relationship-label").getAsString()); } @Test public void verifyComplexRelatedToPserverLabel() - throws AAIFormatVertexException, AAIException, AAIFormatQueryResultFormatNotSupported { - assertTrue(rawFormat.createRelationshipObject(complex).get(0).getAsJsonObject().get("node-type").getAsString() - .equals("pserver")); + throws AAIFormatVertexException { + assertEquals("pserver", rawFormat.createRelationshipObject(complex).get(0).getAsJsonObject().get("node-type").getAsString()); } - public void createLoaderEngineSetup() throws AAIException { + private void createLoaderEngineSetup() throws AAIException { if (loader == null) { loader = loaderFactory.createLoaderForVersion(factoryType, version); - // loader = LoaderFactory.createLoaderForVersion(factoryType, version); - dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, DBConnectionType.CACHED, loader)); - serializer = new DBSerializer(version, dbEngine, factoryType, "Junit"); + dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader)); + DBSerializer serializer = new DBSerializer(version, dbEngine, factoryType, "Junit"); rawFormat = new RawFormat.Builder(loader, serializer, urlBuilder).build(); TransactionalGraphEngine.Admin spyAdmin = spy(dbEngine.asAdmin()); @@ -141,8 +135,27 @@ public class RawFormatTest extends AAISetup { when(dbEngine.asAdmin()).thenReturn(spyAdmin); when(spyAdmin.getReadOnlyTraversalSource()) - .thenReturn(graph.traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance()))); + .thenReturn(graph.traversal().withStrategies(ReadOnlyStrategy.instance())); when(spyAdmin.getTraversalSource()).thenReturn(graph.traversal()); } } + + @Test + public void run() throws AAIFormatVertexException { + assertNotNull(dbEngine.tx()); + System.out.println(dbEngine.tx()); + assertNotNull(graph.traversal()); + JsonObject json = rawFormat.createPropertiesObject(pserver).get(); + json.entrySet().forEach((System.out::println)); + assertTrue(json.has("hostname")); + Map<String, List<String>> propMap = new HashMap<>(); + List<String> selectedProps = new ArrayList<String>( Arrays.asList("'physical-location-id'")); + propMap.put("complex",selectedProps); + JsonObject json1 = rawFormat.createSelectedPropertiesObject(complex, propMap).get(); + json1.entrySet().forEach((System.out::println)); + assertFalse(json1.has("aai-node-type")); + assertTrue(json1.has("physical-location-id")); + } + + } diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceFormatTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceFormatTest.java index 1a301b33..a891230c 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceFormatTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceFormatTest.java @@ -20,18 +20,7 @@ package org.onap.aai.serialization.queryformats; -import static org.junit.Assert.*; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - import com.google.gson.JsonObject; - -import java.util.Arrays; - -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.core.MultivaluedMap; - -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.T; @@ -42,7 +31,6 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.AAISetup; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.ModelType; @@ -54,6 +42,14 @@ import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexExcepti import org.onap.aai.serialization.queryformats.utils.UrlBuilder; import org.springframework.test.annotation.DirtiesContext; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import java.util.Arrays; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class ResourceFormatTest extends AAISetup { @@ -144,7 +140,7 @@ public class ResourceFormatTest extends AAISetup { if (loader == null) { loader = loaderFactory.createLoaderForVersion(factoryType, schemaVersions.getAppRootVersion()); - dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, DBConnectionType.CACHED, loader)); + dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader)); TransactionalGraphEngine.Admin spyAdmin = spy(dbEngine.asAdmin()); @@ -152,7 +148,7 @@ public class ResourceFormatTest extends AAISetup { when(dbEngine.asAdmin()).thenReturn(spyAdmin); when(spyAdmin.getReadOnlyTraversalSource()) - .thenReturn(graph.traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance()))); + .thenReturn(graph.traversal().withStrategies(ReadOnlyStrategy.instance())); when(spyAdmin.getTraversalSource()).thenReturn(graph.traversal()); } } diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceWithSoTTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceWithSoTTest.java index 75fe6ec6..c2e5f814 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceWithSoTTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceWithSoTTest.java @@ -20,15 +20,7 @@ package org.onap.aai.serialization.queryformats; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - import com.google.gson.JsonObject; - -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; @@ -38,7 +30,6 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.AAISetup; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.ModelType; @@ -50,6 +41,10 @@ import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexExcepti import org.onap.aai.serialization.queryformats.utils.UrlBuilder; import org.onap.aai.setup.SchemaVersion; +import static org.junit.Assert.*; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + public class ResourceWithSoTTest extends AAISetup { @Mock private UrlBuilder urlBuilder; @@ -79,7 +74,7 @@ public class ResourceWithSoTTest extends AAISetup { graph = TinkerGraph.open(); - Long currentTimeMs = System.currentTimeMillis(); + long currentTimeMs = System.currentTimeMillis(); String timeNowInMs = Long.toString(currentTimeMs); // PUT / CREATE @@ -119,8 +114,7 @@ public class ResourceWithSoTTest extends AAISetup { // This test is to simulate a PUT request @Test public void testGetJsonFromVertexWithCreateVertex() throws AAIFormatVertexException, AAIException { - if (putVertex == null) - assertTrue("The vertex used for this test is null. Fail immediately.", false); + if (putVertex == null) fail("The vertex used for this test is null. Fail immediately."); JsonObject json = resourceWithSoT.getJsonFromVertex(putVertex).get(); assertEquals(jsonPutObj, json); @@ -129,10 +123,8 @@ public class ResourceWithSoTTest extends AAISetup { // This test is to simulate PATCH requests @Test public void testGetJsonFromVertexWithModifyVertex() throws AAIFormatVertexException, AAIException { - if (patchVertex1 == null) - assertTrue("The vertex 1 used for this test is null. Fail immediately.", false); - if (patchVertex2 == null) - assertTrue("The vertex 2 used for this test is null. Fail immediately.", false); + if (patchVertex1 == null) fail("The vertex 1 used for this test is null. Fail immediately."); + if (patchVertex2 == null) fail("The vertex 2 used for this test is null. Fail immediately."); // Differing Source of Truths will indicate that the action performed modified the vertex JsonObject json1 = resourceWithSoT.getJsonFromVertex(patchVertex1).get(); @@ -155,7 +147,7 @@ public class ResourceWithSoTTest extends AAISetup { if (loader == null) { loader = loaderFactory.createLoaderForVersion(factoryType, version); // loader = LoaderFactory.createLoaderForVersion(factoryType, version); - dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, DBConnectionType.CACHED, loader)); + dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader)); serializer = new DBSerializer(version, dbEngine, factoryType, "Junit"); resourceWithSoT = new ResourceWithSoT.Builder(loader, serializer, urlBuilder).build(); @@ -165,7 +157,7 @@ public class ResourceWithSoTTest extends AAISetup { when(dbEngine.asAdmin()).thenReturn(spyAdmin); when(spyAdmin.getReadOnlyTraversalSource()) - .thenReturn(graph.traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance()))); + .thenReturn(graph.traversal().withStrategies(ReadOnlyStrategy.instance())); when(spyAdmin.getTraversalSource()).thenReturn(graph.traversal()); } } diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/SimpleFormatTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/SimpleFormatTest.java index ab899c01..886a660b 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/SimpleFormatTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/SimpleFormatTest.java @@ -20,22 +20,7 @@ package org.onap.aai.serialization.queryformats; -import static org.junit.Assert.*; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; - import com.google.gson.JsonObject; - -import java.io.UnsupportedEncodingException; -import java.util.Arrays; - -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.core.MultivaluedMap; - -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.T; @@ -47,7 +32,6 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.AAISetup; -import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.ModelType; @@ -60,6 +44,15 @@ import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexExcepti import org.onap.aai.serialization.queryformats.utils.UrlBuilder; import org.springframework.test.annotation.DirtiesContext; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class SimpleFormatTest extends AAISetup { @@ -182,7 +175,7 @@ public class SimpleFormatTest extends AAISetup { if (loader == null) { loader = loaderFactory.createLoaderForVersion(factoryType, schemaVersions.getRelatedLinkVersion()); - dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, DBConnectionType.CACHED, loader)); + dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader)); TransactionalGraphEngine.Admin spyAdmin = spy(dbEngine.asAdmin()); @@ -190,7 +183,7 @@ public class SimpleFormatTest extends AAISetup { when(dbEngine.asAdmin()).thenReturn(spyAdmin); when(spyAdmin.getReadOnlyTraversalSource()) - .thenReturn(graph.traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance()))); + .thenReturn(graph.traversal().withStrategies(ReadOnlyStrategy.instance())); when(spyAdmin.getTraversalSource()).thenReturn(graph.traversal()); } } diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/utils/QueryParamInjectorTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/utils/QueryParamInjectorTest.java index 0b689d88..f039d7cb 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/utils/QueryParamInjectorTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/utils/QueryParamInjectorTest.java @@ -48,11 +48,11 @@ public class QueryParamInjectorTest { MockitoAnnotations.initMocks(this); QueryParamInjector injector = QueryParamInjector.getInstance(); - Builder b = new Builder(loader, serializer, urlBuilder); MultivaluedMap<String, String> params = new MultivaluedHashMap<>(); params.putSingle("nodesOnly", "true"); params.putSingle("depth", "10"); params.putSingle("invalid", "1000"); + Builder b = new Builder(loader, serializer, urlBuilder, params); injector.injectParams(b, params); assertEquals("is nodes only", true, b.isNodesOnly()); diff --git a/aai-core/src/test/java/org/onap/aai/stress/IndexStressTest.java b/aai-core/src/test/java/org/onap/aai/stress/IndexStressTest.java new file mode 100644 index 00000000..143004ac --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/stress/IndexStressTest.java @@ -0,0 +1,132 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.stress; + +import org.apache.commons.lang.RandomStringUtils; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraphTransaction; +import org.junit.Before; +import org.junit.Test; +import org.junit.Ignore; +import org.onap.aai.AAISetup; +import org.onap.aai.dbmap.AAIGraph; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.test.annotation.DirtiesContext; + +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +@Ignore("Run this only to test indexes limit") +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class IndexStressTest extends AAISetup { + + private static final Logger LOGGER = LoggerFactory.getLogger(IndexStressTest.class); + + @Before + public void setup(){ + AAIGraph.getInstance().getGraph(); + } + + @Test + public void testIndexStress(){ + JanusGraphTransaction tx = AAIGraph.getInstance().getGraph().newTransaction(); + + GraphTraversalSource g = tx.traversal(); + + Set<String> linkNameSet = new HashSet<>(); + Set<String> aaiUriSet = new HashSet<>(); + + int TOTAL_LINKS = 101000; + + for(int i = 0; i <TOTAL_LINKS; i++){ + + String linkName = generateName(linkNameSet); + aaiUriSet.add("/network/logical-links/logical-link/" + linkName); + + Vertex v = g.addV() + .property("aai-node-type", "logical-link") + .property("link-name", linkName) + .property("aai-uri", "/network/logical-links/logical-link/" + linkName) + .next(); + + if(i % 1000 == 0){ + LOGGER.debug("Committing up to index {}", i); + tx.commit(); + tx = AAIGraph.getInstance().getGraph().newTransaction(); + g = tx.traversal(); + } + } + + tx.commit(); + + tx = AAIGraph.getInstance().getGraph().newTransaction(); + g = tx.traversal(); + + int totalLinks= 0; + int totalLinksWithNodeType = 0; + int totalLinksUsingUri = 0; + + int index = 0; + for (String linkName : linkNameSet) { + + if(g.V().has("aai-node-type", "logical-link").has("link-name", linkName).hasNext()){ + totalLinksWithNodeType++; + } + + if(g.V().has("link-name", linkName).hasNext()){ + totalLinks++; + } + + if(g.V().has("aai-uri", "/network/logical-links/logical-link/" + linkName).hasNext()){ + totalLinksUsingUri++; + } + + index++; + + if(index%1000 == 0){ + LOGGER.debug("Processed {} many queries and has {} many to go", index, (TOTAL_LINKS-index)); + LOGGER.debug("Total links using linkname found: {}", totalLinks); + LOGGER.debug("Total links using nodetype and linkname found: {}", totalLinksWithNodeType); + LOGGER.debug("Total links using uri found: {}", totalLinksUsingUri); + } + } + + tx.rollback(); + + LOGGER.debug("Total links using linkname found: {}", totalLinks); + LOGGER.debug("Total links using nodetype and linkname found: {}", totalLinksWithNodeType); + LOGGER.debug("Total links using uri found: {}", totalLinksUsingUri); + } + + String generateName(Set<String> uniqueKeys){ + + while(true) { + String data = RandomStringUtils.randomAlphabetic(20); + if (!uniqueKeys.contains(data)){ + uniqueKeys.add(data); + return data; + } + } + } +} diff --git a/aai-core/src/test/java/org/onap/aai/transforms/XmlFormatTransformerTest.java b/aai-core/src/test/java/org/onap/aai/transforms/XmlFormatTransformerTest.java new file mode 100644 index 00000000..6d6ae194 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/transforms/XmlFormatTransformerTest.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.transforms; + +import org.junit.Before; +import org.junit.Test; +import org.onap.aai.PayloadUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +public class XmlFormatTransformerTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(XmlFormatTransformerTest.class); + + private XmlFormatTransformer xmlFormatTransformer; + + @Before + public void setup(){ + this.xmlFormatTransformer = new XmlFormatTransformer(); + } + + @Test + public void testTransformJsonToXml() throws IOException { + + String input = PayloadUtil.getResourcePayload("transform-results-to-result.json"); + String expected = PayloadUtil.getExpectedPayload("transform-json-to-xml.xml"); + // Remove all the whitespace in the xml + expected = expected.replaceAll("\\s", ""); + + LOGGER.debug("Converting the following input to xml: {}", input); + String output = xmlFormatTransformer.transform(input); + + LOGGER.debug("Converted xml payload: {}", output); + assertThat(output, is(expected)); + } +} diff --git a/aai-core/src/test/java/org/onap/aai/util/FileWatcherTest.java b/aai-core/src/test/java/org/onap/aai/util/FileWatcherTest.java deleted file mode 100644 index 2e870f6e..00000000 --- a/aai-core/src/test/java/org/onap/aai/util/FileWatcherTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.util; - -import static org.junit.Assert.*; - -import java.io.File; - -import org.junit.Test; -import org.mockito.Mockito; - -public class FileWatcherTest { - - class FileWatcherExtension extends FileWatcher { - - public FileWatcherExtension(File file) { - super(file); - } - - @Override - protected void onChange(File file) { - System.out.println("do nothing"); - } - } - - @Test - public void testFileWatcher() { - File file = new File("helloworld"); - file.setLastModified(new Long(123)); - FileWatcher fileWatcher = new FileWatcherExtension(file); - assertNotNull(fileWatcher); - file.deleteOnExit(); - } - - @Test(expected = NullPointerException.class) - public void testFileWatcher_nullConstructor() { - FileWatcher fileWatcher = new FileWatcherExtension(null); - assertNull(fileWatcher); - } - - @Test - public void testRun() { - // verify that code is reachable outside of conditional check in run() - File file = new File("helloworld"); - file.setLastModified(new Long(100)); - FileWatcher fileWatcher = new FileWatcherExtension(file); - fileWatcher.run(); - file.deleteOnExit(); - } - - @Test - public void testOnChange() throws Exception { - FileWatcher fileWatcher = Mockito.mock(FileWatcher.class, Mockito.CALLS_REAL_METHODS); - - File file=Mockito.mock(File.class); - fileWatcher.onChange(file); - - Mockito.verify(fileWatcher).onChange(file); - - } -} diff --git a/aai-core/src/test/java/org/onap/aai/util/MapperUtilTest.java b/aai-core/src/test/java/org/onap/aai/util/MapperUtilTest.java deleted file mode 100644 index 33da9c04..00000000 --- a/aai-core/src/test/java/org/onap/aai/util/MapperUtilTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Modifications Copyright © 2018 IBM. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.aai.util; - -import static org.junit.Assert.assertEquals; - -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Test; - -public class MapperUtilTest { - - private JSONObject expectedJson; - private JSONObject sampleJson; - - @Before - public void setup() { - expectedJson = new JSONObject(); - sampleJson = new JSONObject(); - } - - @Test - public void writeAsJSONStringTest() throws Exception { - expectedJson.put("color", "black"); - expectedJson.put("shape", "box"); - SampleClass sample = new SampleClass("black", "box"); - assertEquals(expectedJson.toString(), MapperUtil.writeAsJSONString(sample)); - } - - @Test - public void readAsObjectOfTest() throws Exception { - sampleJson.put("color", "black"); - sampleJson.put("shape", "box"); - SampleClass expectedObject = new SampleClass("black", "box"); - SampleClass actualObject = MapperUtil.readAsObjectOf(SampleClass.class, sampleJson.toString()); - assertEquals(expectedObject.getColor(), actualObject.getColor()); - assertEquals(expectedObject.getShape(), actualObject.getShape()); - } -} - - -class SampleClass { - private String color; - private String shape; - - public SampleClass() { - - } - - public SampleClass(String c, String s) { - color = c; - shape = s; - } - - public String getColor() { - return color; - } - - public void setColor(String color) { - this.color = color; - } - - public String getShape() { - return shape; - } - - public void setShape(String shape) { - this.shape = shape; - } -} diff --git a/aai-core/src/test/java/org/onap/aai/util/StoreNotificationEventTest.java b/aai-core/src/test/java/org/onap/aai/util/StoreNotificationEventTest.java index 08cbba20..b4b8810e 100644 --- a/aai-core/src/test/java/org/onap/aai/util/StoreNotificationEventTest.java +++ b/aai-core/src/test/java/org/onap/aai/util/StoreNotificationEventTest.java @@ -66,19 +66,19 @@ public class StoreNotificationEventTest extends AAISetup { @Test(expected = AAIException.class) public void testStoreEventNullObj() throws AAIException { - sne.storeEvent(new EventHeader(), null); + sne.storeEventAndSendToJms(new EventHeader(), null); } @Test(expected = AAIException.class) public void testStoreEventInvalidObjForPojoUtils() throws AAIException { - sne.storeEvent(new EventHeader(), new Object()); + sne.storeEventAndSendToJms(new EventHeader(), new Object()); } @Test public void testStoreEventEmptyEventHeader() throws AAIException, JsonGenerationException, JsonMappingException, IOException { JsonObject object = Json.createObjectBuilder().add("hello", "world").build(); - String res = sne.storeEvent(new EventHeader(), object); + String res = sne.storeEventAndSendToJms(new EventHeader(), object); assertNotNull(res); assertTrue(res.contains("\"cambria.partition\" : \"" + AAIConstants.UEB_PUB_PARTITION_AAI + "\"")); @@ -118,7 +118,7 @@ public class StoreNotificationEventTest extends AAISetup { eh.setSeverity("ALERT"); eh.setVersion("v12"); - String res = sne.storeEvent(eh, object); + String res = sne.storeEventAndSendToJms(eh, object); assertNotNull(res); assertTrue(res.contains("\"cambria.partition\" : \"" + AAIConstants.UEB_PUB_PARTITION_AAI + "\"")); @@ -161,7 +161,7 @@ public class StoreNotificationEventTest extends AAISetup { @Test(expected = AAIException.class) public void testStoreEventIntrospectorNullObj() throws Exception { Loader loader = Mockito.mock(Loader.class); - sne.storeEvent(loader, null, null); + sne.storeEventAndSendToJms(loader, null, null); } @Ignore("Stopped working since the model driven story") @@ -180,7 +180,7 @@ public class StoreNotificationEventTest extends AAISetup { eventHeader.setValue("severity", "ALERT"); eventHeader.setValue("version", "v12"); Introspector obj = loader.introspectorFromName("notification-event"); - String res = sne.storeEvent(loader, eventHeader, obj); + String res = sne.storeEventAndSendToJms(loader, eventHeader, obj); assertNotNull(res); assertTrue(res.contains("\"cambria.partition\":\"" + AAIConstants.UEB_PUB_PARTITION_AAI + "\"")); @@ -205,7 +205,7 @@ public class StoreNotificationEventTest extends AAISetup { Introspector eventHeader = loader.introspectorFromName("notification-event-header"); Introspector obj = loader.introspectorFromName("notification-event"); - String res = sne.storeEvent(loader, eventHeader, obj); + String res = sne.storeEventAndSendToJms(loader, eventHeader, obj); assertNotNull(res); assertTrue(res.contains("\"cambria.partition\":\"" + AAIConstants.UEB_PUB_PARTITION_AAI + "\"")); diff --git a/aai-core/src/test/resources/bundleconfig-local/aaf/cadi.properties b/aai-core/src/test/resources/bundleconfig-local/aaf/cadi.properties new file mode 100644 index 00000000..8f7004ff --- /dev/null +++ b/aai-core/src/test/resources/bundleconfig-local/aaf/cadi.properties @@ -0,0 +1,14 @@ +## Location properties +## +## Localized Machine Information +## +cadi_loglevel=DEBUG +cadi_latitude=38.0 +cadi_longitude=-72.0 + +# Locate URL (which AAF Env) - Use lower case +aaf_locate_url=https://aafist.test.org:8095 +# AAF URL - Use upper case +aaf_url=https://AAF_LOCATE_URL/service:2.0 +# +cadi_prop_files=src/test/resources/bundleconfig-local/aaf/org.onap.aai.props diff --git a/aai-core/src/test/resources/bundleconfig-local/aaf/org.onap.aai.props b/aai-core/src/test/resources/bundleconfig-local/aaf/org.onap.aai.props new file mode 100644 index 00000000..3056e5f9 --- /dev/null +++ b/aai-core/src/test/resources/bundleconfig-local/aaf/org.onap.aai.props @@ -0,0 +1,4 @@ +cm_url=cm_url +hostname=hostname +aaf_env=IST +cadi_x509_issuers=CN=AAF CADI Test Issuing CA 01, OU=CSO, O=CO, C=US:CN=AAF CADI Test Issuing CA 02, OU=CSO, O=CO, C=US
\ No newline at end of file diff --git a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties b/aai-core/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties index 0239e2ef..f0e09d40 100644 --- a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties +++ b/aai-core/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties @@ -56,3 +56,4 @@ aai.rest.getall.depthparam=someuuid aaf.valid.issuer.wildcard=aaf wild card issuer|aafWildCardIssuer|OU=another +aai.implied.delete.whitelist.junit='pserver','l-interface' diff --git a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/error.properties b/aai-core/src/test/resources/bundleconfig-local/etc/appprops/error.properties index 3a5671c2..d99efb5e 100644 --- a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/error.properties +++ b/aai-core/src/test/resources/bundleconfig-local/etc/appprops/error.properties @@ -154,6 +154,8 @@ AAI_9105=5:0:WARN:9105:403:3300:Authorization error AAI_9106=5:0:WARN:9106:403:3300:Invalid AppId #AAI_9107=5:0:WARN:9107:403:3300:No Username in Request AAI_9107=5:0:WARN:9107:403:3300:SSL is not provided in request, please contact admin +AAI_9108=5:0:WARN:9107:403:3300:Basic auth credentials is not provided in the request +AAI_9109=5:0:WARN:9109:403:3300:User is not allowed to perform implicit delete #--- aaiinstar: 9201-9299 AAI_9201=5:4:ERROR:9201:500:3002:Unable to send notification diff --git a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-cached.properties b/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-cached.properties index aa3c0631..a0926e7c 100644 --- a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-cached.properties +++ b/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-cached.properties @@ -18,6 +18,7 @@ # ============LICENSE_END========================================================= query.fast-property=true +query.smart-limit=false # the following parameters are not reloaded automatically and require a manual bounce storage.backend=inmemory storage.hostname=localhost diff --git a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-realtime.properties b/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-realtime.properties index 05394334..3f00b557 100644 --- a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-realtime.properties +++ b/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-realtime.properties @@ -18,6 +18,7 @@ # ============LICENSE_END========================================================= query.fast-property=true +query.smart-limit=false # the following parameters are not reloaded automatically and require a manual bounce storage.backend=inmemory storage.hostname=localhost diff --git a/aai-core/src/test/resources/dbedgerules/DbEdgeRules_test.json b/aai-core/src/test/resources/dbedgerules/DbEdgeRules_test.json index b07e7783..f47925e4 100644 --- a/aai-core/src/test/resources/dbedgerules/DbEdgeRules_test.json +++ b/aai-core/src/test/resources/dbedgerules/DbEdgeRules_test.json @@ -166,7 +166,6 @@ "multiplicity": "ONE2MANY", "contains-other-v": "NONE", "delete-other-v": "${direction}", - "prevent-delete": "NONE", "description": "Hard to describe", "prevent-delete": "NONE" }, @@ -248,4 +247,4 @@ "prevent-delete": "!${direction}" } ] -}
\ No newline at end of file +} diff --git a/aai-core/src/test/resources/onap/dbedgerules/v14/DbEdgeRules_v14.json b/aai-core/src/test/resources/onap/dbedgerules/v14/DbEdgeRules_v14.json index 2eed8007..7b5c26a7 100644 --- a/aai-core/src/test/resources/onap/dbedgerules/v14/DbEdgeRules_v14.json +++ b/aai-core/src/test/resources/onap/dbedgerules/v14/DbEdgeRules_v14.json @@ -1115,7 +1115,17 @@ "prevent-delete": "NONE", "default": "true", "description":"" - }, + },{ + "from": "sriov-vf", + "to": "l-interface", + "label": "NOT.A.REAL.EDGERULE", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "description":"" + }, { "from": "vlan", "to": "l-interface", @@ -3051,6 +3061,6 @@ "default": "true", "description":"" } - + ] } diff --git a/aai-core/src/test/resources/onap/oxm/v10/aai_oxm_v10.xml b/aai-core/src/test/resources/onap/oxm/v10/aai_oxm_v10.xml index e28466b7..71ab3dd5 100644 --- a/aai-core/src/test/resources/onap/oxm/v10/aai_oxm_v10.xml +++ b/aai-core/src/test/resources/onap/oxm/v10/aai_oxm_v10.xml @@ -1653,6 +1653,7 @@ <xml-property name="namespace" value="cloud-infrastructure"/> <xml-property name="uriTemplate" value="/cloud-infrastructure/pservers/pserver/{hostname}"/> <xml-property name="requiredProps" value="hostname,in-maint"/> + <xml-property name="dslStartNodeProps" value="hostname,pserver-id,pserver-name2,inv-status"/> </xml-properties> </java-type> diff --git a/aai-core/src/test/resources/onap/oxm/v14/aai_oxm_v14.xml b/aai-core/src/test/resources/onap/oxm/v14/aai_oxm_v14.xml index bb9b2eab..08a6cd52 100644 --- a/aai-core/src/test/resources/onap/oxm/v14/aai_oxm_v14.xml +++ b/aai-core/src/test/resources/onap/oxm/v14/aai_oxm_v14.xml @@ -8,9 +8,9 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -4150,7 +4150,7 @@ </xml-element> <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.onap.org.v14.RelationshipList"/> <xml-element java-attribute="cps" name="cps" type="inventory.aai.onap.org.v14.Cps"/> - <xml-element container-type="java.util.ArrayList" java-attribute="l3InterfaceIpv4AddressList" name="l3-interface-ipv4-address-list" type="inventory.aai.onap.org.v14.L3InterfaceIpv4AddressList"/> + <xml-element container-type="java.util.ArrayList" java-attribute="l3InterfaceIpv4AddressList" name="l3-interface-ipv4-address-list" type="inventory.aai.onap.org.v14.L3InterfaceIpv4AddressList"/> <xml-element container-type="java.util.ArrayList" java-attribute="l3InterfaceIpv6AddressList" name="l3-interface-ipv6-address-list" type="inventory.aai.onap.org.v14.L3InterfaceIpv6AddressList"/> </java-attributes> <xml-properties> @@ -7499,7 +7499,7 @@ <xml-properties> <xml-property name="description" value="The network-technology that a cloud-region can support. Current valid values- CONTRAIL AIC_SR_IOV OVS STANDARD-SR-IOV"/> </xml-properties> - </xml-element> + </xml-element> <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String"> <xml-properties> <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete."/> diff --git a/aai-core/src/test/resources/payloads/expected/transform-json-to-xml.xml b/aai-core/src/test/resources/payloads/expected/transform-json-to-xml.xml new file mode 100644 index 00000000..55d8854e --- /dev/null +++ b/aai-core/src/test/resources/payloads/expected/transform-json-to-xml.xml @@ -0,0 +1,59 @@ +<results> + <result> + <related-to> + <node> + <relationship-label>org.onap.relationships.inventory.LocatedIn</relationship-label> + <node-type>complex</node-type> + <id>286724232</id> + <url>/aai/v18/cloud-infrastructure/complexes/complex/testcomplex2</url> + </node> + <node> + <relationship-label>org.onap.relationships.inventory.LocatedIn</relationship-label> + <node-type>complex</node-type> + <id>286724233</id> + <url>/aai/v18/cloud-infrastructure/complexes/complex/testcomplex1</url> + </node> + </related-to> + <node-type>pserver</node-type> + <id>286724136</id> + <url>/aai/v18/cloud-infrastructure/pservers/pserver/test-pserver1</url> + <properties> + <aai-last-mod-ts>1568997029298</aai-last-mod-ts> + <ptnii-equip-name>test-pserver1</ptnii-equip-name> + <equip-type>SERVER</equip-type> + <equip-vendor>SomeVendor</equip-vendor> + <purpose>Standalone</purpose> + <fqdn>a.b.c.d</fqdn> + <aai-uri>/cloud-infrastructure/pservers/pserver/test-pserver1</aai-uri> + <pserver-id>6bf4944a-9f13-4bb8-8f49-b61060793510</pserver-id> + <aai-created-ts>1568997029298</aai-created-ts> + <ipv4-oam-address>1.2.3.4</ipv4-oam-address> + <source-of-truth>AAI</source-of-truth> + <aai-node-type>pserver</aai-node-type> + <hostname>test-pserver1</hostname> + <equip-model>SomeModel</equip-model> + <in-maint>false</in-maint> + <aai-uuid>05fa7b64-59e4-44a1-8162-e32746659c77</aai-uuid> + <resource-version>1568997029298</resource-version> + <last-mod-source-of-truth>AAIRctFeed</last-mod-source-of-truth> + </properties> + </result> + <result> + <related-to></related-to> + <node-type>pserver</node-type> + <id>286724152</id> + <url>/aai/v18/cloud-infrastructure/pservers/pserver/test-pserver2</url> + <properties> + <aai-last-mod-ts>1553805738492</aai-last-mod-ts> + <hostname>test-pserver2</hostname> + <in-maint>false</in-maint> + <aai-uuid>13a8440c-7fb4-4f41-a141-6e1d9e895b4a</aai-uuid> + <resource-version>1553805738492</resource-version> + <aai-uri>/cloud-infrastructure/pservers/pserver/test-pserver2</aai-uri> + <aai-created-ts>1553805738492</aai-created-ts> + <last-mod-source-of-truth>JUNITTESTAPP2</last-mod-source-of-truth> + <source-of-truth>JUNITTESTAPP2</source-of-truth> + <aai-node-type>pserver</aai-node-type> + </properties> + </result> +</results> diff --git a/aai-core/src/test/resources/payloads/resource/complex_pserver_with_relation.json b/aai-core/src/test/resources/payloads/resource/complex_pserver_with_relation.json new file mode 100644 index 00000000..d6b1165f --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/complex_pserver_with_relation.json @@ -0,0 +1,29 @@ +{ + "complex": { + "physical-location-id": "complex-1", + "data-center-code": "MiddletownNJ", + "complex-name": "complex-L-lisleil", + "physical-location-type": "uCPE Complex", + "street1": "4513 Western Ave", + "street2": "CU-L", + "city": "Middletown", + "state": "NJ", + "postal-code": "07748", + "country": "USA", + "region": "NA" + }, + "pserver": { + "hostname": "pserver-1", + "ptnii-equip-name": "ptnii", + "number-of-cpus": 280, + "relationship-list": { + "relationship": [ + { + "related-to": "complex", + "relationship-label": "org.onap.relationships.inventory.LocatedIn", + "related-link": "/aai/v14/cloud-infrastructure/complexes/complex/complex-1" + } + ] + } + } +} diff --git a/aai-core/src/test/resources/payloads/resource/customer_with_children_and_generic-vnf_with_children_and_edge_between_service-instance_vlan.json b/aai-core/src/test/resources/payloads/resource/customer_with_children_and_generic-vnf_with_children_and_edge_between_service-instance_vlan.json new file mode 100644 index 00000000..d4c4f65b --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/customer_with_children_and_generic-vnf_with_children_and_edge_between_service-instance_vlan.json @@ -0,0 +1,70 @@ +{ + "generic-vnf": { + "vnf-id": "gvnf", + "vnf-name": "example-vnf-name-val-28303", + "vnf-name2": "example-vnf-name2-val-14743", + "vnf-type": "example-vnf-type-val-58866", + "service-id": "example-service-id-val-24831", + "regional-resource-zone": "example-regional-resource-zone-val-33255", + "prov-status": "example-prov-status-val-47870", + "operational-state": "example-operational-state-val-8419", + "equipment-role": "example-equipment-role-val-35736", + "orchestration-status": "example-orchestration-status-val-67542", + "l-interfaces": { + "l-interface": [ + { + "interface-name": "lint", + "interface-role": "example-interface-role-val-61355", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-78314", + "vlans": { + "vlan": [ + { + "vlan-interface": "vlan", + "vlan-id-inner": 90845777, + "vlan-id-outer": 23395650 + } + ] + } + } + ] + } + }, + "customer": { + "global-customer-id": "cust", + "subscriber-name": "subscriber-name-022", + "subscriber-type": "subscriber-type-022", + "service-subscriptions": { + "service-subscription": { + "service-type": "ss", + "service-instances": { + "service-instance": [ + { + "service-instance-id": "si", + "relationship-list": { + "relationship": [ + { + "related-to": "vlan", + "relationship-data": [ + { + "relationship-key": "vlan.vlan-interface", + "relationship-value": "vlan" + }, + { + "relationship-key": "l-interface.interface-name", + "relationship-value": "lint" + }, + { + "relationship-key": "generic-vnf.vnf-id", + "relationship-value": "gvnf" + } + ] + } + ] + } + } + ] + } + } + } + } +} diff --git a/aai-core/src/test/resources/payloads/resource/generic-vnf-implied-delete.json b/aai-core/src/test/resources/payloads/resource/generic-vnf-implied-delete.json new file mode 100644 index 00000000..0c83c36a --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/generic-vnf-implied-delete.json @@ -0,0 +1,26 @@ +{ + "vnf-id": "generic-vnf-implied-delete", + "vnf-type": "sometype", + "in-maint": true, + "is-closed-loop-disabled": true, + "vf-modules": { + "vf-module": [ + { + "vf-module-id": "vf-mod-id1", + "is-base-vf-module": true + }, + { + "vf-module-id": "vf-mod-id2", + "is-base-vf-module": true + }, + { + "vf-module-id": "vf-mod-id3", + "is-base-vf-module": true + }, + { + "vf-module-id": "vf-mod-id4", + "is-base-vf-module": true + } + ] + } +} diff --git a/aai-core/src/test/resources/payloads/resource/generic-vnf-notification.json b/aai-core/src/test/resources/payloads/resource/generic-vnf-notification.json new file mode 100644 index 00000000..27b38d2e --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/generic-vnf-notification.json @@ -0,0 +1,6 @@ +{ + "vnf-id": "generic-vnf-notification", + "vnf-type": "sometype", + "in-maint": true, + "is-closed-loop-disabled": true +} diff --git a/aai-core/src/test/resources/payloads/resource/generic-vnf-with-vf-module.json b/aai-core/src/test/resources/payloads/resource/generic-vnf-with-vf-module.json new file mode 100644 index 00000000..09c9b48f --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/generic-vnf-with-vf-module.json @@ -0,0 +1,17 @@ +{ + "vnf-id": "test-vnf11", + "vnf-name": "example-vnf-name-val-37069", + "vnf-name2": "example-vnf-name2-val-58382", + "vnf-type": "example-vnf-type-val-95069", + "in-maint": true, + "is-closed-loop-disabled": true, + "vf-modules": { + "vf-module": [ + { + "vf-module-id": "vf-module-test11", + "is-base-vf-module": true, + "automated-assignment": true + } + ] + } +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-body-create-child-on-existing-obj.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-body-create-child-on-existing-obj.json new file mode 100644 index 00000000..5cb33c82 --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-body-create-child-on-existing-obj.json @@ -0,0 +1,273 @@ +{ + "hostname": "example-hostname-val-85598", + "ptnii-equip-name": "example-ptnii-equip-name-val-85834", + "number-of-cpus": 280, + "disk-in-gigabytes": 78521, + "ram-in-megabytes": 36975, + "equip-type": "example-equip-type-val-47930", + "equip-vendor": "example-equip-vendor-val-59512", + "equip-model": "example-equip-model-val-46076", + "fqdn": "example-fqdn-val-74486", + "pserver-selflink": "example-pserver-selflink-val-72481", + "ipv4-oam-address": "example-ipv4-oam-address-val-16616", + "serial-number": "example-serial-number-val-92800", + "ipaddress-v4-loopback-0": "example-ipaddress-v4-loopback0-val-61384", + "ipaddress-v6-loopback-0": "example-ipaddress-v6-loopback0-val-91056", + "ipaddress-v4-aim": "example-ipaddress-v4-aim-val-72233", + "ipaddress-v6-aim": "example-ipaddress-v6-aim-val-13572", + "ipaddress-v6-oam": "example-ipaddress-v6-oam-val-84518", + "inv-status": "example-inv-status-val-5042", + "pserver-id": "example-pserver-id-val-15622", + "internet-topology": "example-internet-topology-val-31234", + "in-maint": true, + "pserver-name2": "example-pserver-name2-val-93509", + "purpose": "example-purpose-val-52320", + "prov-status": "example-prov-status-val-47313", + "management-option": "example-management-option-val-72434", + "host-profile": "example-host-profile-val-84672", + "p-interfaces": { + "p-interface": [ + { + "interface-name": "example-interface-name-val-46147", + "selflink": "example-selflink-val-81029", + "speed-value": "example-speed-value-val-47874", + "speed-units": "example-speed-units-val-10396", + "port-description": "example-port-description-val-53068", + "equipment-identifier": "example-equipment-identifier-val-63234", + "interface-role": "example-interface-role-val-49232", + "interface-type": "example-interface-type-val-21757", + "prov-status": "example-prov-status-val-19117", + "in-maint": true, + "inv-status": "example-inv-status-val-48715", + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-13366", + "interface-role": "example-interface-role-val-29488", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-78396", + "selflink": "example-selflink-val-4757", + "interface-id": "example-interface-id-val-79486", + "macaddr": "example-macaddr-val-52194", + "network-name": "example-network-name-val-80678", + "management-option": "example-management-option-val-53535", + "interface-description": "example-interface-description-val-299", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-9736", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-62271", + "vlans": { + "vlan": [ + { + "vlan-interface": "example-vlan-interface-val-31470", + "vlan-id-inner": 61286171, + "vlan-id-outer": 64615174, + "speed-value": "example-speed-value-val-80457", + "speed-units": "example-speed-units-val-51587", + "vlan-description": "example-vlan-description-val-97575", + "backdoor-connection": "example-backdoor-connection-val-3179", + "vpn-key": "example-vpn-key-val-50069", + "orchestration-status": "example-orchestration-status-val-34071", + "in-maint": true, + "prov-status": "example-prov-status-val-62615", + "is-ip-unnumbered": true, + "is-private": true, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-8171", + "l3-interface-ipv4-prefix-length": 39266592, + "vlan-id-inner": 91284707, + "vlan-id-outer": 80343467, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-52921", + "neutron-subnet-id": "example-neutron-subnet-id-val-88134" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-70726", + "l3-interface-ipv6-prefix-length": 81422758, + "vlan-id-inner": 15099560, + "vlan-id-outer": 46643832, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-97954", + "neutron-subnet-id": "example-neutron-subnet-id-val-23889" + } + ] + } + ] + }, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-62086", + "interface-role": "example-interface-role-val-13107", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-32015", + "selflink": "example-selflink-val-31580", + "interface-id": "example-interface-id-val-57805", + "macaddr": "example-macaddr-val-54266", + "network-name": "example-network-name-val-38517", + "management-option": "example-management-option-val-8801", + "interface-description": "example-interface-description-val-88573", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-99164", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-14581", + "admin-status": "example-admin-status-val-29720" + } + ] + }, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-31324", + "l3-interface-ipv4-prefix-length": 36060646, + "vlan-id-inner": 62164959, + "vlan-id-outer": 93058593, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-39206", + "neutron-subnet-id": "example-neutron-subnet-id-val-27746" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-72897", + "l3-interface-ipv6-prefix-length": 29592510, + "vlan-id-inner": 18402161, + "vlan-id-outer": 651158, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-6821", + "neutron-subnet-id": "example-neutron-subnet-id-val-11217" + } + ], + "admin-status": "example-admin-status-val-81745" + } + ] + } + }, + { + "interface-name": "p-interface-1", + "in-maint": false + } + ] + }, + "lag-interfaces": { + "lag-interface": [ + { + "interface-name": "example-interface-name-val-87366", + "interface-description": "example-interface-description-val-3722", + "speed-value": "example-speed-value-val-73546", + "speed-units": "example-speed-units-val-73658", + "interface-id": "example-interface-id-val-62385", + "interface-role": "example-interface-role-val-60746", + "prov-status": "example-prov-status-val-26239", + "in-maint": true, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-69579", + "interface-role": "example-interface-role-val-64571", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-68385", + "selflink": "example-selflink-val-29611", + "interface-id": "example-interface-id-val-75464", + "macaddr": "example-macaddr-val-7285", + "network-name": "example-network-name-val-52284", + "management-option": "example-management-option-val-26028", + "interface-description": "example-interface-description-val-37641", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-56460", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-23301", + "vlans": { + "vlan": [ + { + "vlan-interface": "example-vlan-interface-val-56661", + "vlan-id-inner": 33305644, + "vlan-id-outer": 30871600, + "speed-value": "example-speed-value-val-1929", + "speed-units": "example-speed-units-val-71630", + "vlan-description": "example-vlan-description-val-63003", + "backdoor-connection": "example-backdoor-connection-val-41834", + "vpn-key": "example-vpn-key-val-16552", + "orchestration-status": "example-orchestration-status-val-95322", + "in-maint": true, + "prov-status": "example-prov-status-val-89886", + "is-ip-unnumbered": true, + "is-private": true, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-69142", + "l3-interface-ipv4-prefix-length": 11099430, + "vlan-id-inner": 88996967, + "vlan-id-outer": 23003182, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-53091", + "neutron-subnet-id": "example-neutron-subnet-id-val-41571" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-27490", + "l3-interface-ipv6-prefix-length": 20167688, + "vlan-id-inner": 40775405, + "vlan-id-outer": 75855907, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-9739", + "neutron-subnet-id": "example-neutron-subnet-id-val-806" + } + ] + } + ] + }, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-49266", + "interface-role": "example-interface-role-val-210", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-81668", + "selflink": "example-selflink-val-6356", + "interface-id": "example-interface-id-val-99531", + "macaddr": "example-macaddr-val-25092", + "network-name": "example-network-name-val-3319", + "management-option": "example-management-option-val-79883", + "interface-description": "example-interface-description-val-54501", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-48840", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-26846", + "admin-status": "example-admin-status-val-89244" + } + ] + }, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-61251", + "l3-interface-ipv4-prefix-length": 91875404, + "vlan-id-inner": 36470314, + "vlan-id-outer": 96344091, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-17339", + "neutron-subnet-id": "example-neutron-subnet-id-val-86128" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-31476", + "l3-interface-ipv6-prefix-length": 11663872, + "vlan-id-inner": 28459412, + "vlan-id-outer": 9852622, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-15120", + "neutron-subnet-id": "example-neutron-subnet-id-val-36088" + } + ], + "admin-status": "example-admin-status-val-81055" + } + ] + } + } + ] + } +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-body-create-edge-between-pserver-and-generic-vnf.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-body-create-edge-between-pserver-and-generic-vnf.json new file mode 100644 index 00000000..79099538 --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-body-create-edge-between-pserver-and-generic-vnf.json @@ -0,0 +1,289 @@ +{ + "hostname": "example-hostname-val-85598", + "ptnii-equip-name": "example-ptnii-equip-name-val-85834", + "number-of-cpus": 280, + "disk-in-gigabytes": 78521, + "ram-in-megabytes": 36975, + "equip-type": "example-equip-type-val-47930", + "equip-vendor": "example-equip-vendor-val-59512", + "equip-model": "example-equip-model-val-46076", + "fqdn": "example-fqdn-val-74486", + "pserver-selflink": "example-pserver-selflink-val-72481", + "ipv4-oam-address": "example-ipv4-oam-address-val-16616", + "serial-number": "example-serial-number-val-92800", + "ipaddress-v4-loopback-0": "example-ipaddress-v4-loopback0-val-61384", + "ipaddress-v6-loopback-0": "example-ipaddress-v6-loopback0-val-91056", + "ipaddress-v4-aim": "example-ipaddress-v4-aim-val-72233", + "ipaddress-v6-aim": "example-ipaddress-v6-aim-val-13572", + "ipaddress-v6-oam": "example-ipaddress-v6-oam-val-84518", + "inv-status": "example-inv-status-val-5042", + "pserver-id": "example-pserver-id-val-15622", + "internet-topology": "example-internet-topology-val-31234", + "in-maint": true, + "pserver-name2": "example-pserver-name2-val-93509", + "purpose": "example-purpose-val-52320", + "prov-status": "example-prov-status-val-47313", + "management-option": "example-management-option-val-72434", + "host-profile": "example-host-profile-val-84672", + "relationship-list": { + "relationship": [ + { + "related-to": "generic-vnf", + "relationship-label": "tosca.relationships.HostedOn", + "related-link": "/aai/v14/network/generic-vnfs/generic-vnf/generic-vnf-notification", + "relationship-data": [ + { + "relationship-key": "generic-vnf.vnf-id", + "relationship-value": "generic-vnf-notification" + } + ], + "related-to-property": [ + { + "property-key": "generic-vnf.vnf-name" + } + ] + } + ] + }, + "p-interfaces": { + "p-interface": [ + { + "interface-name": "example-interface-name-val-46147", + "selflink": "example-selflink-val-81029", + "speed-value": "example-speed-value-val-47874", + "speed-units": "example-speed-units-val-10396", + "port-description": "example-port-description-val-53068", + "equipment-identifier": "example-equipment-identifier-val-63234", + "interface-role": "example-interface-role-val-49232", + "interface-type": "example-interface-type-val-21757", + "prov-status": "example-prov-status-val-19117", + "in-maint": true, + "inv-status": "example-inv-status-val-48715", + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-13366", + "interface-role": "example-interface-role-val-29488", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-78396", + "selflink": "example-selflink-val-4757", + "interface-id": "example-interface-id-val-79486", + "macaddr": "example-macaddr-val-52194", + "network-name": "example-network-name-val-80678", + "management-option": "example-management-option-val-53535", + "interface-description": "example-interface-description-val-299", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-9736", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-62271", + "vlans": { + "vlan": [ + { + "vlan-interface": "example-vlan-interface-val-31470", + "vlan-id-inner": 61286171, + "vlan-id-outer": 64615174, + "speed-value": "example-speed-value-val-80457", + "speed-units": "example-speed-units-val-51587", + "vlan-description": "example-vlan-description-val-97575", + "backdoor-connection": "example-backdoor-connection-val-3179", + "vpn-key": "example-vpn-key-val-50069", + "orchestration-status": "example-orchestration-status-val-34071", + "in-maint": true, + "prov-status": "example-prov-status-val-62615", + "is-ip-unnumbered": true, + "is-private": true, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-8171", + "l3-interface-ipv4-prefix-length": 39266592, + "vlan-id-inner": 91284707, + "vlan-id-outer": 80343467, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-52921", + "neutron-subnet-id": "example-neutron-subnet-id-val-88134" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-70726", + "l3-interface-ipv6-prefix-length": 81422758, + "vlan-id-inner": 15099560, + "vlan-id-outer": 46643832, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-97954", + "neutron-subnet-id": "example-neutron-subnet-id-val-23889" + } + ] + } + ] + }, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-62086", + "interface-role": "example-interface-role-val-13107", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-32015", + "selflink": "example-selflink-val-31580", + "interface-id": "example-interface-id-val-57805", + "macaddr": "example-macaddr-val-54266", + "network-name": "example-network-name-val-38517", + "management-option": "example-management-option-val-8801", + "interface-description": "example-interface-description-val-88573", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-99164", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-14581", + "admin-status": "example-admin-status-val-29720" + } + ] + }, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-31324", + "l3-interface-ipv4-prefix-length": 36060646, + "vlan-id-inner": 62164959, + "vlan-id-outer": 93058593, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-39206", + "neutron-subnet-id": "example-neutron-subnet-id-val-27746" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-72897", + "l3-interface-ipv6-prefix-length": 29592510, + "vlan-id-inner": 18402161, + "vlan-id-outer": 651158, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-6821", + "neutron-subnet-id": "example-neutron-subnet-id-val-11217" + } + ], + "admin-status": "example-admin-status-val-81745" + } + ] + } + } + ] + }, + "lag-interfaces": { + "lag-interface": [ + { + "interface-name": "example-interface-name-val-87366", + "interface-description": "example-interface-description-val-3722", + "speed-value": "example-speed-value-val-73546", + "speed-units": "example-speed-units-val-73658", + "interface-id": "example-interface-id-val-62385", + "interface-role": "example-interface-role-val-60746", + "prov-status": "example-prov-status-val-26239", + "in-maint": true, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-69579", + "interface-role": "example-interface-role-val-64571", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-68385", + "selflink": "example-selflink-val-29611", + "interface-id": "example-interface-id-val-75464", + "macaddr": "example-macaddr-val-7285", + "network-name": "example-network-name-val-52284", + "management-option": "example-management-option-val-26028", + "interface-description": "example-interface-description-val-37641", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-56460", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-23301", + "vlans": { + "vlan": [ + { + "vlan-interface": "example-vlan-interface-val-56661", + "vlan-id-inner": 33305644, + "vlan-id-outer": 30871600, + "speed-value": "example-speed-value-val-1929", + "speed-units": "example-speed-units-val-71630", + "vlan-description": "example-vlan-description-val-63003", + "backdoor-connection": "example-backdoor-connection-val-41834", + "vpn-key": "example-vpn-key-val-16552", + "orchestration-status": "example-orchestration-status-val-95322", + "in-maint": true, + "prov-status": "example-prov-status-val-89886", + "is-ip-unnumbered": true, + "is-private": true, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-69142", + "l3-interface-ipv4-prefix-length": 11099430, + "vlan-id-inner": 88996967, + "vlan-id-outer": 23003182, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-53091", + "neutron-subnet-id": "example-neutron-subnet-id-val-41571" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-27490", + "l3-interface-ipv6-prefix-length": 20167688, + "vlan-id-inner": 40775405, + "vlan-id-outer": 75855907, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-9739", + "neutron-subnet-id": "example-neutron-subnet-id-val-806" + } + ] + } + ] + }, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-49266", + "interface-role": "example-interface-role-val-210", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-81668", + "selflink": "example-selflink-val-6356", + "interface-id": "example-interface-id-val-99531", + "macaddr": "example-macaddr-val-25092", + "network-name": "example-network-name-val-3319", + "management-option": "example-management-option-val-79883", + "interface-description": "example-interface-description-val-54501", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-48840", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-26846", + "admin-status": "example-admin-status-val-89244" + } + ] + }, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-61251", + "l3-interface-ipv4-prefix-length": 91875404, + "vlan-id-inner": 36470314, + "vlan-id-outer": 96344091, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-17339", + "neutron-subnet-id": "example-neutron-subnet-id-val-86128" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-31476", + "l3-interface-ipv6-prefix-length": 11663872, + "vlan-id-inner": 28459412, + "vlan-id-outer": 9852622, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-15120", + "neutron-subnet-id": "example-neutron-subnet-id-val-36088" + } + ], + "admin-status": "example-admin-status-val-81055" + } + ] + } + } + ] + } +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-body-delete-edge-between-pserver-and-generic-vnf.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-body-delete-edge-between-pserver-and-generic-vnf.json new file mode 100644 index 00000000..cdcd3ee0 --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-body-delete-edge-between-pserver-and-generic-vnf.json @@ -0,0 +1,269 @@ +{ + "hostname": "example-hostname-val-85598", + "ptnii-equip-name": "example-ptnii-equip-name-val-85834", + "number-of-cpus": 280, + "disk-in-gigabytes": 78521, + "ram-in-megabytes": 36975, + "equip-type": "example-equip-type-val-47930", + "equip-vendor": "example-equip-vendor-val-59512", + "equip-model": "example-equip-model-val-46076", + "fqdn": "example-fqdn-val-74486", + "pserver-selflink": "example-pserver-selflink-val-72481", + "ipv4-oam-address": "example-ipv4-oam-address-val-16616", + "serial-number": "example-serial-number-val-92800", + "ipaddress-v4-loopback-0": "example-ipaddress-v4-loopback0-val-61384", + "ipaddress-v6-loopback-0": "example-ipaddress-v6-loopback0-val-91056", + "ipaddress-v4-aim": "example-ipaddress-v4-aim-val-72233", + "ipaddress-v6-aim": "example-ipaddress-v6-aim-val-13572", + "ipaddress-v6-oam": "example-ipaddress-v6-oam-val-84518", + "inv-status": "example-inv-status-val-5042", + "pserver-id": "example-pserver-id-val-15622", + "internet-topology": "example-internet-topology-val-31234", + "in-maint": true, + "pserver-name2": "example-pserver-name2-val-93509", + "purpose": "example-purpose-val-52320", + "prov-status": "example-prov-status-val-47313", + "management-option": "example-management-option-val-72434", + "host-profile": "example-host-profile-val-84672", + "p-interfaces": { + "p-interface": [ + { + "interface-name": "example-interface-name-val-46147", + "selflink": "example-selflink-val-81029", + "speed-value": "example-speed-value-val-47874", + "speed-units": "example-speed-units-val-10396", + "port-description": "example-port-description-val-53068", + "equipment-identifier": "example-equipment-identifier-val-63234", + "interface-role": "example-interface-role-val-49232", + "interface-type": "example-interface-type-val-21757", + "prov-status": "example-prov-status-val-19117", + "in-maint": true, + "inv-status": "example-inv-status-val-48715", + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-13366", + "interface-role": "example-interface-role-val-29488", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-78396", + "selflink": "example-selflink-val-4757", + "interface-id": "example-interface-id-val-79486", + "macaddr": "example-macaddr-val-52194", + "network-name": "example-network-name-val-80678", + "management-option": "example-management-option-val-53535", + "interface-description": "example-interface-description-val-299", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-9736", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-62271", + "vlans": { + "vlan": [ + { + "vlan-interface": "example-vlan-interface-val-31470", + "vlan-id-inner": 61286171, + "vlan-id-outer": 64615174, + "speed-value": "example-speed-value-val-80457", + "speed-units": "example-speed-units-val-51587", + "vlan-description": "example-vlan-description-val-97575", + "backdoor-connection": "example-backdoor-connection-val-3179", + "vpn-key": "example-vpn-key-val-50069", + "orchestration-status": "example-orchestration-status-val-34071", + "in-maint": true, + "prov-status": "example-prov-status-val-62615", + "is-ip-unnumbered": true, + "is-private": true, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-8171", + "l3-interface-ipv4-prefix-length": 39266592, + "vlan-id-inner": 91284707, + "vlan-id-outer": 80343467, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-52921", + "neutron-subnet-id": "example-neutron-subnet-id-val-88134" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-70726", + "l3-interface-ipv6-prefix-length": 81422758, + "vlan-id-inner": 15099560, + "vlan-id-outer": 46643832, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-97954", + "neutron-subnet-id": "example-neutron-subnet-id-val-23889" + } + ] + } + ] + }, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-62086", + "interface-role": "example-interface-role-val-13107", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-32015", + "selflink": "example-selflink-val-31580", + "interface-id": "example-interface-id-val-57805", + "macaddr": "example-macaddr-val-54266", + "network-name": "example-network-name-val-38517", + "management-option": "example-management-option-val-8801", + "interface-description": "example-interface-description-val-88573", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-99164", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-14581", + "admin-status": "example-admin-status-val-29720" + } + ] + }, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-31324", + "l3-interface-ipv4-prefix-length": 36060646, + "vlan-id-inner": 62164959, + "vlan-id-outer": 93058593, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-39206", + "neutron-subnet-id": "example-neutron-subnet-id-val-27746" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-72897", + "l3-interface-ipv6-prefix-length": 29592510, + "vlan-id-inner": 18402161, + "vlan-id-outer": 651158, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-6821", + "neutron-subnet-id": "example-neutron-subnet-id-val-11217" + } + ], + "admin-status": "example-admin-status-val-81745" + } + ] + } + } + ] + }, + "lag-interfaces": { + "lag-interface": [ + { + "interface-name": "example-interface-name-val-87366", + "interface-description": "example-interface-description-val-3722", + "speed-value": "example-speed-value-val-73546", + "speed-units": "example-speed-units-val-73658", + "interface-id": "example-interface-id-val-62385", + "interface-role": "example-interface-role-val-60746", + "prov-status": "example-prov-status-val-26239", + "in-maint": true, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-69579", + "interface-role": "example-interface-role-val-64571", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-68385", + "selflink": "example-selflink-val-29611", + "interface-id": "example-interface-id-val-75464", + "macaddr": "example-macaddr-val-7285", + "network-name": "example-network-name-val-52284", + "management-option": "example-management-option-val-26028", + "interface-description": "example-interface-description-val-37641", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-56460", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-23301", + "vlans": { + "vlan": [ + { + "vlan-interface": "example-vlan-interface-val-56661", + "vlan-id-inner": 33305644, + "vlan-id-outer": 30871600, + "speed-value": "example-speed-value-val-1929", + "speed-units": "example-speed-units-val-71630", + "vlan-description": "example-vlan-description-val-63003", + "backdoor-connection": "example-backdoor-connection-val-41834", + "vpn-key": "example-vpn-key-val-16552", + "orchestration-status": "example-orchestration-status-val-95322", + "in-maint": true, + "prov-status": "example-prov-status-val-89886", + "is-ip-unnumbered": true, + "is-private": true, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-69142", + "l3-interface-ipv4-prefix-length": 11099430, + "vlan-id-inner": 88996967, + "vlan-id-outer": 23003182, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-53091", + "neutron-subnet-id": "example-neutron-subnet-id-val-41571" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-27490", + "l3-interface-ipv6-prefix-length": 20167688, + "vlan-id-inner": 40775405, + "vlan-id-outer": 75855907, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-9739", + "neutron-subnet-id": "example-neutron-subnet-id-val-806" + } + ] + } + ] + }, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-49266", + "interface-role": "example-interface-role-val-210", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-81668", + "selflink": "example-selflink-val-6356", + "interface-id": "example-interface-id-val-99531", + "macaddr": "example-macaddr-val-25092", + "network-name": "example-network-name-val-3319", + "management-option": "example-management-option-val-79883", + "interface-description": "example-interface-description-val-54501", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-48840", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-26846", + "admin-status": "example-admin-status-val-89244" + } + ] + }, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-61251", + "l3-interface-ipv4-prefix-length": 91875404, + "vlan-id-inner": 36470314, + "vlan-id-outer": 96344091, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-17339", + "neutron-subnet-id": "example-neutron-subnet-id-val-86128" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-31476", + "l3-interface-ipv6-prefix-length": 11663872, + "vlan-id-inner": 28459412, + "vlan-id-outer": 9852622, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-15120", + "neutron-subnet-id": "example-neutron-subnet-id-val-36088" + } + ], + "admin-status": "example-admin-status-val-81055" + } + ] + } + } + ] + } +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-header-create-child-on-existing-obj.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-header-create-child-on-existing-obj.json new file mode 100644 index 00000000..2c255c1f --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-header-create-child-on-existing-obj.json @@ -0,0 +1,9 @@ +{ + "id": "JUNIT-TRANSACTION", + "source-name": "JUNIT", + "version": "v14", + "action": "UPDATE", + "entity-type": "pserver", + "top-entity-type": "pserver", + "entity-link": "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598" +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-header-create-edge-between-pserver-and-generic-vnf.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-header-create-edge-between-pserver-and-generic-vnf.json new file mode 100644 index 00000000..2c255c1f --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-header-create-edge-between-pserver-and-generic-vnf.json @@ -0,0 +1,9 @@ +{ + "id": "JUNIT-TRANSACTION", + "source-name": "JUNIT", + "version": "v14", + "action": "UPDATE", + "entity-type": "pserver", + "top-entity-type": "pserver", + "entity-link": "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598" +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-header-delete-edge-between-pserver-and-generic-vnf.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-header-delete-edge-between-pserver-and-generic-vnf.json new file mode 100644 index 00000000..2c255c1f --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-all/expected-notification-header-delete-edge-between-pserver-and-generic-vnf.json @@ -0,0 +1,9 @@ +{ + "id": "JUNIT-TRANSACTION", + "source-name": "JUNIT", + "version": "v14", + "action": "UPDATE", + "entity-type": "pserver", + "top-entity-type": "pserver", + "entity-link": "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598" +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-body-create-child-on-existing-obj.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-body-create-child-on-existing-obj.json new file mode 100644 index 00000000..174db245 --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-body-create-child-on-existing-obj.json @@ -0,0 +1,12 @@ +{ + "hostname": "example-hostname-val-85598", + "pserver-name2": "example-pserver-name2-val-93509", + "p-interfaces": { + "p-interface": [ + { + "interface-name": "p-interface-1", + "in-maint": false + } + ] + } +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-body-create-edge-between-pserver-and-generic-vnf.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-body-create-edge-between-pserver-and-generic-vnf.json new file mode 100644 index 00000000..54afd1b6 --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-body-create-edge-between-pserver-and-generic-vnf.json @@ -0,0 +1,48 @@ +{ + "hostname": "example-hostname-val-85598", + "ptnii-equip-name": "example-ptnii-equip-name-val-85834", + "number-of-cpus": 280, + "disk-in-gigabytes": 78521, + "ram-in-megabytes": 36975, + "equip-type": "example-equip-type-val-47930", + "equip-vendor": "example-equip-vendor-val-59512", + "equip-model": "example-equip-model-val-46076", + "fqdn": "example-fqdn-val-74486", + "pserver-selflink": "example-pserver-selflink-val-72481", + "ipv4-oam-address": "example-ipv4-oam-address-val-16616", + "serial-number": "example-serial-number-val-92800", + "ipaddress-v4-loopback-0": "example-ipaddress-v4-loopback0-val-61384", + "ipaddress-v6-loopback-0": "example-ipaddress-v6-loopback0-val-91056", + "ipaddress-v4-aim": "example-ipaddress-v4-aim-val-72233", + "ipaddress-v6-aim": "example-ipaddress-v6-aim-val-13572", + "ipaddress-v6-oam": "example-ipaddress-v6-oam-val-84518", + "inv-status": "example-inv-status-val-5042", + "pserver-id": "example-pserver-id-val-15622", + "internet-topology": "example-internet-topology-val-31234", + "in-maint": true, + "pserver-name2": "example-pserver-name2-val-93509", + "purpose": "example-purpose-val-52320", + "prov-status": "example-prov-status-val-47313", + "management-option": "example-management-option-val-72434", + "host-profile": "example-host-profile-val-84672", + "relationship-list": { + "relationship": [ + { + "related-to": "generic-vnf", + "relationship-label": "tosca.relationships.HostedOn", + "related-link": "/aai/v14/network/generic-vnfs/generic-vnf/generic-vnf-notification", + "relationship-data": [ + { + "relationship-key": "generic-vnf.vnf-id", + "relationship-value": "generic-vnf-notification" + } + ], + "related-to-property": [ + { + "property-key": "generic-vnf.vnf-name" + } + ] + } + ] + } +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-body-delete-edge-between-pserver-and-generic-vnf.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-body-delete-edge-between-pserver-and-generic-vnf.json new file mode 100644 index 00000000..369bc29b --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-body-delete-edge-between-pserver-and-generic-vnf.json @@ -0,0 +1,28 @@ +{ + "hostname": "example-hostname-val-85598", + "ptnii-equip-name": "example-ptnii-equip-name-val-85834", + "number-of-cpus": 280, + "disk-in-gigabytes": 78521, + "ram-in-megabytes": 36975, + "equip-type": "example-equip-type-val-47930", + "equip-vendor": "example-equip-vendor-val-59512", + "equip-model": "example-equip-model-val-46076", + "fqdn": "example-fqdn-val-74486", + "pserver-selflink": "example-pserver-selflink-val-72481", + "ipv4-oam-address": "example-ipv4-oam-address-val-16616", + "serial-number": "example-serial-number-val-92800", + "ipaddress-v4-loopback-0": "example-ipaddress-v4-loopback0-val-61384", + "ipaddress-v6-loopback-0": "example-ipaddress-v6-loopback0-val-91056", + "ipaddress-v4-aim": "example-ipaddress-v4-aim-val-72233", + "ipaddress-v6-aim": "example-ipaddress-v6-aim-val-13572", + "ipaddress-v6-oam": "example-ipaddress-v6-oam-val-84518", + "inv-status": "example-inv-status-val-5042", + "pserver-id": "example-pserver-id-val-15622", + "internet-topology": "example-internet-topology-val-31234", + "in-maint": true, + "pserver-name2": "example-pserver-name2-val-93509", + "purpose": "example-purpose-val-52320", + "prov-status": "example-prov-status-val-47313", + "management-option": "example-management-option-val-72434", + "host-profile": "example-host-profile-val-84672" +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-header-create-child-on-existing-obj.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-header-create-child-on-existing-obj.json new file mode 100644 index 00000000..e9c408af --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-header-create-child-on-existing-obj.json @@ -0,0 +1,9 @@ +{ + "id": "JUNIT-TRANSACTION", + "source-name": "JUNIT", + "version": "v14", + "action": "CREATE", + "entity-type": "p-interface", + "top-entity-type": "pserver", + "entity-link": "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598/p-interfaces/p-interface/p-interface-1" +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-header-create-edge-between-pserver-and-generic-vnf.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-header-create-edge-between-pserver-and-generic-vnf.json new file mode 100644 index 00000000..2c255c1f --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-header-create-edge-between-pserver-and-generic-vnf.json @@ -0,0 +1,9 @@ +{ + "id": "JUNIT-TRANSACTION", + "source-name": "JUNIT", + "version": "v14", + "action": "UPDATE", + "entity-type": "pserver", + "top-entity-type": "pserver", + "entity-link": "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598" +} diff --git a/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-header-delete-edge-between-pserver-and-generic-vnf.json b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-header-delete-edge-between-pserver-and-generic-vnf.json new file mode 100644 index 00000000..2c255c1f --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/notification-dmaap-events/depth-zero/expected-notification-header-delete-edge-between-pserver-and-generic-vnf.json @@ -0,0 +1,9 @@ +{ + "id": "JUNIT-TRANSACTION", + "source-name": "JUNIT", + "version": "v14", + "action": "UPDATE", + "entity-type": "pserver", + "top-entity-type": "pserver", + "entity-link": "/aai/v14/cloud-infrastructure/pservers/pserver/example-hostname-val-85598" +} diff --git a/aai-core/src/test/resources/payloads/resource/prevalidation/failed-response-with-violations.json b/aai-core/src/test/resources/payloads/resource/prevalidation/failed-response-with-violations.json new file mode 100644 index 00000000..409516dc --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/prevalidation/failed-response-with-violations.json @@ -0,0 +1,28 @@ +{ + "validationId": "52245aa2-72a8-440d-87e2-570272aa4a83", + "validationTimestamp": "20191201T211503Z", + "entityId": { + "vnf-id": "vnf-jenkins-15903-3" + }, + "entityName": "ormfl405me3", + "entityType": "generic-vnf", + "entityLink": "network/generic-vnfs/generic-vnf/vnf-jenkins-15903-3", + "resourceVersion": "1567815933280", + "requestor": "JUNIT", + "violations": [{ + "violationId": "37d6a7ebc1fc244f9dd04b1518726a9b4cc2350e6ff478c69502e8aeb1508333", + "modelName": null, + "category": "INVALID_VALUE", + "severity": "MAJOR", + "violationType": "Dlp_rule", + "validationRule": "DLP validate generic-vnf nf-values", + "violationDetails": { + "nf-role": "vSAEGW", + "nf-naming-code": "foo", + "nf-type": "blah", + "nf-function": "blah" + }, + "errorMessage": "Invalid nf values, check nf-type, nf-role, nf-function, and nf-naming-code" + } + ] +} diff --git a/aai-core/src/test/resources/payloads/resource/prevalidation/success-request-with-no-violations.json b/aai-core/src/test/resources/payloads/resource/prevalidation/success-request-with-no-violations.json new file mode 100644 index 00000000..328f9a26 --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/prevalidation/success-request-with-no-violations.json @@ -0,0 +1,22 @@ +{ + "cambria.partition": "AAI", + "event-header": { + "severity": "NORMAL", + "entity-type": "pserver", + "top-entity-type": "pserver", + "entity-link": "/aai/v19/cloud-infrastructure/pservers/pserver/test-pserver234", + "event-type": "AAI-EVENT", + "domain": "uINT6", + "action": "CREATE", + "sequence-number": "0", + "id": "70b33094-9d60-4e49-9a42-9f9b45ef1aa6", + "source-name": "JUNIT", + "version": "v19", + "timestamp": "20191202-01:26:24:749" + }, + "entity": { + "hostname": "test-pserver234", + "in-maint": false, + "resource-version": "1575249983853" + } +} diff --git a/aai-core/src/test/resources/payloads/resource/prevalidation/success-response-with-empty-violations.json b/aai-core/src/test/resources/payloads/resource/prevalidation/success-response-with-empty-violations.json new file mode 100644 index 00000000..ecd907a1 --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/prevalidation/success-response-with-empty-violations.json @@ -0,0 +1,13 @@ +{ + "validationId": "52245aa2-72a8-440d-87e2-570272aa4a83b", + "validationTimestamp": "20191201T211503Z", + "entityId": { + "vnf-id": "vnf-jenkins-15903-3" + }, + "entityName": "ormfl405me3", + "entityType": "generic-vnf", + "entityLink": "network/generic-vnfs/generic-vnf/vnf-jenkins-15903-3", + "resourceVersion": "1567815933280", + "requestor": "JUNIT", + "violations": [] +} diff --git a/aai-core/src/test/resources/payloads/resource/prevalidation/success-response-with-exclude-violations.json b/aai-core/src/test/resources/payloads/resource/prevalidation/success-response-with-exclude-violations.json new file mode 100644 index 00000000..106b763a --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/prevalidation/success-response-with-exclude-violations.json @@ -0,0 +1,12 @@ +{ + "validationId": "52245aa2-72a8-440d-87e2-570272aa4a83b", + "validationTimestamp": "20191201T211503Z", + "entityId": { + "vnf-id": "vnf-jenkins-15903-3" + }, + "entityName": "ormfl405me3", + "entityType": "generic-vnf", + "entityLink": "network/generic-vnfs/generic-vnf/vnf-jenkins-15903-3", + "resourceVersion": "1567815933280", + "requestor": "JUNIT" +} diff --git a/aai-core/src/test/resources/payloads/resource/pserver-implied-delete.json b/aai-core/src/test/resources/payloads/resource/pserver-implied-delete.json new file mode 100644 index 00000000..5cc35713 --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/pserver-implied-delete.json @@ -0,0 +1,23 @@ +{ + "hostname": "test-pserver-implied-delete", + "p-interfaces": { + "p-interface": [ + { + "interface-name": "test-p-interface-implied-delete-1", + "selflink": "somelink" + }, + { + "interface-name": "test-p-interface-implied-delete-2", + "selflink": "somelink" + }, + { + "interface-name": "test-p-interface-implied-delete-3", + "selflink": "somelink" + }, + { + "interface-name": "test-p-interface-implied-delete-4", + "selflink": "somelink" + } + ] + } +} diff --git a/aai-core/src/test/resources/payloads/resource/pserver-to-gvnf-relationship-notification.json b/aai-core/src/test/resources/payloads/resource/pserver-to-gvnf-relationship-notification.json new file mode 100644 index 00000000..cb8ec43a --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/pserver-to-gvnf-relationship-notification.json @@ -0,0 +1,4 @@ +{ + "related-to": "generic-vnf", + "related-link": "/network/generic-vnfs/generic-vnf/generic-vnf-notification" +} diff --git a/aai-core/src/test/resources/payloads/resource/pserver-with-children-for-notification.json b/aai-core/src/test/resources/payloads/resource/pserver-with-children-for-notification.json new file mode 100644 index 00000000..f0dd071c --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/pserver-with-children-for-notification.json @@ -0,0 +1,273 @@ +{ + "hostname": "example-hostname-val-85598", + "ptnii-equip-name": "example-ptnii-equip-name-val-85834", + "number-of-cpus": 280, + "disk-in-gigabytes": 78521, + "ram-in-megabytes": 36975, + "equip-type": "example-equip-type-val-47930", + "equip-vendor": "example-equip-vendor-val-59512", + "equip-model": "example-equip-model-val-46076", + "fqdn": "example-fqdn-val-74486", + "pserver-selflink": "example-pserver-selflink-val-72481", + "ipv4-oam-address": "example-ipv4-oam-address-val-16616", + "serial-number": "example-serial-number-val-92800", + "ipaddress-v4-loopback-0": "example-ipaddress-v4-loopback0-val-61384", + "ipaddress-v6-loopback-0": "example-ipaddress-v6-loopback0-val-91056", + "ipaddress-v4-aim": "example-ipaddress-v4-aim-val-72233", + "ipaddress-v6-aim": "example-ipaddress-v6-aim-val-13572", + "ipaddress-v6-oam": "example-ipaddress-v6-oam-val-84518", + "inv-status": "example-inv-status-val-5042", + "pserver-id": "example-pserver-id-val-15622", + "internet-topology": "example-internet-topology-val-31234", + "in-maint": true, + "pserver-name2": "example-pserver-name2-val-93509", + "purpose": "example-purpose-val-52320", + "prov-status": "example-prov-status-val-47313", + "management-option": "example-management-option-val-72434", + "host-profile": "example-host-profile-val-84672", + "p-interfaces": { + "p-interface": [ + { + "interface-name": "example-interface-name-val-46147", + "selflink": "example-selflink-val-81029", + "speed-value": "example-speed-value-val-47874", + "speed-units": "example-speed-units-val-10396", + "port-description": "example-port-description-val-53068", + "equipment-identifier": "example-equipment-identifier-val-63234", + "interface-role": "example-interface-role-val-49232", + "interface-type": "example-interface-type-val-21757", + "prov-status": "example-prov-status-val-19117", + "in-maint": true, + "inv-status": "example-inv-status-val-48715", + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-13366", + "interface-role": "example-interface-role-val-29488", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-78396", + "selflink": "example-selflink-val-4757", + "interface-id": "example-interface-id-val-79486", + "macaddr": "example-macaddr-val-52194", + "network-name": "example-network-name-val-80678", + "management-option": "example-management-option-val-53535", + "interface-description": "example-interface-description-val-299", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-9736", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-62271", + "priority": 82452, + "vlans": { + "vlan": [ + { + "vlan-interface": "example-vlan-interface-val-31470", + "vlan-id-inner": 61286171, + "vlan-id-outer": 64615174, + "speed-value": "example-speed-value-val-80457", + "speed-units": "example-speed-units-val-51587", + "vlan-description": "example-vlan-description-val-97575", + "backdoor-connection": "example-backdoor-connection-val-3179", + "vpn-key": "example-vpn-key-val-50069", + "orchestration-status": "example-orchestration-status-val-34071", + "in-maint": true, + "prov-status": "example-prov-status-val-62615", + "is-ip-unnumbered": true, + "is-private": true, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-8171", + "l3-interface-ipv4-prefix-length": 39266592, + "vlan-id-inner": 91284707, + "vlan-id-outer": 80343467, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-52921", + "neutron-subnet-id": "example-neutron-subnet-id-val-88134" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-70726", + "l3-interface-ipv6-prefix-length": 81422758, + "vlan-id-inner": 15099560, + "vlan-id-outer": 46643832, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-97954", + "neutron-subnet-id": "example-neutron-subnet-id-val-23889" + } + ] + } + ] + }, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-62086", + "interface-role": "example-interface-role-val-13107", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-32015", + "selflink": "example-selflink-val-31580", + "interface-id": "example-interface-id-val-57805", + "macaddr": "example-macaddr-val-54266", + "network-name": "example-network-name-val-38517", + "management-option": "example-management-option-val-8801", + "interface-description": "example-interface-description-val-88573", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-99164", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-14581", + "priority": 80355, + "admin-status": "example-admin-status-val-29720" + } + ] + }, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-31324", + "l3-interface-ipv4-prefix-length": 36060646, + "vlan-id-inner": 62164959, + "vlan-id-outer": 93058593, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-39206", + "neutron-subnet-id": "example-neutron-subnet-id-val-27746" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-72897", + "l3-interface-ipv6-prefix-length": 29592510, + "vlan-id-inner": 18402161, + "vlan-id-outer": 651158, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-6821", + "neutron-subnet-id": "example-neutron-subnet-id-val-11217" + } + ], + "admin-status": "example-admin-status-val-81745" + } + ] + } + } + ] + }, + "lag-interfaces": { + "lag-interface": [ + { + "interface-name": "example-interface-name-val-87366", + "interface-description": "example-interface-description-val-3722", + "speed-value": "example-speed-value-val-73546", + "speed-units": "example-speed-units-val-73658", + "interface-id": "example-interface-id-val-62385", + "interface-role": "example-interface-role-val-60746", + "prov-status": "example-prov-status-val-26239", + "in-maint": true, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-69579", + "interface-role": "example-interface-role-val-64571", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-68385", + "selflink": "example-selflink-val-29611", + "interface-id": "example-interface-id-val-75464", + "macaddr": "example-macaddr-val-7285", + "network-name": "example-network-name-val-52284", + "management-option": "example-management-option-val-26028", + "interface-description": "example-interface-description-val-37641", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-56460", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-23301", + "priority": 84739, + "vlans": { + "vlan": [ + { + "vlan-interface": "example-vlan-interface-val-56661", + "vlan-id-inner": 33305644, + "vlan-id-outer": 30871600, + "speed-value": "example-speed-value-val-1929", + "speed-units": "example-speed-units-val-71630", + "vlan-description": "example-vlan-description-val-63003", + "backdoor-connection": "example-backdoor-connection-val-41834", + "vpn-key": "example-vpn-key-val-16552", + "orchestration-status": "example-orchestration-status-val-95322", + "in-maint": true, + "prov-status": "example-prov-status-val-89886", + "is-ip-unnumbered": true, + "is-private": true, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-69142", + "l3-interface-ipv4-prefix-length": 11099430, + "vlan-id-inner": 88996967, + "vlan-id-outer": 23003182, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-53091", + "neutron-subnet-id": "example-neutron-subnet-id-val-41571" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-27490", + "l3-interface-ipv6-prefix-length": 20167688, + "vlan-id-inner": 40775405, + "vlan-id-outer": 75855907, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-9739", + "neutron-subnet-id": "example-neutron-subnet-id-val-806" + } + ] + } + ] + }, + "l-interfaces": { + "l-interface": [ + { + "interface-name": "example-interface-name-val-49266", + "interface-role": "example-interface-role-val-210", + "v6-wan-link-ip": "example-v6-wan-link-ip-val-81668", + "selflink": "example-selflink-val-6356", + "interface-id": "example-interface-id-val-99531", + "macaddr": "example-macaddr-val-25092", + "network-name": "example-network-name-val-3319", + "management-option": "example-management-option-val-79883", + "interface-description": "example-interface-description-val-54501", + "is-port-mirrored": true, + "in-maint": true, + "prov-status": "example-prov-status-val-48840", + "is-ip-unnumbered": true, + "allowed-address-pairs": "example-allowed-address-pairs-val-26846", + "priority": 21862, + "admin-status": "example-admin-status-val-89244" + } + ] + }, + "l3-interface-ipv4-address-list": [ + { + "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-61251", + "l3-interface-ipv4-prefix-length": 91875404, + "vlan-id-inner": 36470314, + "vlan-id-outer": 96344091, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-17339", + "neutron-subnet-id": "example-neutron-subnet-id-val-86128" + } + ], + "l3-interface-ipv6-address-list": [ + { + "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-31476", + "l3-interface-ipv6-prefix-length": 11663872, + "vlan-id-inner": 28459412, + "vlan-id-outer": 9852622, + "is-floating": true, + "neutron-network-id": "example-neutron-network-id-val-15120", + "neutron-subnet-id": "example-neutron-subnet-id-val-36088" + } + ], + "admin-status": "example-admin-status-val-81055" + } + ] + } + } + ] + } +} diff --git a/aai-core/src/test/resources/payloads/resource/transform-results-to-result.json b/aai-core/src/test/resources/payloads/resource/transform-results-to-result.json new file mode 100644 index 00000000..63fa9114 --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/transform-results-to-result.json @@ -0,0 +1,61 @@ +{ + "results": [ + { + "id": "286724136", + "node-type": "pserver", + "url": "/aai/v18/cloud-infrastructure/pservers/pserver/test-pserver1", + "properties": { + "equip-type": "SERVER", + "equip-vendor": "SomeVendor", + "equip-model": "SomeModel", + "in-maint": false, + "last-mod-source-of-truth": "AAIRctFeed", + "aai-node-type": "pserver", + "aai-created-ts": 1568997029298, + "aai-last-mod-ts": 1568997029298, + "source-of-truth": "AAI", + "aai-uri": "/cloud-infrastructure/pservers/pserver/test-pserver1", + "aai-uuid": "05fa7b64-59e4-44a1-8162-e32746659c77", + "ipv4-oam-address": "1.2.3.4", + "hostname": "test-pserver1", + "pserver-id": "6bf4944a-9f13-4bb8-8f49-b61060793510", + "purpose": "Standalone", + "fqdn": "a.b.c.d", + "ptnii-equip-name": "test-pserver1", + "resource-version": "1568997029298" + }, + "related-to": [ + { + "id": "286724232", + "relationship-label": "org.onap.relationships.inventory.LocatedIn", + "node-type": "complex", + "url": "/aai/v18/cloud-infrastructure/complexes/complex/testcomplex2" + }, + { + "id": "286724233", + "relationship-label": "org.onap.relationships.inventory.LocatedIn", + "node-type": "complex", + "url": "/aai/v18/cloud-infrastructure/complexes/complex/testcomplex1" + } + ] + }, + { + "id": "286724152", + "node-type": "pserver", + "url": "/aai/v18/cloud-infrastructure/pservers/pserver/test-pserver2", + "properties": { + "in-maint": false, + "last-mod-source-of-truth": "JUNITTESTAPP2", + "aai-node-type": "pserver", + "aai-created-ts": 1553805738492, + "aai-last-mod-ts": 1553805738492, + "source-of-truth": "JUNITTESTAPP2", + "aai-uri": "/cloud-infrastructure/pservers/pserver/test-pserver2", + "aai-uuid": "13a8440c-7fb4-4f41-a141-6e1d9e895b4a", + "hostname": "test-pserver2", + "resource-version": "1553805738492" + }, + "related-to": [] + } + ] +} diff --git a/aai-core/src/test/resources/payloads/resource/vnfc-related-to-vf-module.json b/aai-core/src/test/resources/payloads/resource/vnfc-related-to-vf-module.json new file mode 100644 index 00000000..139681fa --- /dev/null +++ b/aai-core/src/test/resources/payloads/resource/vnfc-related-to-vf-module.json @@ -0,0 +1,19 @@ +{ + "vnfc-name": "test-vnfc11", + "nfc-naming-code": "testname", + "nfc-function": "test-value", + "relationship-list": { + "relationship": [{ + "related-to": "vf-module", + "relationship-data": [{ + "relationship-key": "vnf.vnf-id", + "relationship-value": "test-vnf11" + }, { + "relationship-key": "vf-module.vf-module-id", + "relationship-value": "vf-module-test11" + } + ] + } + ] + } +} |