summaryrefslogtreecommitdiffstats
path: root/src/main/java
diff options
context:
space:
mode:
authorJessica Wagantall <jwagantall@linuxfoundation.org>2020-12-08 09:33:13 -0800
committerJessica Wagantall <jwagantall@linuxfoundation.org>2020-12-08 09:33:25 -0800
commitbfc36d8cb714661eb00ba805d7858872cbce5308 (patch)
tree99052cc69000d791187d45381b4253353c77bef1 /src/main/java
parentdcd4bab11134095747a90d05f97a578b7d909520 (diff)
parent1083012bb7376c63d26b7caf9e6251d736342e30 (diff)
Merge branch 'master' of /home/jwagantall/linuxfoundation/onap/IT-21108/clamp
Signed-off-by: Jessica Wagantall <jwagantall@linuxfoundation.org>
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/onap/clamp/authorization/AuthorizationController.java189
-rw-r--r--src/main/java/org/onap/clamp/authorization/CldsUser.java97
-rw-r--r--src/main/java/org/onap/clamp/authorization/SecureServicePermission.java203
-rw-r--r--src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java46
-rw-r--r--src/main/java/org/onap/clamp/authorization/UserService.java47
-rw-r--r--src/main/java/org/onap/clamp/clds/Application.java182
-rw-r--r--src/main/java/org/onap/clamp/clds/ClampInUserAuditorAware.java40
-rw-r--r--src/main/java/org/onap/clamp/clds/ClampServlet.java142
-rw-r--r--src/main/java/org/onap/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java53
-rw-r--r--src/main/java/org/onap/clamp/clds/client/CdsServices.java229
-rw-r--r--src/main/java/org/onap/clamp/clds/client/DcaeInventoryServices.java141
-rw-r--r--src/main/java/org/onap/clamp/clds/client/PolicyEngineServices.java227
-rw-r--r--src/main/java/org/onap/clamp/clds/config/AafConfiguration.java67
-rw-r--r--src/main/java/org/onap/clamp/clds/config/CamelConfiguration.java134
-rw-r--r--src/main/java/org/onap/clamp/clds/config/ClampProperties.java105
-rw-r--r--src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java74
-rw-r--r--src/main/java/org/onap/clamp/clds/config/DefaultDictionaryElements.java167
-rw-r--r--src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java138
-rw-r--r--src/main/java/org/onap/clamp/clds/config/SslConfig.java93
-rw-r--r--src/main/java/org/onap/clamp/clds/config/SystemPropertiesLoader.java49
-rw-r--r--src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java99
-rw-r--r--src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java290
-rw-r--r--src/main/java/org/onap/clamp/clds/config/spring/CldsConfiguration.java55
-rw-r--r--src/main/java/org/onap/clamp/clds/config/spring/SdcControllerConfiguration.java113
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/CldsConfigException.java61
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/CldsUsersException.java61
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/NotAuthorizedException.java61
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/cds/CdsParametersException.java53
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/dcae/DcaeDeploymentException.java61
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/sdc/controller/BlueprintParserException.java54
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java54
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java54
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcControllerException.java54
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcDownloadException.java54
-rw-r--r--src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcParametersException.java54
-rw-r--r--src/main/java/org/onap/clamp/clds/filter/ClampCadiFilter.java190
-rw-r--r--src/main/java/org/onap/clamp/clds/model/ClampInformation.java62
-rw-r--r--src/main/java/org/onap/clamp/clds/model/CldsHealthCheck.java60
-rw-r--r--src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java67
-rw-r--r--src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryCache.java62
-rw-r--r--src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponse.java102
-rw-r--r--src/main/java/org/onap/clamp/clds/model/dcae/DcaeLinks.java60
-rw-r--r--src/main/java/org/onap/clamp/clds/model/dcae/DcaeOperationStatusResponse.java88
-rw-r--r--src/main/java/org/onap/clamp/clds/sdc/controller/DistributionStatusMessage.java84
-rw-r--r--src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java435
-rw-r--r--src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleControllerStatus.java28
-rw-r--r--src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintArtifact.java70
-rw-r--r--src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintMicroService.java93
-rw-r--r--src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParser.java222
-rw-r--r--src/main/java/org/onap/clamp/clds/sdc/controller/installer/ChainGenerator.java91
-rw-r--r--src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java221
-rw-r--r--src/main/java/org/onap/clamp/clds/service/CldsHealthcheckService.java81
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/JsonEditorSchemaConstants.java86
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/ToscaSchemaConstants.java83
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertor.java780
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java98
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/UnknownComponentException.java34
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/elements/ArrayField.java72
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/elements/Constraint.java222
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElement.java121
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElementProperty.java135
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java76
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java43
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java220
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/execution/target/ToscaMetadataTargetProcess.java40
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java346
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaElementParser.java103
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java32
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java219
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplate.java224
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateField.java149
-rw-r--r--src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateManager.java187
-rw-r--r--src/main/java/org/onap/clamp/clds/util/ClampVersioning.java62
-rw-r--r--src/main/java/org/onap/clamp/clds/util/CryptoUtils.java168
-rw-r--r--src/main/java/org/onap/clamp/clds/util/JsonUtils.java55
-rw-r--r--src/main/java/org/onap/clamp/clds/util/LogMessages.java36
-rw-r--r--src/main/java/org/onap/clamp/clds/util/LoggingUtils.java414
-rw-r--r--src/main/java/org/onap/clamp/clds/util/OnapLogConstants.java304
-rw-r--r--src/main/java/org/onap/clamp/clds/util/ResourceFileUtils.java89
-rw-r--r--src/main/java/org/onap/clamp/configuration/ClampGsonDataFormat.java172
-rw-r--r--src/main/java/org/onap/clamp/dao/model/gson/converter/InstantDeserializer.java47
-rw-r--r--src/main/java/org/onap/clamp/dao/model/gson/converter/InstantSerializer.java41
-rw-r--r--src/main/java/org/onap/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java109
-rw-r--r--src/main/java/org/onap/clamp/dao/model/jsontype/JsonTypeDescriptor.java107
-rw-r--r--src/main/java/org/onap/clamp/dao/model/jsontype/StringJsonUserType.java52
-rw-r--r--src/main/java/org/onap/clamp/flow/log/FlowLogOperation.java101
-rw-r--r--src/main/java/org/onap/clamp/loop/CsarInstaller.java210
-rw-r--r--src/main/java/org/onap/clamp/loop/Loop.java391
-rw-r--r--src/main/java/org/onap/clamp/loop/LoopController.java204
-rw-r--r--src/main/java/org/onap/clamp/loop/LoopService.java190
-rw-r--r--src/main/java/org/onap/clamp/loop/LoopState.java28
-rw-r--r--src/main/java/org/onap/clamp/loop/LoopsRepository.java37
-rw-r--r--src/main/java/org/onap/clamp/loop/cds/CdsDataInstaller.java173
-rw-r--r--src/main/java/org/onap/clamp/loop/common/AuditEntity.java148
-rw-r--r--src/main/java/org/onap/clamp/loop/components/external/DcaeComponent.java253
-rw-r--r--src/main/java/org/onap/clamp/loop/components/external/ExternalComponent.java59
-rw-r--r--src/main/java/org/onap/clamp/loop/components/external/ExternalComponentState.java128
-rw-r--r--src/main/java/org/onap/clamp/loop/components/external/PolicyComponent.java195
-rw-r--r--src/main/java/org/onap/clamp/loop/deploy/DcaeDeployParameters.java119
-rw-r--r--src/main/java/org/onap/clamp/loop/log/LogType.java28
-rw-r--r--src/main/java/org/onap/clamp/loop/log/LoopLog.java196
-rw-r--r--src/main/java/org/onap/clamp/loop/log/LoopLogRepository.java32
-rw-r--r--src/main/java/org/onap/clamp/loop/log/LoopLogService.java51
-rw-r--r--src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java129
-rw-r--r--src/main/java/org/onap/clamp/loop/service/Service.java168
-rw-r--r--src/main/java/org/onap/clamp/loop/service/ServicesRepository.java31
-rw-r--r--src/main/java/org/onap/clamp/loop/template/LoopElementModel.java298
-rw-r--r--src/main/java/org/onap/clamp/loop/template/LoopElementModelsRepository.java31
-rw-r--r--src/main/java/org/onap/clamp/loop/template/LoopTemplate.java341
-rw-r--r--src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModel.java194
-rw-r--r--src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModelId.java100
-rw-r--r--src/main/java/org/onap/clamp/loop/template/LoopTemplatesRepository.java37
-rw-r--r--src/main/java/org/onap/clamp/loop/template/LoopTemplatesService.java67
-rw-r--r--src/main/java/org/onap/clamp/loop/template/LoopType.java42
-rw-r--r--src/main/java/org/onap/clamp/loop/template/LoopTypeConvertor.java52
-rw-r--r--src/main/java/org/onap/clamp/loop/template/PolicyModel.java282
-rw-r--r--src/main/java/org/onap/clamp/loop/template/PolicyModelId.java93
-rw-r--r--src/main/java/org/onap/clamp/loop/template/PolicyModelsRepository.java38
-rw-r--r--src/main/java/org/onap/clamp/loop/template/PolicyModelsService.java173
-rw-r--r--src/main/java/org/onap/clamp/policy/Policy.java287
-rw-r--r--src/main/java/org/onap/clamp/policy/PolicyService.java36
-rw-r--r--src/main/java/org/onap/clamp/policy/downloader/PolicyEngineController.java78
-rw-r--r--src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicy.java276
-rw-r--r--src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyRepository.java32
-rw-r--r--src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyService.java112
-rw-r--r--src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java218
-rw-r--r--src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepository.java32
-rw-r--r--src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java352
-rw-r--r--src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java94
-rw-r--r--src/main/java/org/onap/clamp/policy/pdpgroup/PdpGroup.java93
-rw-r--r--src/main/java/org/onap/clamp/policy/pdpgroup/PdpSubgroup.java56
-rw-r--r--src/main/java/org/onap/clamp/policy/pdpgroup/PolicyModelKey.java126
-rw-r--r--src/main/java/org/onap/clamp/tosca/Dictionary.java219
-rw-r--r--src/main/java/org/onap/clamp/tosca/DictionaryElement.java254
-rw-r--r--src/main/java/org/onap/clamp/tosca/DictionaryElementsRepository.java32
-rw-r--r--src/main/java/org/onap/clamp/tosca/DictionaryRepository.java40
-rw-r--r--src/main/java/org/onap/clamp/tosca/DictionaryService.java141
-rw-r--r--src/main/java/org/onap/clamp/util/PassDecoder.java65
-rw-r--r--src/main/java/org/onap/clamp/util/SemanticVersioning.java91
139 files changed, 17796 insertions, 0 deletions
diff --git a/src/main/java/org/onap/clamp/authorization/AuthorizationController.java b/src/main/java/org/onap/clamp/authorization/AuthorizationController.java
new file mode 100644
index 000000000..f4da09a2e
--- /dev/null
+++ b/src/main/java/org/onap/clamp/authorization/AuthorizationController.java
@@ -0,0 +1,189 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * 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.clamp.authorization;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.util.Date;
+import org.apache.camel.Exchange;
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.clds.exception.NotAuthorizedException;
+import org.onap.clamp.clds.model.ClampInformation;
+import org.onap.clamp.clds.util.LoggingUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+/**
+ * Verify user has right permissions.
+ */
+@Component
+public class AuthorizationController {
+
+ protected static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(AuthorizationController.class);
+ protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ protected static final EELFLogger securityLogger =
+ EELFManager.getInstance().getSecurityLogger();
+
+ // By default we'll set it to a default handler
+ @Autowired
+ private ClampProperties refProp;
+
+ private SecurityContext securityContext = SecurityContextHolder.getContext();
+
+ public static final String PERM_PREFIX = "security.permission.type.";
+ private static final String PERM_INSTANCE = "security.permission.instance";
+
+ private static String retrieveUserName(SecurityContext securityContext) {
+ if (securityContext == null || securityContext.getAuthentication() == null) {
+ return null;
+ }
+ if ((securityContext.getAuthentication().getPrincipal()) instanceof String) {
+ // anonymous case
+ return ((String) securityContext.getAuthentication().getPrincipal());
+ } else {
+ return ((UserDetails) securityContext.getAuthentication().getPrincipal()).getUsername();
+ }
+ }
+
+ /**
+ * Get the principal name.
+ *
+ * @return The principal name
+ */
+ public static String getPrincipalName(SecurityContext securityContext) {
+ String principal = AuthorizationController.retrieveUserName(securityContext);
+ String name = "Not found";
+ if (principal != null) {
+ name = principal;
+ }
+ return name;
+ }
+
+ /**
+ * Insert authorize the api based on the permission.
+ *
+ * @param camelExchange The Camel Exchange object containing the properties
+ * @param typeVar The type of the permissions
+ * @param instanceVar The instance of the permissions. e.g. dev
+ * @param action The action of the permissions. e.g. read
+ */
+ public void authorize(Exchange camelExchange, String typeVar, String instanceVar,
+ String action) {
+ String type = refProp.getStringValue(PERM_PREFIX + typeVar);
+ String instance = refProp.getStringValue(PERM_INSTANCE);
+
+ if (null == type || type.isEmpty()) {
+ // authorization is turned off, since the permission is not defined
+ return;
+ }
+ if (null != instanceVar && !instanceVar.isEmpty()) {
+ instance = instanceVar;
+ }
+ String principalName = AuthorizationController.getPrincipalName(this.securityContext);
+ SecureServicePermission perm = SecureServicePermission.create(type, instance, action);
+ Date startTime = new Date();
+ LoggingUtils.setTargetContext("Clamp", "authorize");
+ LoggingUtils.setTimeContext(startTime, new Date());
+ securityLogger.debug("checking if {} has permission: {}", principalName, perm);
+
+ if (!isUserPermitted(perm)) {
+ String msg = principalName + " does not have permission: " + perm;
+ LoggingUtils.setErrorContext("100", "Authorization Error");
+ securityLogger.warn(msg);
+ throw new NotAuthorizedException(msg);
+ }
+ }
+
+ /**
+ * Insert authorize the api based on the permission.
+ *
+ * @param inPermission Security permission in input
+ * @return True if user is permitted
+ */
+ public boolean isUserPermitted(SecureServicePermission inPermission) {
+
+ String principalName = AuthorizationController.getPrincipalName(this.securityContext);
+ // check if the user has the permission key or the permission key with a
+ // combination of all instance and/or all action.
+ if (hasRole(inPermission.getKey()) || hasRole(inPermission.getKeyAllInstance())) {
+ auditLogger.info("{} authorized because user has permission with * for instance: {}",
+ principalName, inPermission.getKey().replace("|", ":"));
+ return true;
+ // the rest of these don't seem to be required - isUserInRole method
+ // appears to take * as a wildcard
+ } else if (hasRole(inPermission.getKeyAllInstanceAction())) {
+ auditLogger.info(
+ "{} authorized because user has permission with * for instance and * for action: {}",
+ principalName, inPermission.getKey().replace("|", ":"));
+ return true;
+ } else if (hasRole(inPermission.getKeyAllAction())) {
+ auditLogger.info("{} authorized because user has permission with * for action: {}",
+ principalName, inPermission.getKey().replace("|", ":"));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected boolean hasRole(String role) {
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication == null) {
+ return false;
+ }
+ for (GrantedAuthority auth : authentication.getAuthorities()) {
+ if (role.equals(auth.getAuthority())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets clds info. CLDS IFO service will return 3 things 1. User Name 2. CLDS
+ * code version that is currently installed from pom.xml file 3. User
+ * permissions
+ *
+ * @return the clds info
+ */
+ public ClampInformation getClampInformation() {
+ ClampInformation clampInfo = new ClampInformation();
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication == null) {
+ return new ClampInformation();
+ }
+ clampInfo.setUserName(AuthorizationController.getPrincipalName(this.securityContext));
+ for (GrantedAuthority auth : authentication.getAuthorities()) {
+ clampInfo.getAllPermissions().add(auth.getAuthority());
+ }
+ return clampInfo;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/authorization/CldsUser.java b/src/main/java/org/onap/clamp/authorization/CldsUser.java
new file mode 100644
index 000000000..b50f50cb2
--- /dev/null
+++ b/src/main/java/org/onap/clamp/authorization/CldsUser.java
@@ -0,0 +1,97 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.authorization;
+
+import java.util.Arrays;
+
+/**
+ * The class represents the CldsUser that can be extracted from cldsusers.json.
+ */
+public class CldsUser {
+
+ private String user;
+ private String password;
+ private SecureServicePermission[] permissions;
+
+ /**
+ * Returns the user.
+ *
+ * @return the user
+ */
+ public String getUser() {
+ return user;
+ }
+
+ /**
+ * Sets the user.
+ *
+ * @param user
+ * the user to set
+ */
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ /**
+ * Returns the password.
+ *
+ * @return the password
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * Sets the password.
+ *
+ * @param password
+ * the password to set
+ */
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ /**
+ * Returns the permissions.
+ *
+ * @return the permissions
+ */
+ public SecureServicePermission[] getPermissions() {
+ return Arrays.copyOf(permissions, permissions.length);
+ }
+
+ public String[] getPermissionsString() {
+ return Arrays.stream(getPermissions()).map(SecureServicePermission::getKey).toArray(String[]::new);
+ }
+
+ /**
+ * Sets the permissions.
+ *
+ * @param permissionsArray
+ * the permissions to set
+ */
+ public void setPermissions(SecureServicePermission[] permissionsArray) {
+ this.permissions = Arrays.copyOf(permissionsArray, permissionsArray.length);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/authorization/SecureServicePermission.java b/src/main/java/org/onap/clamp/authorization/SecureServicePermission.java
new file mode 100644
index 000000000..374aab90c
--- /dev/null
+++ b/src/main/java/org/onap/clamp/authorization/SecureServicePermission.java
@@ -0,0 +1,203 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.authorization;
+
+/**
+ * Permission class that can be instantiated easily using constructor or factory
+ * methods.
+ */
+public class SecureServicePermission {
+ public static final String ALL = "*";
+
+ private String type;
+ private String instance;
+ private String action;
+
+ /**
+ * Factory method to create permission given type, instance, and action.
+ *
+ * @param type type of the permission
+ * @param instance instance of the permission
+ * @param action action of the permission
+ * @return instance of SecureServicePermission with type, instance and action
+ */
+ public static SecureServicePermission create(String type, String instance, String action) {
+ return new SecureServicePermission(type, instance, action);
+ }
+
+ /**
+ * Factory method to create permission given type and instance. Default
+ * action to ALL/*.
+ *
+ * @param type type of the permission
+ * @param instance instance of the permission
+ * @return instance of SecureServicePermission with type, instance and default action
+ */
+ public static SecureServicePermission create(String type, String instance) {
+ return new SecureServicePermission(type, instance, ALL);
+ }
+
+ /**
+ * Factory method to create permission given type. Default instance and
+ * action to ALL/*.
+ *
+ * @param type type of the permission
+ * @return instance of SecureServicePermission with type and default instance and action
+ */
+ public static SecureServicePermission create(String type) {
+ return new SecureServicePermission(type, ALL, ALL);
+ }
+
+ /**
+ * Instantiate permission given type, instance, and action.
+ *
+ * @param type type of the permission
+ * @param instance instance of the permission
+ * @param action action of the permission
+ */
+ public SecureServicePermission(String type, String instance, String action) {
+ this.type = type;
+ this.instance = instance;
+ this.action = action;
+ }
+
+ /**
+ * Instantiate permission given type from concatenated string
+ *
+ * @param concatenatedString
+ * the string type|instance|action, less than 3 params can be
+ * provided (e.g. "permission-type-cl", "permission-type-cl|dev",
+ * "permission-type-cl|dev|update" )
+ */
+ public SecureServicePermission(String concatenatedString) {
+ String[] userInfo = concatenatedString.split("[|]");
+ // We should have at least 1 string
+ this.type = userInfo[0];
+ this.instance = (userInfo.length > 1 ? userInfo[1] : ALL);
+ this.action = (userInfo.length > 2 ? userInfo[2] : ALL);
+ }
+
+ /**
+ * Override toString - return permission in key format.
+ */
+ @Override
+ public String toString() {
+ return getKey();
+ }
+
+ /**
+ * Return Permission in Key format = type, instance, and action separate by
+ * pipe character.
+ *
+ * @return permission in key format
+ */
+ public String getKey() {
+ return type + "|" + instance + "|" + action;
+ }
+
+ /**
+ * Return Permission in Key format = type, all instance, and action separate
+ * by pipe character.
+ *
+ * @return permission in key format
+ */
+ public String getKeyAllInstance() {
+ return type + "|" + ALL + "|" + action;
+ }
+
+ /**
+ * Return Permission in Key format = type, all instance, and all action
+ * separate by pipe character.
+ *
+ * @return permission in key format
+ */
+ public String getKeyAllInstanceAction() {
+ return type + "|" + ALL + "|" + ALL;
+ }
+
+ /**
+ * Return Permission in Key format = type, instance, and all action separate
+ * by pipe character.
+ *
+ * @return permission in key format
+ */
+ public String getKeyAllAction() {
+ return type + "|" + instance + "|" + ALL;
+ }
+
+ /**
+ * Returns the permission type.
+ *
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Sets the type of permission.
+ *
+ * @param type the type to set
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the instance of permission.
+ *
+ * @return the instance
+ */
+ public String getInstance() {
+ return instance;
+ }
+
+ /**
+ * Sets the instance of permission.
+ *
+ * @param instance the instance to set
+ */
+ public void setInstance(String instance) {
+ this.instance = instance;
+ }
+
+ /**
+ * Returns the action of permission.
+ *
+ * @return the action
+ */
+ public String getAction() {
+ return action;
+ }
+
+ /**
+ * Sets the action of permission.
+ *
+ * @param action the action to set
+ */
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java b/src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java
new file mode 100644
index 000000000..026ee802c
--- /dev/null
+++ b/src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.clamp.authorization;
+
+
+import com.google.gson.Gson;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import java.lang.reflect.Type;
+
+public class SecureServicePermissionDeserializer implements JsonDeserializer<SecureServicePermission> {
+
+ @Override
+ public SecureServicePermission deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException {
+ if (json.isJsonPrimitive()) {
+ return new SecureServicePermission(json.getAsString());
+ } else {
+ // if not string try default deserialization
+ return new Gson().fromJson(json, SecureServicePermission.class);
+ }
+ }
+}
diff --git a/src/main/java/org/onap/clamp/authorization/UserService.java b/src/main/java/org/onap/clamp/authorization/UserService.java
new file mode 100644
index 000000000..b4f51c95b
--- /dev/null
+++ b/src/main/java/org/onap/clamp/authorization/UserService.java
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.authorization;
+
+
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+
+/**
+ * User service used for authorization verification at the login page. Do not
+ * remove this class.
+ */
+@Controller
+public class UserService {
+
+ private SecurityContext securityContext = SecurityContextHolder.getContext();
+
+ /**
+ * REST service that returns the username.
+ *
+ * @return the user name
+ */
+ public String getUser() {
+ return AuthorizationController.getPrincipalName(securityContext);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/Application.java b/src/main/java/org/onap/clamp/clds/Application.java
new file mode 100644
index 000000000..e83ff3e76
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/Application.java
@@ -0,0 +1,182 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * 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.clamp.clds;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import org.apache.catalina.connector.Connector;
+import org.onap.clamp.clds.util.ClampVersioning;
+import org.onap.clamp.clds.util.ResourceFileUtils;
+import org.onap.clamp.util.PassDecoder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.core.env.Environment;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@ComponentScan(basePackages = { "org.onap.clamp" })
+@SpringBootApplication(exclude = { SecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class })
+@EnableJpaRepositories(basePackages = { "org.onap.clamp" })
+@EntityScan(basePackages = { "org.onap.clamp" })
+@EnableTransactionManagement
+@EnableConfigurationProperties
+@EnableAsync
+@EnableScheduling
+@EnableJpaAuditing
+public class Application extends SpringBootServletInitializer {
+
+ protected static final EELFLogger eelfLogger = EELFManager.getInstance().getLogger(Application.class);
+ // This settings is an additional one to Spring config,
+ // only if we want to have an additional port automatically redirected to
+ // HTTPS
+ @Value("${server.http-to-https-redirection.port:none}")
+ private String httpRedirectedPort;
+ /**
+ * This 8080 is the default port used by spring if this parameter is not
+ * specified in application.properties.
+ */
+ @Value("${server.port:8080}")
+ private String springServerPort;
+ @Value("${server.ssl.key-store:none}")
+ private String sslKeystoreFile;
+
+ @Autowired
+ private Environment env;
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(Application.class);
+ }
+
+ public static void main(String[] args) {
+ // Start the Spring application
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * This method is used to declare the camel servlet.
+ *
+ * @return A servlet bean
+ * @throws IOException IO Exception
+ */
+ @Bean
+ public ServletRegistrationBean camelServletRegistrationBean() throws IOException {
+ eelfLogger.info(ResourceFileUtils.getResourceAsString("boot-message.txt") + "(v"
+ + ClampVersioning.getCldsVersionFromProps() + ")" + System.getProperty("line.separator")
+ + getSslExpirationDate());
+ ServletRegistrationBean registration = new ServletRegistrationBean(new ClampServlet(), "/restservices/clds/*");
+ registration.setName("CamelServlet");
+ return registration;
+ }
+
+ /**
+ * This method is used by Spring to create the servlet container factory.
+ *
+ * @return The TomcatEmbeddedServletContainerFactory just created
+ */
+ @Bean
+ public ServletWebServerFactory getEmbeddedServletContainerFactory() {
+ TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
+ if (!"none".equals(httpRedirectedPort) && !"none".equals(sslKeystoreFile)) {
+ // Automatically redirect to HTTPS
+ tomcat = new TomcatEmbeddedServletContainerFactoryRedirection();
+ Connector newConnector = createRedirectConnector(Integer.parseInt(springServerPort));
+ if (newConnector != null) {
+ tomcat.addAdditionalTomcatConnectors(newConnector);
+ }
+ }
+ return tomcat;
+ }
+
+ private Connector createRedirectConnector(int redirectSecuredPort) {
+ if (redirectSecuredPort <= 0) {
+ eelfLogger.warn("HTTP port redirection to HTTPS is disabled because the HTTPS port is 0 (random port) or -1"
+ + " (Connector disabled)");
+ return null;
+ }
+ Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
+ connector.setScheme("http");
+ connector.setSecure(false);
+ connector.setPort(Integer.parseInt(httpRedirectedPort));
+ connector.setRedirectPort(redirectSecuredPort);
+ return connector;
+ }
+
+ private String getSslExpirationDate() throws IOException {
+ StringBuilder result = new StringBuilder(" :: SSL Certificates :: ");
+ try {
+ if (env.getProperty("server.ssl.key-store") != null) {
+
+ KeyStore keystore = KeyStore.getInstance(env.getProperty("server.ssl.key-store-type"));
+ String password = PassDecoder.decode(env.getProperty("server.ssl.key-store-password"),
+ env.getProperty("clamp.config.keyFile"));
+ String keyStore = env.getProperty("server.ssl.key-store");
+ InputStream is = ResourceFileUtils.getResourceAsStream(keyStore.replaceAll("classpath:", ""));
+ keystore.load(is, password.toCharArray());
+
+ Enumeration<String> aliases = keystore.aliases();
+ while (aliases.hasMoreElements()) {
+ String alias = aliases.nextElement();
+ if ("X.509".equals(keystore.getCertificate(alias).getType())) {
+ result.append("* " + alias + " expires "
+ + ((X509Certificate) keystore.getCertificate(alias)).getNotAfter()
+ + System.getProperty("line.separator"));
+ }
+ }
+ } else {
+ result.append("* NONE HAS been configured");
+ }
+ } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
+ eelfLogger.warn("SSL certificate access error ", e);
+
+ }
+ return result.toString();
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/ClampInUserAuditorAware.java b/src/main/java/org/onap/clamp/clds/ClampInUserAuditorAware.java
new file mode 100644
index 000000000..9351db23c
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/ClampInUserAuditorAware.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds;
+
+import java.util.Optional;
+import org.onap.clamp.authorization.AuthorizationController;
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ClampInUserAuditorAware implements AuditorAware<String> {
+
+ @Override
+ public Optional<String> getCurrentAuditor() {
+ return Optional.of(AuthorizationController.getPrincipalName(SecurityContextHolder.getContext()));
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/ClampServlet.java b/src/main/java/org/onap/clamp/clds/ClampServlet.java
new file mode 100644
index 000000000..8ebc7a16b
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/ClampServlet.java
@@ -0,0 +1,142 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * 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.clamp.clds;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import fj.data.Array;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.camel.component.servlet.CamelHttpTransportServlet;
+import org.onap.clamp.authorization.SecureServicePermission;
+import org.springframework.context.ApplicationContext;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+public class ClampServlet extends CamelHttpTransportServlet {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -4198841134910211542L;
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(ClampServlet.class);
+ private static final String PERM_INSTANCE = "clamp.config.security.permission.instance";
+ private static final String PERM_CL = "clamp.config.security.permission.type.cl";
+ private static final String PERM_TEMPLATE = "clamp.config.security.permission.type.template";
+ private static final String PERM_VF = "clamp.config.security.permission.type.filter.vf";
+ private static final String PERM_MANAGE = "clamp.config.security.permission.type.cl.manage";
+ private static final String PERM_TOSCA = "clamp.config.security.permission.type.tosca";
+ private static final String AUTHENTICATION_CLASS = "clamp.config.security.authentication.class";
+ private static final String READ = "read";
+ private static final String UPDATE = "update";
+
+ private static List<SecureServicePermission> permissionList;
+
+ private synchronized List<String> loadDynamicAuthenticationClasses() {
+ return Arrays.stream(WebApplicationContextUtils.getWebApplicationContext(getServletContext())
+ .getEnvironment().getProperty(AUTHENTICATION_CLASS).split(",")).map(className -> className.trim())
+ .collect(Collectors.toList());
+ }
+
+ private synchronized List<SecureServicePermission> getPermissionList() {
+ if (permissionList == null) {
+ permissionList = new ArrayList<>();
+ ApplicationContext applicationContext = WebApplicationContextUtils
+ .getWebApplicationContext(getServletContext());
+ String cldsPermissionInstance = applicationContext.getEnvironment().getProperty(PERM_INSTANCE);
+ permissionList.add(SecureServicePermission.create(applicationContext.getEnvironment().getProperty(PERM_CL),
+ cldsPermissionInstance, READ));
+ permissionList.add(SecureServicePermission.create(applicationContext.getEnvironment().getProperty(PERM_CL),
+ cldsPermissionInstance, UPDATE));
+ permissionList.add(SecureServicePermission.create(
+ applicationContext.getEnvironment().getProperty(PERM_TEMPLATE), cldsPermissionInstance, READ));
+ permissionList.add(SecureServicePermission.create(
+ applicationContext.getEnvironment().getProperty(PERM_TEMPLATE), cldsPermissionInstance, UPDATE));
+ permissionList.add(SecureServicePermission.create(applicationContext.getEnvironment().getProperty(PERM_VF),
+ cldsPermissionInstance, "*"));
+ permissionList.add(SecureServicePermission
+ .create(applicationContext.getEnvironment().getProperty(PERM_MANAGE), cldsPermissionInstance, "*"));
+ permissionList.add(SecureServicePermission
+ .create(applicationContext.getEnvironment().getProperty(PERM_TOSCA), cldsPermissionInstance, READ));
+ permissionList.add(SecureServicePermission
+ .create(applicationContext.getEnvironment().getProperty(PERM_TOSCA),
+ cldsPermissionInstance, UPDATE));
+ }
+ return permissionList;
+ }
+
+ /**
+ * When AAF is enabled, request object will contain a cadi Wrapper, so queries
+ * to isUserInRole will invoke a http call to AAF server.
+ */
+ @Override
+ protected void doService(HttpServletRequest request, HttpServletResponse response) {
+ Principal principal = request.getUserPrincipal();
+ if (principal != null && loadDynamicAuthenticationClasses().stream()
+ .anyMatch(className -> className.equals(principal.getClass().getName()))) {
+ // When AAF is enabled, there is a need to provision the permissions to Spring
+ // system
+ List<GrantedAuthority> grantedAuths = new ArrayList<>();
+ for (SecureServicePermission perm : getPermissionList()) {
+ String permString = perm.toString();
+ if (request.isUserInRole(permString)) {
+ grantedAuths.add(new SimpleGrantedAuthority(permString));
+ }
+ }
+ Authentication auth = new UsernamePasswordAuthenticationToken(new User(principal.getName(), "",
+ grantedAuths), "", grantedAuths);
+ SecurityContextHolder.getContext().setAuthentication(auth);
+ }
+ try {
+ super.doService(request, response);
+ } catch (ServletException | IOException ioe) {
+ logger.error("Exception caught when executing doService in servlet", ioe);
+ try {
+ response.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ } catch (IOException e) {
+ logger.error("Exception caught when executing HTTP sendError in servlet", e);
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java b/src/main/java/org/onap/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java
new file mode 100644
index 000000000..a0109a688
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds;
+
+import org.apache.catalina.Context;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+
+/**
+ * This class is a factory that redirects by default all HTTP to HTTPS
+ * connector. It is used by the Application.java class and defined in a Spring
+ * Bean.
+ * In order to do this, the method postProcessContext has been overridden to
+ * provide another behavior.
+ */
+public class TomcatEmbeddedServletContainerFactoryRedirection extends TomcatServletWebServerFactory {
+
+ /**
+ * This method is there to force the automatic redirection of all calls done
+ * on the tomcat server to a Secure connection.
+ */
+ @Override
+ protected void postProcessContext(Context context) {
+ SecurityConstraint securityConstraint = new SecurityConstraint();
+ securityConstraint.setUserConstraint("CONFIDENTIAL");
+ SecurityCollection collection = new SecurityCollection();
+ collection.addPattern("/*");
+ securityConstraint.addCollection(collection);
+ context.addConstraint(securityConstraint);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/client/CdsServices.java b/src/main/java/org/onap/clamp/clds/client/CdsServices.java
new file mode 100644
index 000000000..fd3b3539a
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/client/CdsServices.java
@@ -0,0 +1,229 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * 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.clamp.clds.client;
+
+import static java.lang.Boolean.parseBoolean;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import java.util.Date;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.onap.clamp.clds.exception.cds.CdsParametersException;
+import org.onap.clamp.clds.model.cds.CdsBpWorkFlowListResponse;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.clds.util.LoggingUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class implements the communication with CDS for the service inventory.
+ */
+@Component
+public class CdsServices {
+
+ @Autowired
+ CamelContext camelContext;
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(CdsServices.class);
+
+ private static final String TYPE = "type";
+ private static final String PROPERTIES = "properties";
+ private static final String LIST = "list";
+
+ /**
+ * Constructor.
+ */
+ @Autowired
+ public CdsServices() {
+ }
+
+
+ /**
+ * Query CDS to get blueprint's workflow list.
+ *
+ * @param blueprintName CDS blueprint name
+ * @param blueprintVersion CDS blueprint version
+ * @return CdsBpWorkFlowListResponse CDS blueprint's workflow list
+ */
+ public CdsBpWorkFlowListResponse getBlueprintWorkflowList(String blueprintName, String blueprintVersion) {
+ LoggingUtils.setTargetContext("CDS", "getBlueprintWorkflowList");
+
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext)
+ .withProperty("blueprintName", blueprintName).withProperty("blueprintVersion", blueprintVersion)
+ .build();
+
+ Exchange exchangeResponse = camelContext.createProducerTemplate()
+ .send("direct:get-blueprint-workflow-list", myCamelExchange);
+
+ if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) {
+ String cdsResponse = (String) exchangeResponse.getIn().getBody();
+ logger.info("getBlueprintWorkflowList, response from CDS:" + cdsResponse);
+ LoggingUtils.setResponseContext("0", "Get Blueprint workflow list", this.getClass().getName());
+ Date startTime = new Date();
+ LoggingUtils.setTimeContext(startTime, new Date());
+ return JsonUtils.GSON_JPA_MODEL.fromJson(cdsResponse, CdsBpWorkFlowListResponse.class);
+ } else {
+ logger.error("CDS getBlueprintWorkflowList FAILED");
+ return null;
+ }
+
+ }
+
+ /**
+ * Query CDS to get input properties of workflow.
+ *
+ * @param blueprintName CDS blueprint name
+ * @param blueprintVersion CDS blueprint name
+ * @param workflow CDS blueprint's workflow
+ * @return input properties in json format
+ */
+ public JsonObject getWorkflowInputProperties(String blueprintName, String blueprintVersion,
+ String workflow) {
+ LoggingUtils.setTargetContext("CDS", "getWorkflowInputProperties");
+
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext)
+ .withBody(getCdsPayloadForWorkFlow(blueprintName, blueprintVersion, workflow))
+ .build();
+
+ Exchange exchangeResponse = camelContext.createProducerTemplate()
+ .send("direct:get-blueprint-workflow-input-properties", myCamelExchange);
+
+ if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) {
+ String cdsResponse = (String) exchangeResponse.getIn().getBody();
+ logger.info("getWorkflowInputProperties, response from CDS:" + cdsResponse);
+ LoggingUtils.setResponseContext("0", "Get Blueprint workflow input properties", this.getClass().getName());
+ Date startTime = new Date();
+ LoggingUtils.setTimeContext(startTime, new Date());
+ return parseCdsResponse(cdsResponse);
+ } else {
+ logger.error("CDS getWorkflowInputProperties FAILED");
+ return null;
+ }
+ }
+
+ protected JsonObject parseCdsResponse(String response) {
+ JsonObject root = JsonParser.parseString(response).getAsJsonObject();
+ JsonObject inputs = root.getAsJsonObject("workFlowData").getAsJsonObject("inputs");
+ JsonObject dataTypes = root.getAsJsonObject("dataTypes");
+
+ JsonObject workFlowProperties = new JsonObject();
+ workFlowProperties.add("inputs", getInputProperties(inputs, dataTypes, new JsonObject()));
+ return workFlowProperties;
+ }
+
+ private JsonObject getInputProperties(JsonObject inputs, JsonObject dataTypes,
+ JsonObject inputObject) {
+ if (inputs == null) {
+ return inputObject;
+ }
+
+ for (Map.Entry<String, JsonElement> entry : inputs.entrySet()) {
+ String key = entry.getKey();
+ JsonObject inputProperty = inputs.getAsJsonObject(key);
+ String type = inputProperty.get(TYPE).getAsString();
+ if (isComplexType(type, dataTypes)) {
+ inputObject.add(key, handleComplexType(type, dataTypes));
+ } else if (LIST.equalsIgnoreCase(type)) {
+ handleListType(key, inputProperty, dataTypes, inputObject);
+ } else if (isInputParam(inputProperty)) {
+ inputObject.add(key, entry.getValue());
+ }
+ }
+ return inputObject;
+ }
+
+ private void handleListType(String propertyName,
+ JsonObject inputProperty,
+ JsonObject dataTypes,
+ JsonObject inputObject) {
+ if (inputProperty.get("entry_schema") == null) {
+ throw new CdsParametersException("Entry schema is null for " + propertyName);
+ }
+
+ String type = inputProperty.get("entry_schema").getAsJsonObject().get(
+ TYPE).getAsString();
+ if (dataTypes.get(type) != null) {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty(TYPE, LIST);
+ jsonObject.add(PROPERTIES, getPropertiesObject(type, dataTypes));
+ inputObject.add(propertyName, jsonObject);
+ } else if (isInputParam(inputProperty)) {
+ inputObject.add(propertyName, inputProperty);
+ }
+ }
+
+ private JsonObject handleComplexType(String key, JsonObject dataTypes) {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty(TYPE, "object");
+ jsonObject.add(PROPERTIES, getPropertiesObject(key, dataTypes));
+ return jsonObject;
+ }
+
+ private JsonObject getPropertiesObject(String key, JsonObject dataTypes) {
+ JsonObject properties = dataTypes.get(key).getAsJsonObject().get(PROPERTIES).getAsJsonObject();
+ JsonObject object = new JsonObject();
+ getInputProperties(properties, dataTypes, object);
+ return object;
+ }
+
+ private boolean isComplexType(String type, JsonObject dataTypes) {
+ if (dataTypes == null) {
+ return false;
+ }
+ return dataTypes.get(type) != null;
+ }
+
+ private boolean isInputParam(JsonObject inputProperty) {
+ JsonElement inputParam = inputProperty.get("input-param");
+ if (inputParam == null) {
+ return false;
+ }
+ return parseBoolean(inputParam.getAsString());
+ }
+
+ /**
+ * Creates payload to query CDS to get workflow input properties.
+ *
+ * @param blueprintName CDS blueprint name
+ * @param version CDS blueprint version
+ * @param workflow CDS blueprint workflow
+ * @return returns payload in json format
+ */
+ public String getCdsPayloadForWorkFlow(String blueprintName, String version, String workflow) {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty("blueprintName", blueprintName);
+ jsonObject.addProperty("version", version);
+ jsonObject.addProperty("returnContent", "json");
+ jsonObject.addProperty("workflowName", workflow);
+ jsonObject.addProperty("specType", "TOSCA");
+ return jsonObject.toString();
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/client/DcaeInventoryServices.java b/src/main/java/org/onap/clamp/clds/client/DcaeInventoryServices.java
new file mode 100644
index 000000000..b24bc99b2
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/client/DcaeInventoryServices.java
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.client;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.io.IOException;
+import java.util.Date;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.clds.model.dcae.DcaeInventoryResponse;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.clds.util.LoggingUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class implements the communication with DCAE for the service inventory.
+ */
+@Component
+public class DcaeInventoryServices {
+
+ @Autowired
+ CamelContext camelContext;
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(DcaeInventoryServices.class);
+ protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
+ public static final String DCAE_INVENTORY_URL = "dcae.inventory.url";
+ public static final String DCAE_INVENTORY_RETRY_INTERVAL = "dcae.intentory.retry.interval";
+ public static final String DCAE_INVENTORY_RETRY_LIMIT = "dcae.intentory.retry.limit";
+ private final ClampProperties refProp;
+
+ /**
+ * Constructor.
+ */
+ @Autowired
+ public DcaeInventoryServices(ClampProperties refProp) {
+ this.refProp = refProp;
+ }
+
+ private int getTotalCountFromDcaeInventoryResponse(String responseStr) throws ParseException {
+ JSONParser parser = new JSONParser();
+ Object obj0 = parser.parse(responseStr);
+ JSONObject jsonObj = (JSONObject) obj0;
+ Long totalCount = (Long) jsonObj.get("totalCount");
+ return totalCount.intValue();
+ }
+
+ private DcaeInventoryResponse getItemsFromDcaeInventoryResponse(String responseStr) throws ParseException {
+ JSONParser parser = new JSONParser();
+ Object obj0 = parser.parse(responseStr);
+ JSONObject jsonObj = (JSONObject) obj0;
+ JSONArray itemsArray = (JSONArray) jsonObj.get("items");
+ JSONObject dcaeServiceType0 = (JSONObject) itemsArray.get(0);
+ return JsonUtils.GSON.fromJson(dcaeServiceType0.toString(), DcaeInventoryResponse.class);
+ }
+
+ /**
+ * DO a query to DCAE to get some Information.
+ *
+ * @param artifactName The artifact Name
+ * @param serviceUuid The service UUID
+ * @param resourceUuid The resource UUID
+ * @return The DCAE inventory for the artifact in DcaeInventoryResponse
+ * @throws IOException In case of issues with the stream
+ * @throws ParseException In case of issues with the Json parsing
+ */
+ public DcaeInventoryResponse getDcaeInformation(String artifactName, String serviceUuid, String resourceUuid)
+ throws IOException, ParseException, InterruptedException {
+ LoggingUtils.setTargetContext("DCAE", "getDcaeInformation");
+
+ int retryInterval = 0;
+ int retryLimit = 1;
+ if (refProp.getStringValue(DCAE_INVENTORY_RETRY_LIMIT) != null) {
+ retryLimit = Integer.valueOf(refProp.getStringValue(DCAE_INVENTORY_RETRY_LIMIT));
+ }
+ if (refProp.getStringValue(DCAE_INVENTORY_RETRY_INTERVAL) != null) {
+ retryInterval = Integer.valueOf(refProp.getStringValue(DCAE_INVENTORY_RETRY_INTERVAL));
+ }
+ for (int i = 0; i < retryLimit; i++) {
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext)
+ .withProperty("blueprintResourceId", resourceUuid).withProperty("blueprintServiceId", serviceUuid)
+ .withProperty("blueprintName", artifactName).build();
+ metricsLogger.info("Attempt n°" + i + " to contact DCAE inventory");
+
+ Exchange exchangeResponse = camelContext.createProducerTemplate()
+ .send("direct:get-dcae-blueprint-inventory", myCamelExchange);
+
+ if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) {
+ String dcaeResponse = (String) exchangeResponse.getIn().getBody();
+ int totalCount = getTotalCountFromDcaeInventoryResponse(dcaeResponse);
+ metricsLogger.info("getDcaeInformation complete: totalCount returned=" + totalCount);
+ if (totalCount > 0) {
+ logger.info("getDcaeInformation, answer from DCAE inventory:" + dcaeResponse);
+ LoggingUtils.setResponseContext("0", "Get Dcae Information success", this.getClass().getName());
+ Date startTime = new Date();
+ LoggingUtils.setTimeContext(startTime, new Date());
+ return getItemsFromDcaeInventoryResponse(dcaeResponse);
+ } else {
+ logger.info("Dcae inventory totalCount returned is 0, so waiting " + retryInterval
+ + "ms before retrying ...");
+ // wait for a while and try to connect to DCAE again
+ Thread.sleep(retryInterval);
+ }
+ }
+ }
+ logger.warn("Dcae inventory totalCount returned is still 0, after " + retryLimit + " attempts, returning NULL");
+ return null;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/client/PolicyEngineServices.java b/src/main/java/org/onap/clamp/clds/client/PolicyEngineServices.java
new file mode 100644
index 000000000..c75d733a8
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/client/PolicyEngineServices.java
@@ -0,0 +1,227 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.client;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.clds.sdc.controller.installer.BlueprintMicroService;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.loop.template.PolicyModel;
+import org.onap.clamp.loop.template.PolicyModelId;
+import org.onap.clamp.loop.template.PolicyModelsService;
+import org.onap.clamp.policy.pdpgroup.PdpGroup;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.Yaml;
+
+
+/**
+ * The class implements the communication with the Policy Engine to retrieve
+ * policy models (tosca). It mainly delegates the physical calls to Camel
+ * engine.
+ */
+@Component
+public class PolicyEngineServices {
+ private final CamelContext camelContext;
+
+ private final PolicyModelsService policyModelsService;
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyEngineServices.class);
+ private static int retryInterval = 0;
+ private static int retryLimit = 1;
+
+ public static final String POLICY_RETRY_INTERVAL = "policy.retry.interval";
+ public static final String POLICY_RETRY_LIMIT = "policy.retry.limit";
+
+ /**
+ * Default constructor.
+ *
+ * @param camelContext Camel context bean
+ * @param clampProperties ClampProperties bean
+ * @param policyModelsService policyModel service
+ */
+ @Autowired
+ public PolicyEngineServices(CamelContext camelContext, ClampProperties clampProperties,
+ PolicyModelsService policyModelsService) {
+ this.camelContext = camelContext;
+ this.policyModelsService = policyModelsService;
+ if (clampProperties.getStringValue(POLICY_RETRY_LIMIT) != null) {
+ retryLimit = Integer.parseInt(clampProperties.getStringValue(POLICY_RETRY_LIMIT));
+ }
+ if (clampProperties.getStringValue(POLICY_RETRY_INTERVAL) != null) {
+ retryInterval = Integer.parseInt(clampProperties.getStringValue(POLICY_RETRY_INTERVAL));
+ }
+ }
+
+ /**
+ * This method query Policy engine and create a PolicyModel object with type and version.
+ * If the policy already exist in the db it returns the existing one.
+ *
+ * @param policyType The policyType id
+ * @param policyVersion The policy version of that type
+ * @return A PolicyModel created from policyEngine data or null if nothing is found on policyEngine
+ */
+ public PolicyModel createPolicyModelFromPolicyEngine(String policyType, String policyVersion) {
+ PolicyModel policyModelFound = policyModelsService.getPolicyModel(policyType, policyVersion);
+ if (policyModelFound == null) {
+ String policyTosca = this.downloadOnePolicy(policyType, policyVersion);
+ if (policyTosca != null && !policyTosca.isEmpty()) {
+ return policyModelsService.savePolicyModelInNewTransaction(
+ new PolicyModel(policyType, policyTosca, policyVersion));
+ } else {
+ logger.error("Policy not found in the Policy Engine, returning null: " + policyType
+ + "/" + policyVersion);
+ return null;
+ }
+ } else {
+ logger.info("Skipping policy model download as it exists already in the database " + policyType
+ + "/" + policyVersion);
+ return policyModelFound;
+ }
+ }
+
+ /**
+ * This method query Policy engine and create a PolicyModel object with type and version.
+ *
+ * @param microService microservice object instance
+ * @return A PolicyModel created from policyEngine data
+ */
+ public PolicyModel createPolicyModelFromPolicyEngine(BlueprintMicroService microService) {
+ return createPolicyModelFromPolicyEngine(microService.getModelType(), microService.getModelVersion());
+ }
+
+ /**
+ * This method synchronize the clamp database and the policy engine.
+ * So it creates the required PolicyModel.
+ */
+ public void synchronizeAllPolicies() {
+ LinkedHashMap<String, Object> loadedYaml;
+ loadedYaml = new Yaml().load(downloadAllPolicies());
+ if (loadedYaml == null || loadedYaml.isEmpty()) {
+ logger.warn("getAllPolicyType yaml returned by policy engine could not be decoded, as it's null or empty");
+ return;
+ }
+
+ LinkedHashMap<String, Object> policyTypesMap = (LinkedHashMap<String, Object>) loadedYaml
+ .get("policy_types");
+ policyTypesMap.forEach((key, value) ->
+ this.createPolicyModelFromPolicyEngine(key,
+ ((String) ((LinkedHashMap<String, Object>) value).get("version"))));
+ }
+
+ /**
+ * This method can be used to download all policy types + data types defined in
+ * policy engine.
+ *
+ * @return A yaml containing all policy Types and all data types
+ */
+ public String downloadAllPolicies() {
+ return callCamelRoute(ExchangeBuilder.anExchange(camelContext).build(), "direct:get-all-policy-models",
+ "Get all policies");
+ }
+
+ /**
+ * This method can be used to download a policy tosca model on the engine.
+ *
+ * @param policyType The policy type (id)
+ * @param policyVersion The policy version
+ * @return A string with the whole policy tosca model
+ */
+ public String downloadOnePolicy(String policyType, String policyVersion) {
+ logger.info("Downloading the policy model " + policyType + "/" + policyVersion);
+ DumperOptions options = new DumperOptions();
+ options.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
+ options.setIndent(4);
+ options.setPrettyFlow(true);
+ options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+ Yaml yamlParser = new Yaml(options);
+ String responseBody = callCamelRoute(
+ ExchangeBuilder.anExchange(camelContext).withProperty("policyModelName", policyType)
+ .withProperty("policyModelVersion", policyVersion).build(), "direct:get-policy-model",
+ "Get one policy");
+
+ if (responseBody == null || responseBody.isEmpty()) {
+ logger.warn("getPolicyModel returned by policy engine could not be decoded, as it's null or empty");
+ return null;
+ }
+
+ return yamlParser.dump((Map<String, Object>) yamlParser.load(responseBody));
+ }
+
+ /**
+ * This method can be used to download all Pdp Groups data from policy engine.
+ */
+ public void downloadPdpGroups() {
+ String responseBody =
+ callCamelRoute(ExchangeBuilder.anExchange(camelContext).build(), "direct:get-all-pdp-groups",
+ "Get Pdp Groups");
+
+ if (responseBody == null || responseBody.isEmpty()) {
+ logger.warn("getPdpGroups returned by policy engine could not be decoded, as it's null or empty");
+ return;
+ }
+
+ JsonObject jsonObj = JsonUtils.GSON.fromJson(responseBody, JsonObject.class);
+
+ List<PdpGroup> pdpGroupList = new LinkedList<>();
+ JsonArray itemsArray = (JsonArray) jsonObj.get("groups");
+
+ for (com.google.gson.JsonElement jsonElement : itemsArray) {
+ JsonObject item = (JsonObject) jsonElement;
+ PdpGroup pdpGroup = JsonUtils.GSON.fromJson(item.toString(), PdpGroup.class);
+ pdpGroupList.add(pdpGroup);
+ }
+
+ policyModelsService.updatePdpGroupInfo(pdpGroupList);
+ }
+
+ private String callCamelRoute(Exchange exchange, String camelFlow, String logMsg) {
+ for (int i = 0; i < retryLimit; i++) {
+ Exchange exchangeResponse = camelContext.createProducerTemplate().send(camelFlow, exchange);
+ if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) {
+ return (String) exchangeResponse.getIn().getBody();
+ } else {
+ logger.info(logMsg + " query " + retryInterval + "ms before retrying ...");
+ // wait for a while and try to connect to DCAE again
+ try {
+ Thread.sleep(retryInterval);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ return "";
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/config/AafConfiguration.java b/src/main/java/org/onap/clamp/clds/config/AafConfiguration.java
new file mode 100644
index 000000000..d9178cb9a
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/AafConfiguration.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.config;
+
+import javax.servlet.Filter;
+
+import org.onap.clamp.clds.filter.ClampCadiFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+@Profile("clamp-aaf-authentication")
+public class AafConfiguration {
+
+ /**
+ * Method to return clamp cadi filter.
+ *
+ * @return Filter
+ */
+ @Bean(name = "cadiFilter")
+ public Filter cadiFilter() {
+ return new ClampCadiFilter();
+ }
+
+ /**
+ * Method to register cadi filter.
+ *
+ * @return FilterRegistrationBean
+ */
+ @Bean
+ public FilterRegistrationBean cadiFilterRegistration() {
+ FilterRegistrationBean registration = new FilterRegistrationBean();
+ registration.setFilter(cadiFilter());
+ registration.addUrlPatterns("/restservices/clds/v1/user/*");
+ registration.addUrlPatterns("/restservices/clds/v2/dictionary/*");
+ registration.addUrlPatterns("/restservices/clds/v2/templates/*");
+ registration.addUrlPatterns("/restservices/clds/v2/clampInformation/*");
+ registration.addUrlPatterns("/restservices/clds/v2/policyToscaModels/*");
+ registration.addUrlPatterns("/restservices/clds/v2/loop/*");
+ registration.setName("cadiFilter");
+ registration.setOrder(0);
+ return registration;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/config/CamelConfiguration.java b/src/main/java/org/onap/clamp/clds/config/CamelConfiguration.java
new file mode 100644
index 000000000..36e11f64f
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/CamelConfiguration.java
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.config;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.http4.HttpClientConfigurer;
+import org.apache.camel.component.http4.HttpComponent;
+import org.apache.camel.model.rest.RestBindingMode;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
+import org.onap.clamp.clds.util.ClampVersioning;
+import org.onap.clamp.clds.util.ResourceFileUtils;
+import org.onap.clamp.util.PassDecoder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CamelConfiguration extends RouteBuilder {
+
+ @Autowired
+ CamelContext camelContext;
+
+ @Autowired
+ private Environment env;
+
+ private void configureDefaultSslProperties() throws IOException {
+ if (env.getProperty("server.ssl.trust-store") != null) {
+ URL storeResource = Thread.currentThread().getContextClassLoader()
+ .getResource(env.getProperty("server.ssl.trust-store").replaceFirst("classpath:", ""));
+ System.setProperty("javax.net.ssl.trustStore", storeResource.getPath());
+ String keyFile = env.getProperty("clamp.config.keyFile");
+ String trustStorePass = PassDecoder.decode(env.getProperty("server.ssl.trust-store-password"),
+ keyFile);
+ System.setProperty("javax.net.ssl.trustStorePassword", trustStorePass);
+ System.setProperty("javax.net.ssl.trustStoreType", "jks");
+ System.setProperty("ssl.TrustManagerFactory.algorithm", "PKIX");
+ storeResource = Thread.currentThread().getContextClassLoader()
+ .getResource(env.getProperty("server.ssl.key-store").replaceFirst("classpath:", ""));
+ System.setProperty("javax.net.ssl.keyStore", storeResource.getPath());
+
+ String keyStorePass = PassDecoder.decode(env.getProperty("server.ssl.key-store-password"),
+ keyFile);
+ System.setProperty("javax.net.ssl.keyStorePassword", keyStorePass);
+ System.setProperty("javax.net.ssl.keyStoreType", env.getProperty("server.ssl.key-store-type"));
+ }
+ }
+
+ private void registerTrustStore()
+ throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, CertificateException, IOException {
+ if (env.getProperty("server.ssl.trust-store") != null) {
+ KeyStore truststore = KeyStore.getInstance("JKS");
+ String keyFile = env.getProperty("clamp.config.keyFile");
+ String password = PassDecoder.decode(env.getProperty("server.ssl.trust-store-password"), keyFile);
+ truststore.load(
+ ResourceFileUtils.getResourceAsStream(env.getProperty("server.ssl.trust-store")),
+ password.toCharArray());
+
+ TrustManagerFactory trustFactory = TrustManagerFactory.getInstance("PKIX");
+ trustFactory.init(truststore);
+ SSLContext sslcontext = SSLContext.getInstance("TLS");
+ sslcontext.init(null, trustFactory.getTrustManagers(), null);
+ SSLSocketFactory factory = new SSLSocketFactory(sslcontext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+ SchemeRegistry registry = new SchemeRegistry();
+ final Scheme scheme = new Scheme("https4", 443, factory);
+ registry.register(scheme);
+ ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
+ HttpComponent http4 = camelContext.getComponent("https4", HttpComponent.class);
+ http4.setHttpClientConfigurer(new HttpClientConfigurer() {
+
+ @Override
+ public void configureHttpClient(HttpClientBuilder builder) {
+ builder.setSSLSocketFactory(factory);
+ Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+ .register("https", factory).register("http", plainsf).build();
+ builder.setConnectionManager(new BasicHttpClientConnectionManager(registry));
+ }
+ });
+ }
+ }
+
+ @Override
+ public void configure()
+ throws KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
+ restConfiguration().component("servlet").bindingMode(RestBindingMode.json).jsonDataFormat("clamp-gson")
+ .dataFormatProperty("prettyPrint", "true")// .enableCORS(true)
+ // turn on swagger api-doc
+ .apiContextPath("api-doc").apiVendorExtension(true).apiProperty("api.title", "Clamp Rest API")
+ .apiProperty("api.version", ClampVersioning.getCldsVersionFromProps())
+ .apiProperty("base.path", "/restservices/clds/");
+
+ // camelContext.setTracing(true);
+
+ configureDefaultSslProperties();
+ registerTrustStore();
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/config/ClampProperties.java b/src/main/java/org/onap/clamp/clds/config/ClampProperties.java
new file mode 100644
index 000000000..0b5c951bf
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/ClampProperties.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.config;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+/**
+ * Holds Clamp properties and add some functionalities.
+ */
+@Component
+public class ClampProperties {
+
+ @Autowired
+ private ApplicationContext appContext;
+ @Autowired
+ private Environment env;
+ public static final String CONFIG_PREFIX = "clamp.config.";
+
+ /**
+ * get property value.
+ *
+ * @param key The first key
+ * @return The string with the value
+ */
+ public String getStringValue(String key) {
+ return env.getProperty(CONFIG_PREFIX + key);
+ }
+
+ /**
+ * get property value for a combo key (key1 + "." + key2). If not found just use
+ * key1.
+ *
+ * @param key1 The first key
+ * @param key2 The second key after a dot
+ * @return The string with the value
+ */
+ public String getStringValue(String key1, String key2) {
+ String value = getStringValue(key1 + "." + key2);
+ if (value == null || value.length() == 0) {
+ value = getStringValue(key1);
+ }
+ return value;
+ }
+
+ /**
+ * Return the file content. The value obtained from the clds-reference file will
+ * be used as a filename.
+ *
+ * @param key The key that will be used to access the clds-reference file
+ * @return File content in String
+ * @throws IOException In case of issues with the JSON parser
+ */
+ public String getFileContent(String key) throws IOException {
+ String fileReference = getStringValue(key);
+ return (fileReference != null) ? getFileContentFromPath(fileReference) : null;
+ }
+
+ /**
+ * Return the file content. First try with combo key (key1 + "." + key2),
+ * otherwise default to just key1. The value obtained from the clds-reference
+ * file will be used as a filename.
+ *
+ * @param key1 The first key
+ * @param key2 The second key after a dot
+ * @return File content in String
+ * @throws IOException In case of issues with the JSON parser
+ */
+ public String getFileContent(String key1, String key2) throws IOException {
+ String fileReference = getStringValue(key1, key2);
+ return (fileReference != null) ? getFileContentFromPath(fileReference) : null;
+ }
+
+ private String getFileContentFromPath(String filepath) throws IOException {
+ URL url = appContext.getResource(filepath).getURL();
+ return IOUtils.toString(url, StandardCharsets.UTF_8);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java b/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java
new file mode 100644
index 000000000..a7ef10738
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * 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.clamp.clds.config;
+
+import com.google.gson.JsonParseException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import org.apache.commons.io.IOUtils;
+import org.onap.clamp.authorization.CldsUser;
+import org.onap.clamp.clds.exception.CldsUsersException;
+import org.onap.clamp.clds.util.JsonUtils;
+
+public class CldsUserJsonDecoder {
+
+ private CldsUserJsonDecoder() {
+ }
+
+ /**
+ * This method decodes the JSON file provided to a CldsUser Array. The stream is
+ * closed after this call, this is not possible to reuse it.
+ *
+ * @param cldsUsersFile
+ * The inputStream containing the users json file
+ * @return CldsUser[] Array containing a list of the user defined in the JSON
+ * file
+ */
+ public static CldsUser[] decodeJson(InputStream cldsUsersFile) {
+ try {
+ return decodeJson(IOUtils.toString(cldsUsersFile, StandardCharsets.UTF_8.name()));
+ } catch (IOException e) {
+ throw new CldsUsersException("Exception occurred during the decoding of the clds-users.json", e);
+ }
+ }
+
+ /**
+ * This method decodes the JSON string to a CldsUser Array.
+ *
+ * @param cldsUsersString JSON string
+ * @return CldsUser[] Array containing a list of the user defined in the JSON
+ */
+ public static CldsUser[] decodeJson(String cldsUsersString) {
+ try {
+ // the ObjectMapper readValue method closes the stream no need to do
+ // it
+ return JsonUtils.GSON.fromJson(cldsUsersString, CldsUser[].class);
+ } catch (JsonParseException e) {
+ throw new CldsUsersException("Exception occurred during the decoding of the clds-users.json", e);
+ }
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/config/DefaultDictionaryElements.java b/src/main/java/org/onap/clamp/clds/config/DefaultDictionaryElements.java
new file mode 100644
index 000000000..1c52e4100
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/DefaultDictionaryElements.java
@@ -0,0 +1,167 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.config;
+
+import javax.annotation.PostConstruct;
+import org.onap.clamp.tosca.Dictionary;
+import org.onap.clamp.tosca.DictionaryElement;
+import org.onap.clamp.tosca.DictionaryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+@Profile("default-dictionary-elements")
+public class DefaultDictionaryElements {
+
+ @Autowired
+ private DictionaryService dictionaryService;
+
+ /**
+ * Init method.
+ */
+ @PostConstruct
+ public void init() {
+ preProvisionDefaultActors();
+ preProvisionDefaultOperations();
+ }
+
+ private void preProvisionDefaultActors() {
+ // Set up dictionary elements
+ Dictionary actorDictionary = new Dictionary();
+ actorDictionary.setName("DefaultActors");
+ actorDictionary.setSecondLevelDictionary(0);
+ actorDictionary.setSubDictionaryType("");
+
+ DictionaryElement elementSo = new DictionaryElement();
+ elementSo.setName("SO");
+ elementSo.setShortName("SO");
+ elementSo.setType("string");
+ elementSo.setDescription("SO component");
+ actorDictionary.addDictionaryElements(elementSo);
+
+ DictionaryElement elementSdnc = new DictionaryElement();
+ elementSdnc.setName("SDNC");
+ elementSdnc.setShortName("SDNC");
+ elementSdnc.setType("string");
+ elementSdnc.setDescription("SDNC component");
+ actorDictionary.addDictionaryElements(elementSdnc);
+
+ DictionaryElement elementAppc = new DictionaryElement();
+ elementAppc.setName("APPC");
+ elementAppc.setShortName("APPC");
+ elementAppc.setType("string");
+ elementAppc.setDescription("APPC component");
+ actorDictionary.addDictionaryElements(elementAppc);
+
+ DictionaryElement elementVfc = new DictionaryElement();
+ elementVfc.setName("VFC");
+ elementVfc.setShortName("VFC");
+ elementVfc.setType("string");
+ elementVfc.setDescription("VFC component");
+ actorDictionary.addDictionaryElements(elementVfc);
+
+ DictionaryElement elementSdnr = new DictionaryElement();
+ elementSdnr.setName("SDNR");
+ elementSdnr.setShortName("SDNR");
+ elementSdnr.setType("string");
+ elementSdnr.setDescription("SDNR component");
+ actorDictionary.addDictionaryElements(elementSdnr);
+
+ dictionaryService.saveOrUpdateDictionary(actorDictionary);
+ }
+
+ private void preProvisionDefaultOperations() {
+ // Set up dictionary elements
+ Dictionary operationDictionary = new Dictionary();
+ operationDictionary.setName("DefaultOperations");
+ operationDictionary.setSecondLevelDictionary(0);
+ operationDictionary.setSubDictionaryType("");
+
+ DictionaryElement elementRestart = new DictionaryElement();
+ elementRestart.setName("Restart");
+ elementRestart.setShortName("Restart (APPC operation)");
+ elementRestart.setType("string");
+ elementRestart.setDescription("APPC operation");
+ operationDictionary.addDictionaryElements(elementRestart);
+
+ DictionaryElement elementRebuild = new DictionaryElement();
+ elementRebuild.setName("Rebuild");
+ elementRebuild.setShortName("Rebuild (APPC operation)");
+ elementRebuild.setType("string");
+ elementRebuild.setDescription("APPC operation");
+ operationDictionary.addDictionaryElements(elementRebuild);
+
+ DictionaryElement elementMigrate = new DictionaryElement();
+ elementMigrate.setName("Migrate");
+ elementMigrate.setShortName("Migrate (APPC operation)");
+ elementMigrate.setType("string");
+ elementMigrate.setDescription("APPC operation");
+ operationDictionary.addDictionaryElements(elementMigrate);
+
+ DictionaryElement elementHealthCheck = new DictionaryElement();
+ elementHealthCheck.setName("Health-Check");
+ elementHealthCheck.setShortName("Health-Check (APPC operation)");
+ elementHealthCheck.setType("string");
+ elementHealthCheck.setDescription("APPC operation");
+ operationDictionary.addDictionaryElements(elementHealthCheck);
+
+ DictionaryElement elementModifyConfig = new DictionaryElement();
+ elementModifyConfig.setName("ModifyConfig");
+ elementModifyConfig.setShortName("ModifyConfig (APPC/VFC operation)");
+ elementModifyConfig.setType("string");
+ elementModifyConfig.setDescription("APPC/VFC operation");
+ operationDictionary.addDictionaryElements(elementModifyConfig);
+
+ DictionaryElement elementVfModuleCreate = new DictionaryElement();
+ elementVfModuleCreate.setName("VF Module Create");
+ elementVfModuleCreate.setShortName("VF Module Create (SO operation)");
+ elementVfModuleCreate.setType("string");
+ elementVfModuleCreate.setDescription("SO operation");
+ operationDictionary.addDictionaryElements(elementVfModuleCreate);
+
+ DictionaryElement elementVfModuleDelete = new DictionaryElement();
+ elementVfModuleDelete.setName("VF Module Delete");
+ elementVfModuleDelete.setShortName("VF Module Delete (SO operation)");
+ elementVfModuleDelete.setType("string");
+ elementVfModuleDelete.setDescription("SO operation");
+ operationDictionary.addDictionaryElements(elementVfModuleDelete);
+
+ DictionaryElement elementReroute = new DictionaryElement();
+ elementReroute.setName("Reroute");
+ elementReroute.setShortName("Reroute (SDNC operation)");
+ elementReroute.setType("string");
+ elementReroute.setDescription("SDNC operation");
+ operationDictionary.addDictionaryElements(elementReroute);
+
+ DictionaryElement elementBandwidthOnDemand = new DictionaryElement();
+ elementBandwidthOnDemand.setName("BandwidthOnDemand");
+ elementBandwidthOnDemand.setShortName("BandwidthOnDemand (SDNC operation)");
+ elementBandwidthOnDemand.setType("string");
+ elementBandwidthOnDemand.setDescription("SDNC operation");
+ operationDictionary.addDictionaryElements(elementBandwidthOnDemand);
+
+ dictionaryService.saveOrUpdateDictionary(operationDictionary);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java b/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java
new file mode 100644
index 000000000..cfd5f990f
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java
@@ -0,0 +1,138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * 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.clamp.clds.config;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import org.onap.clamp.authorization.CldsUser;
+import org.onap.clamp.clds.exception.CldsConfigException;
+import org.onap.clamp.clds.exception.CldsUsersException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+/**
+ * This class is used to enable the HTTP authentication to login. It requires a
+ * specific JSON file containing the user definition
+ * (classpath:clds/clds-users.json).
+ */
+@Configuration
+@EnableWebSecurity
+@Profile("clamp-default-user")
+public class DefaultUserConfiguration extends WebSecurityConfigurerAdapter {
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(DefaultUserConfiguration.class);
+
+ private static final String SETUP_WEB_USERS_EXCEPTION_MSG = "Exception occurred during the "
+ + " setup of the Web users in memory";
+ @Autowired
+ private ClampProperties refProp;
+ @Value("${clamp.config.security.permission.type.cl:permission-type-cl}")
+ private String cldsPersmissionTypeCl;
+ @Value("${CLDS_PERMISSION_INSTANCE:dev}")
+ private String cldsPermissionInstance;
+ @Value("${clamp.config.security.encoder:bcrypt}")
+ private String cldsEncoderMethod;
+ @Value("${clamp.config.security.encoder.bcrypt.strength:10}")
+ private Integer cldsBcryptEncoderStrength;
+
+ /**
+ * This method configures on which URL the authorization will be enabled.
+ */
+ @Override
+ protected void configure(HttpSecurity http) {
+ try {
+ http.csrf().disable().httpBasic().and().authorizeRequests().antMatchers("/restservices/clds/v1/user/**")
+ .authenticated().anyRequest().permitAll().and().sessionManagement()
+ .maximumSessions(1);
+
+ } catch (Exception e) {
+ logger.error(SETUP_WEB_USERS_EXCEPTION_MSG, e);
+ throw new CldsUsersException(SETUP_WEB_USERS_EXCEPTION_MSG, e);
+ }
+ }
+
+ /**
+ * This method is called by the framework and is used to load all the users
+ * defined in cldsUsersFile variable (this file path can be configured in the
+ * application.properties).
+ *
+ * @param auth authentication manager builder
+ */
+ @Autowired
+ public void configureGlobal(AuthenticationManagerBuilder auth) {
+ // configure algorithm used for password hashing
+ final PasswordEncoder passwordEncoder = getPasswordEncoder();
+
+ try {
+ CldsUser[] usersList = loadUsers();
+ // no users defined
+ if (null == usersList) {
+ logger.warn("No users defined. Users should be defined under clds-users.json");
+ return;
+ }
+ for (CldsUser user : usersList) {
+ auth.inMemoryAuthentication().withUser(user.getUser()).password(user.getPassword())
+ .authorities(user.getPermissionsString()).and().passwordEncoder(passwordEncoder);
+ }
+ } catch (Exception e) {
+ logger.error(SETUP_WEB_USERS_EXCEPTION_MSG, e);
+ throw new CldsUsersException(SETUP_WEB_USERS_EXCEPTION_MSG, e);
+ }
+ }
+
+ /**
+ * This method loads physically the JSON file and convert it to an Array of
+ * CldsUser.
+ *
+ * @return The array of CldsUser
+ * @throws IOException In case of the file is not found
+ */
+ private CldsUser[] loadUsers() throws IOException {
+ logger.info("Load from clds-users.properties");
+ return CldsUserJsonDecoder.decodeJson(refProp.getFileContent("files.cldsUsers"));
+ }
+
+ /**
+ * This methods returns the chosen encoder for password hashing.
+ */
+ private PasswordEncoder getPasswordEncoder() {
+ if ("bcrypt".equals(cldsEncoderMethod)) {
+ return new BCryptPasswordEncoder(cldsBcryptEncoderStrength);
+ } else {
+ throw new CldsConfigException(
+ "Invalid clamp.config.security.encoder value. 'bcrypt' is the only option at this time.");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/config/SslConfig.java b/src/main/java/org/onap/clamp/clds/config/SslConfig.java
new file mode 100644
index 000000000..6345f4b56
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/SslConfig.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.config;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import org.onap.clamp.clds.util.ResourceFileUtils;
+import org.onap.clamp.util.PassDecoder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.server.Ssl;
+import org.springframework.boot.web.server.SslStoreProvider;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.ResourceLoader;
+
+@Configuration
+@Profile("clamp-ssl-config")
+public class SslConfig {
+ @Autowired
+ private Environment env;
+
+ @Bean
+ WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer(ServerProperties serverProperties,
+ ResourceLoader resourceLoader) {
+ return (tomcat) -> tomcat.setSslStoreProvider(new SslStoreProvider() {
+ @Override
+ public KeyStore getKeyStore() throws KeyStoreException,
+ NoSuchAlgorithmException, CertificateException, IOException {
+ KeyStore keystore = KeyStore.getInstance(env.getProperty("server.ssl.key-store-type"));
+ String password = PassDecoder.decode(env.getProperty("server.ssl.key-store-password"),
+ env.getProperty("clamp.config.keyFile"));
+ keystore.load(ResourceFileUtils.getResourceAsStream(env.getProperty("server.ssl.key-store")),
+ password.toCharArray());
+ return keystore;
+ }
+
+ @Override
+ public KeyStore getTrustStore() throws KeyStoreException,
+ NoSuchAlgorithmException, CertificateException, IOException {
+ KeyStore truststore = KeyStore.getInstance("JKS");
+ String password = PassDecoder.decode(env.getProperty("server.ssl.trust-store-password"),
+ env.getProperty("clamp.config.keyFile"));
+ truststore.load(
+ ResourceFileUtils.getResourceAsStream(env.getProperty("server.ssl.trust-store")),
+ password.toCharArray());
+ return truststore;
+ }
+ });
+ }
+
+ @Bean
+ WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatSslCustomizer(ServerProperties serverProperties,
+ ResourceLoader resourceLoader) {
+ return (tomcat) -> tomcat.setSsl(new Ssl() {
+ @Override
+ public String getKeyPassword() {
+ String password = PassDecoder.decode(env.getProperty("server.ssl.key-password"),
+ env.getProperty("clamp.config.keyFile"));
+ return password;
+ }
+ });
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/config/SystemPropertiesLoader.java b/src/main/java/org/onap/clamp/clds/config/SystemPropertiesLoader.java
new file mode 100644
index 000000000..7480beb8d
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/SystemPropertiesLoader.java
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.config;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.util.Properties;
+
+import javax.annotation.Resource;
+
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SystemPropertiesLoader implements ApplicationListener<ContextRefreshedEvent> {
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(SystemPropertiesLoader.class);
+
+ @Resource(name = "mapper")
+ private Properties myTranslator;
+
+ @Override
+ public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
+ logger.info("Loading additional JVM properties:" + myTranslator.toString());
+ System.getProperties().putAll(myTranslator);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java b/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java
new file mode 100644
index 000000000..ad2751bb8
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * 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.clamp.clds.config.sdc;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
+import org.onap.clamp.clds.exception.sdc.controller.SdcParametersException;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.io.Resource;
+
+/**
+ * This class maps the SDC config JSON file. This JSON can have multiple
+ * sdc-controller config. So the json is loaded in a static way and the instance
+ * must specify the controller name that it represents.
+ */
+public class SdcControllersConfiguration {
+
+ private static final String CONTROLLER_SUBTREE_KEY = "sdc-connections";
+ @Autowired
+ protected ApplicationContext appContext;
+ /**
+ * The file name that will be loaded by Spring.
+ */
+ @Value("${clamp.config.files.sdcController:'classpath:/clds/sdc-controllers-config.json'}")
+ protected String sdcControllerFile;
+ /**
+ * The root of the JSON.
+ */
+ private JsonObject jsonRootNode;
+
+ /**
+ * Loads configuration from SDC controller config file.
+ *
+ * @throws IOException IO Exception
+ */
+ @PostConstruct
+ public void loadConfiguration() throws IOException {
+ Resource resource = appContext.getResource(sdcControllerFile);
+ // Try to load json tree
+ jsonRootNode = JsonUtils.GSON.fromJson(new InputStreamReader(
+ resource.getInputStream(), StandardCharsets.UTF_8),
+ JsonObject.class);
+ }
+
+ public SdcSingleControllerConfiguration getSdcSingleControllerConfiguration(String controllerName) {
+ return getAllDefinedControllers().get(controllerName);
+ }
+
+ /**
+ * This method reads all Controllers configurations and returns them.
+ *
+ * @return A list of controller Names defined in the config
+ */
+ public Map<String, SdcSingleControllerConfiguration> getAllDefinedControllers() {
+ Map<String, SdcSingleControllerConfiguration> result = new HashMap<>();
+ if (jsonRootNode.get(CONTROLLER_SUBTREE_KEY) != null) {
+ jsonRootNode.get(CONTROLLER_SUBTREE_KEY).getAsJsonObject().entrySet().forEach(
+ entry -> result.put(entry.getKey(),
+ new SdcSingleControllerConfiguration(entry.getValue().getAsJsonObject(), entry.getKey())));
+ } else {
+ throw new SdcParametersException(
+ CONTROLLER_SUBTREE_KEY + " key not found in the file: " + sdcControllerFile);
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java b/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java
new file mode 100644
index 000000000..da90e6060
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java
@@ -0,0 +1,290 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.config.sdc;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.codec.DecoderException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcParametersException;
+import org.onap.clamp.clds.util.CryptoUtils;
+import org.onap.sdc.api.consumer.IConfiguration;
+
+/**
+ * This class maps the SDC config JSON for one controller.
+ */
+public class SdcSingleControllerConfiguration implements IConfiguration {
+
+ private static final EELFLogger logger = EELFManager.getInstance()
+ .getLogger(SdcSingleControllerConfiguration.class);
+ /**
+ * The sdc Controller name corresponding.
+ */
+ private String sdcControllerName;
+ /**
+ * The root of the JSON.
+ */
+ private JsonObject jsonRootNode;
+ // All keys that can be present in the JSON
+ public static final String CONSUMER_GROUP_ATTRIBUTE_NAME = "consumerGroup";
+ public static final String CONSUMER_ID_ATTRIBUTE_NAME = "consumerId";
+ public static final String ENVIRONMENT_NAME_ATTRIBUTE_NAME = "environmentName";
+ public static final String SDC_KEY_ATTRIBUTE_NAME = "password";
+ public static final String POLLING_INTERVAL_ATTRIBUTE_NAME = "pollingInterval";
+ public static final String RELEVANT_ARTIFACT_TYPES_ATTRIBUTE_NAME = "relevantArtifactTypes";
+ public static final String USER_ATTRIBUTE_NAME = "user";
+ public static final String SDC_ADDRESS_ATTRIBUTE_NAME = "sdcAddress";
+ public static final String POLLING_TIMEOUT_ATTRIBUTE_NAME = "pollingTimeout";
+ public static final String ACTIVATE_SERVER_TLS_AUTH = "activateServerTLSAuth";
+ public static final String KEY_STORE_KEY = "keyStorePassword";
+ public static final String KEY_STORE_PATH = "keyStorePath";
+ public static final String MESSAGE_BUS_ADDRESSES = "messageBusAddresses";
+ private String errorMessageKeyNotFound;
+ /**
+ * Supported artifact types.
+ */
+ public static final String HEAT = "HEAT";
+ public static final String HEAT_ARTIFACT = "HEAT_ARTIFACT";
+ public static final String HEAT_ENV = "HEAT_ENV";
+ public static final String HEAT_NESTED = "HEAT_NESTED";
+ public static final String HEAT_NET = "HEAT_NET";
+ public static final String HEAT_VOL = "HEAT_VOL";
+ public static final String OTHER = "OTHER";
+ public static final String TOSCA_CSAR = "TOSCA_CSAR";
+ public static final String VF_MODULES_METADATA = "VF_MODULES_METADATA";
+ private static final String[] SUPPORTED_ARTIFACT_TYPES = {
+ TOSCA_CSAR, VF_MODULES_METADATA
+ };
+ public static final List<String> SUPPORTED_ARTIFACT_TYPES_LIST = Collections
+ .unmodifiableList(Arrays.asList(SUPPORTED_ARTIFACT_TYPES));
+
+ /**
+ * This constructor builds a SdcSingleControllerConfiguration from the
+ * corresponding json.
+ *
+ * @param jsonNode
+ * The JSON node
+ * @param controllerName
+ * The controller name that must appear in the JSON
+ */
+ public SdcSingleControllerConfiguration(JsonObject jsonNode, String controllerName) {
+ jsonRootNode = jsonNode;
+ setSdcControllerName(controllerName);
+ testAllRequiredParameters();
+ }
+
+ public String getSdcControllerName() {
+ return sdcControllerName;
+ }
+
+ /**
+ * Sets SDC controller name.
+ *
+ * @param controllerName SDC controller name
+ */
+ public void setSdcControllerName(String controllerName) {
+ this.sdcControllerName = controllerName;
+ errorMessageKeyNotFound = " parameter cannot be found in config file for controller name" + sdcControllerName;
+ testAllRequiredParameters();
+ }
+
+ private String getStringConfig(String key) {
+ if (jsonRootNode != null && jsonRootNode.get(key) != null) {
+ String config = jsonRootNode.get(key).getAsString();
+ return config.isEmpty() ? null : config;
+ }
+ return null;
+ }
+
+ private Integer getIntConfig(String key) {
+ if (jsonRootNode != null && jsonRootNode.get(key) != null) {
+ return jsonRootNode.get(key).getAsInt();
+ } else {
+ return 0;
+ }
+ }
+
+ private String getEncryptedStringConfig(String key) throws GeneralSecurityException, DecoderException {
+ if (jsonRootNode != null && jsonRootNode.get(key) != null) {
+ return jsonRootNode.get(key).getAsString().isEmpty() ? null
+ : CryptoUtils.decrypt(jsonRootNode.get(key).getAsString());
+ }
+ return null;
+ }
+
+ @Override
+ public java.lang.Boolean isUseHttpsWithDmaap() {
+ return false;
+ }
+
+ @Override
+ public String getConsumerGroup() {
+ if (jsonRootNode != null && jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME) != null) {
+ String config = jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME).getAsString();
+ return "NULL".equals(config) || config.isEmpty() ? null : config;
+ }
+ return null;
+ }
+
+ @Override
+ public String getConsumerID() {
+ return getStringConfig(CONSUMER_ID_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public String getEnvironmentName() {
+ return getStringConfig(ENVIRONMENT_NAME_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public String getPassword() {
+ try {
+ return getEncryptedStringConfig(SDC_KEY_ATTRIBUTE_NAME);
+ } catch (GeneralSecurityException | DecoderException e) {
+ logger.error("Unable to decrypt the SDC password", e);
+ return null;
+ }
+ }
+
+ @Override
+ public int getPollingInterval() {
+ return getIntConfig(POLLING_INTERVAL_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public List<String> getRelevantArtifactTypes() {
+ // DO not return the Static List SUPPORTED_ARTIFACT_TYPES_LIST because
+ // the ASDC Client could try to modify it !!!
+ return Arrays.asList(SUPPORTED_ARTIFACT_TYPES);
+ }
+
+ @Override
+ public String getUser() {
+ return getStringConfig(USER_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public String getAsdcAddress() {
+ return getStringConfig(SDC_ADDRESS_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public int getPollingTimeout() {
+ return getIntConfig(POLLING_TIMEOUT_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public boolean activateServerTLSAuth() {
+ if (jsonRootNode != null && jsonRootNode.get(ACTIVATE_SERVER_TLS_AUTH) != null
+ && jsonRootNode.get(ACTIVATE_SERVER_TLS_AUTH).isJsonPrimitive()) {
+ return jsonRootNode.get(ACTIVATE_SERVER_TLS_AUTH).getAsBoolean();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public String getKeyStorePassword() {
+ try {
+ return getEncryptedStringConfig(KEY_STORE_KEY);
+ } catch (GeneralSecurityException | DecoderException e) {
+ logger.error("Unable to decrypt the SDC password", e);
+ return null;
+ }
+ }
+
+ @Override
+ public String getKeyStorePath() {
+ return getStringConfig(KEY_STORE_PATH);
+ }
+
+ /**
+ * This method can be used to validate all required parameters are well
+ * there.
+ */
+ public void testAllRequiredParameters() {
+ // Special case for this attribute that can be null from
+ // getConsumerGroup
+ if (jsonRootNode == null) {
+ throw new SdcParametersException("Json is null for controller " + this.getSdcControllerName());
+ }
+ if (this.getConsumerGroup() == null && (jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME) == null
+ || !"NULL".equals(jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME).getAsString()))) {
+ throw new SdcParametersException(CONSUMER_GROUP_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getConsumerID() == null || this.getConsumerID().isEmpty()) {
+ throw new SdcParametersException(CONSUMER_ID_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getEnvironmentName() == null || this.getEnvironmentName().isEmpty()) {
+ throw new SdcParametersException(ENVIRONMENT_NAME_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getAsdcAddress() == null || this.getAsdcAddress().isEmpty()) {
+ throw new SdcParametersException(SDC_ADDRESS_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getMsgBusAddress() == null || this.getMsgBusAddress().isEmpty()) {
+ throw new SdcParametersException(MESSAGE_BUS_ADDRESSES + errorMessageKeyNotFound);
+ }
+ if (this.getPassword() == null || this.getPassword().isEmpty()) {
+ throw new SdcParametersException(SDC_KEY_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getPollingInterval() == 0) {
+ throw new SdcParametersException(POLLING_INTERVAL_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getPollingTimeout() == 0) {
+ throw new SdcParametersException(POLLING_TIMEOUT_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getRelevantArtifactTypes() == null || this.getRelevantArtifactTypes().isEmpty()) {
+ throw new SdcParametersException(RELEVANT_ARTIFACT_TYPES_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getUser() == null || this.getUser().isEmpty()) {
+ throw new SdcParametersException(USER_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ }
+
+ /**
+ * The flag allows the client to receive metadata for all resources of the
+ * service regardless of the artifacts associated to them. Setting the flag
+ * to false will preserve legacy behavior.
+ */
+ @Override
+ public boolean isFilterInEmptyResources() {
+ return false;
+ }
+
+ @Override
+ public List<String> getMsgBusAddress() {
+ List<String> addressesList = new ArrayList<>();
+ if (jsonRootNode != null && jsonRootNode.get(MESSAGE_BUS_ADDRESSES) != null) {
+ jsonRootNode.get(MESSAGE_BUS_ADDRESSES).getAsJsonArray().forEach(k -> addressesList.add(k.getAsString()));
+ return addressesList;
+ } else {
+ return addressesList;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/config/spring/CldsConfiguration.java b/src/main/java/org/onap/clamp/clds/config/spring/CldsConfiguration.java
new file mode 100644
index 000000000..14c08c800
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/spring/CldsConfiguration.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.config.spring;
+
+import org.onap.clamp.clds.config.ClampProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.PropertiesFactoryBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+@Profile("clamp-default")
+public class CldsConfiguration {
+
+ @Autowired
+ private ApplicationContext appContext;
+ @Autowired
+ private ClampProperties refProp;
+
+
+ /**
+ * This loads the file system.properties.
+ *
+ * @return The PropertiesFactoryBean
+ */
+ @Bean(name = "mapper")
+ public PropertiesFactoryBean mapper() {
+ PropertiesFactoryBean bean = new PropertiesFactoryBean();
+ bean.setLocation(appContext.getResource(refProp.getStringValue("files.systemProperties")));
+ return bean;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/config/spring/SdcControllerConfiguration.java b/src/main/java/org/onap/clamp/clds/config/spring/SdcControllerConfiguration.java
new file mode 100644
index 000000000..eca45d66f
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/config/spring/SdcControllerConfiguration.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.config.spring;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.clds.config.sdc.SdcControllersConfiguration;
+import org.onap.clamp.clds.exception.sdc.controller.SdcControllerException;
+import org.onap.clamp.clds.sdc.controller.SdcSingleController;
+import org.onap.clamp.clds.sdc.controller.SdcSingleControllerStatus;
+import org.onap.clamp.loop.CsarInstaller;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.Scheduled;
+
+@Configuration
+@Profile("clamp-sdc-controller")
+public class SdcControllerConfiguration {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcControllerConfiguration.class);
+ private List<SdcSingleController> sdcControllersList = new ArrayList<>();
+ private final ClampProperties clampProp;
+ private final CsarInstaller csarInstaller;
+
+ @Autowired
+ public SdcControllerConfiguration(ClampProperties clampProp,
+ @Qualifier("csarInstaller") CsarInstaller csarInstaller) {
+ this.clampProp = clampProp;
+ this.csarInstaller = csarInstaller;
+ }
+
+ /**
+ * Loads SDC controller configuration.
+ */
+ @PostConstruct
+ public void loadSdcControllers() {
+ SdcControllersConfiguration sdcControllersConfig = getSdcControllersConfiguration();
+ sdcControllersConfig.getAllDefinedControllers().forEach((key, value) -> {
+ logger.info("Creating controller instance:" + key);
+ SdcSingleController sdcController = new SdcSingleController(clampProp, csarInstaller, value, null);
+ sdcControllersList.add(sdcController);
+ });
+ }
+
+ /**
+ * Checks whether all SDC controllers defined are up and running.
+ */
+ @Scheduled(fixedRate = 120000)
+ public void checkAllSdcControllers() {
+ logger.info("Checking that all SDC Controllers defined are up and running");
+ for (SdcSingleController controller : sdcControllersList) {
+ try {
+ if (SdcSingleControllerStatus.STOPPED.equals(controller.getControllerStatus())) {
+ controller.initSdc();
+ }
+ } catch (SdcControllerException e) {
+ logger.error("Exception caught when booting sdc controller", e);
+ }
+ }
+ logger.info("SDC Controllers check completed");
+ }
+
+ /**
+ * Closes all SDC Controller and the SDC Client.
+ */
+ @PreDestroy
+ public void killSdcControllers() {
+ sdcControllersList.forEach(e -> {
+ try {
+ e.closeSdc();
+ } catch (SdcControllerException e1) {
+ logger.error("Exception caught when stopping sdc controller", e1);
+ }
+ });
+ }
+
+ @Bean(name = "sdcControllersConfiguration")
+ public SdcControllersConfiguration getSdcControllersConfiguration() {
+ return new SdcControllersConfiguration();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/exception/CldsConfigException.java b/src/main/java/org/onap/clamp/clds/exception/CldsConfigException.java
new file mode 100644
index 000000000..93d98151a
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/CldsConfigException.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.exception;
+
+/**
+ * New exception to CldsUser errors.
+ *
+ */
+public class CldsConfigException extends RuntimeException {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 5958873136187918505L;
+
+ /**
+ * This constructor can be used to create a new CldsConfigException.
+ *
+ * @param message
+ * A string message detailing the problem
+ * @param ex
+ * The exception sent by the code
+ */
+ public CldsConfigException(String message, Throwable ex) {
+ super(message, ex);
+ }
+
+ /**
+ * This constructor can be used to create a new CldsConfigException. Use
+ * this constructor only if you are creating a new exception stack, not if
+ * an exception was already raised by another code.
+ *
+ * @param message
+ * A string message detailing the problem
+ */
+ public CldsConfigException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/CldsUsersException.java b/src/main/java/org/onap/clamp/clds/exception/CldsUsersException.java
new file mode 100644
index 000000000..270bfa1e2
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/CldsUsersException.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.exception;
+
+/**
+ * New exception to CldsUser errors.
+ *
+ */
+public class CldsUsersException extends RuntimeException {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 933535057227505342L;
+
+ /**
+ * This constructor can be used to create a new CldsUsersException.
+ *
+ * @param message
+ * A string message detailing the problem
+ * @param ex
+ * The exception sent by the code
+ */
+ public CldsUsersException(String message, Throwable ex) {
+ super(message, ex);
+ }
+
+ /**
+ * This constructor can be used to create a new CldsUsersException. Use this
+ * constructor only if you are creating a new exception stack, not if an
+ * exception was already raised by another code.
+ *
+ * @param message
+ * A string message detailing the problem
+ */
+ public CldsUsersException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/NotAuthorizedException.java b/src/main/java/org/onap/clamp/clds/exception/NotAuthorizedException.java
new file mode 100644
index 000000000..1bdf18e7e
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/NotAuthorizedException.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.exception;
+
+/**
+ * New exception to request errors.
+ *
+ */
+public class NotAuthorizedException extends RuntimeException {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -5738167530541646123L;
+
+ /**
+ * This constructor can be used to create a new CldsConfigException.
+ *
+ * @param message
+ * A string message detailing the problem
+ * @param ex
+ * The exception sent by the code
+ */
+ public NotAuthorizedException(String message, Throwable ex) {
+ super(message, ex);
+ }
+
+ /**
+ * This constructor can be used to create a new CldsConfigException. Use this
+ * constructor only if you are creating a new exception stack, not if an
+ * exception was already raised by another code.
+ *
+ * @param message
+ * A string message detailing the problem
+ */
+ public NotAuthorizedException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/cds/CdsParametersException.java b/src/main/java/org/onap/clamp/clds/exception/cds/CdsParametersException.java
new file mode 100644
index 000000000..73ce31f89
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/cds/CdsParametersException.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * 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.clamp.clds.exception.cds;
+
+/**
+ * Exception while parsing CDS response.
+ */
+public class CdsParametersException extends RuntimeException {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = 8425657297510362736L;
+
+ /**
+ * This constructor can be used to create a new CdsParametersException.
+ *
+ * @param message The message to dump
+ */
+ public CdsParametersException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new CdsParametersException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public CdsParametersException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/dcae/DcaeDeploymentException.java b/src/main/java/org/onap/clamp/clds/exception/dcae/DcaeDeploymentException.java
new file mode 100644
index 000000000..e733da53d
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/dcae/DcaeDeploymentException.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.exception.dcae;
+
+/**
+ * New exception to capture DCAE communication errors.
+ *
+ */
+public class DcaeDeploymentException extends RuntimeException {
+
+ /**
+ * Generated ID.
+ */
+ private static final long serialVersionUID = 8452294782552680243L;
+
+ /**
+ * This constructor can be used to create a new DcaeDeploymentException.
+ *
+ * @param message
+ * A string message detailing the problem
+ * @param ex
+ * The exception sent by the code
+ */
+ public DcaeDeploymentException(String message, Throwable ex) {
+ super(message, ex);
+ }
+
+ /**
+ * This constructor can be used to create a new DcaeDeploymentException. Use
+ * this constructor only if you are creating a new exception stack, not if
+ * an exception was already raised by another code.
+ *
+ * @param message
+ * A string message detailing the problem
+ */
+ public DcaeDeploymentException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/BlueprintParserException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/BlueprintParserException.java
new file mode 100644
index 000000000..7257fd8a0
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/BlueprintParserException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception during blueprint parsing.
+ */
+public class BlueprintParserException extends Exception {
+
+ /**
+ * Serial ID.
+ */
+ private static final long serialVersionUID = -3044162346353623199L;
+
+ /**
+ * This constructor can be used to create a new SdcDownloadException.
+ *
+ * @param message The message to dump
+ */
+ public BlueprintParserException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcDownloadException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public BlueprintParserException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java
new file mode 100644
index 000000000..c3ebde1f8
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception during Csar operations.
+ */
+public class CsarHandlerException extends Exception {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -7628640776124409155L;
+
+ /**
+ * This constructor can be used to create a new CsarHandlerException.
+ *
+ * @param message The message to dump
+ */
+ public CsarHandlerException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new CsarHandlerException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public CsarHandlerException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java
new file mode 100644
index 000000000..523766af1
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception during SDC artifact installation.
+ */
+public class SdcArtifactInstallerException extends Exception {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = 4095937499475915021L;
+
+ /**
+ * This constructor can be used to create a new SdcArtifactInstallerException.
+ *
+ * @param message The message to dump
+ */
+ public SdcArtifactInstallerException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcArtifactInstallerException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public SdcArtifactInstallerException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcControllerException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcControllerException.java
new file mode 100644
index 000000000..d73001d78
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcControllerException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception of the SDC controller.
+ */
+public class SdcControllerException extends Exception {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = -4236006447255525130L;
+
+ /**
+ * This constructor can be used to create a new SdcControllerException.
+ *
+ * @param message The message to dump
+ */
+ public SdcControllerException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcControllerException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public SdcControllerException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcDownloadException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcDownloadException.java
new file mode 100644
index 000000000..6cd3fb88d
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcDownloadException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception during download from SDC.
+ */
+public class SdcDownloadException extends Exception {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = -5276848693231134901L;
+
+ /**
+ * This constructor can be used to create a new SdcDownloadException.
+ *
+ * @param message The message to dump
+ */
+ public SdcDownloadException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcDownloadException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public SdcDownloadException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcParametersException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcParametersException.java
new file mode 100644
index 000000000..bfe63cbfb
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcParametersException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception of the SDC controller.
+ */
+public class SdcParametersException extends RuntimeException {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = 8425657297510362736L;
+
+ /**
+ * This constructor can be used to create a new SdcParametersException.
+ *
+ * @param message The message to dump
+ */
+ public SdcParametersException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcParametersException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public SdcParametersException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/filter/ClampCadiFilter.java b/src/main/java/org/onap/clamp/clds/filter/ClampCadiFilter.java
new file mode 100644
index 000000000..c673f544a
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/filter/ClampCadiFilter.java
@@ -0,0 +1,190 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.filter;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.StandardCopyOption;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.cadi.filter.CadiFilter;
+import org.onap.clamp.clds.util.ResourceFileUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+
+public class ClampCadiFilter extends CadiFilter {
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(ClampCadiFilter.class);
+
+ @Autowired
+ private ApplicationContext appContext;
+
+ @Value("${server.ssl.key-store:#{null}}")
+ private String keyStore;
+
+ @Value("${server.ssl.key-store-password:#{null}}")
+ private String keyStorePass;
+
+ @Value("${server.ssl.trust-store:#{null}}")
+ private String trustStore;
+
+ @Value("${server.ssl.trust-store-password:#{null}}")
+ private String trustStorePass;
+
+ @Value("${server.ssl.key-alias:clamp@clamp.onap.org}")
+ private String alias;
+
+ @Value("${clamp.config.keyFile:#{null}}")
+ private String keyFile;
+
+ @Value("${clamp.config.cadi.cadiLoglevel:#{null}}")
+ private String cadiLoglevel;
+
+ @Value("${clamp.config.cadi.cadiLatitude:#{null}}")
+ private String cadiLatitude;
+
+ @Value("${clamp.config.cadi.cadiLongitude:#{null}}")
+ private String cadiLongitude;
+
+ @Value("${clamp.config.cadi.aafLocateUrl:#{null}}")
+ private String aafLocateUrl;
+
+ @Value("${clamp.config.cadi.oauthTokenUrl:#{null}}")
+ private String oauthTokenUrl;
+
+ @Value("${clamp.config.cadi.oauthIntrospectUrl:#{null}}")
+ private String oauthIntrospectUrl;
+
+ @Value("${clamp.config.cadi.aafEnv:#{null}}")
+ private String aafEnv;
+
+ @Value("${clamp.config.cadi.aafUrl:#{null}}")
+ private String aafUrl;
+
+ @Value("${clamp.config.cadi.cadiX509Issuers:#{null}}")
+ private String cadiX509Issuers;
+
+ @Value("${clamp.config.caCerts:#{null}}")
+ private String caCertsPath;
+
+ private void checkIfNullProperty(String key, String value) {
+ /*
+ * When value is null, so not defined in application.properties set nothing in
+ * System properties
+ */
+ if (value != null) {
+ /*
+ * Ensure that any properties already defined in System.prop by JVM params won't
+ * be overwritten by Spring application.properties values
+ */
+ System.setProperty(key, System.getProperty(key, value));
+ }
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // set some properties in System so that Cadi filter will find its config
+ // The JVM values set will always overwrite the Spring ones.
+ checkIfNullProperty(Config.CADI_KEYFILE, convertSpringToPath(keyFile));
+ checkIfNullProperty(Config.CADI_LOGLEVEL, cadiLoglevel);
+ checkIfNullProperty(Config.CADI_LATITUDE, cadiLatitude);
+ checkIfNullProperty(Config.CADI_LONGITUDE, cadiLongitude);
+
+ checkIfNullProperty(Config.AAF_LOCATE_URL, aafLocateUrl);
+ checkIfNullProperty(Config.AAF_OAUTH2_TOKEN_URL, oauthTokenUrl);
+ checkIfNullProperty(Config.AAF_OAUTH2_INTROSPECT_URL, oauthIntrospectUrl);
+
+ checkIfNullProperty(Config.AAF_ENV, aafEnv);
+ checkIfNullProperty(Config.AAF_URL, aafUrl);
+ checkIfNullProperty(Config.CADI_X509_ISSUERS, cadiX509Issuers);
+ checkIfNullProperty(Config.CADI_KEYSTORE, convertSpringToPath(keyStore));
+ checkIfNullProperty(Config.CADI_TRUSTSTORE, convertSpringToPath(trustStore));
+ checkIfNullProperty(Config.CADI_ALIAS, alias);
+ checkIfNullProperty(Config.CADI_KEYSTORE_PASSWORD, keyStorePass);
+ checkIfNullProperty(Config.CADI_TRUSTSTORE_PASSWORD, trustStorePass);
+
+ super.init(filterConfig);
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ try {
+ String certHeader = ((HttpServletRequest) request).getHeader("X-SSL-Cert");
+ if (certHeader != null) {
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) certificateFactory
+ .generateCertificate(new ByteArrayInputStream(
+ URLDecoder.decode(certHeader, StandardCharsets.UTF_8.toString()).getBytes()));
+ X509Certificate caCert = (X509Certificate) certificateFactory
+ .generateCertificate(new ByteArrayInputStream(
+ ResourceFileUtils.getResourceAsString(this.caCertsPath).getBytes()));
+
+ X509Certificate[] certifArray = ((X509Certificate[]) request
+ .getAttribute("javax.servlet.request.X509Certificate"));
+ if (certifArray == null) {
+ certifArray = new X509Certificate[] { cert, caCert };
+ request.setAttribute("javax.servlet.request.X509Certificate", certifArray);
+ } else {
+ certifArray[0] = cert;
+ certifArray[1] = caCert;
+ }
+ }
+
+ } catch (CertificateException e) {
+ logger.error("Unable to inject the X.509 certificate", e);
+ }
+ super.doFilter(request, response, chain);
+ }
+
+ private String convertSpringToPath(String fileName) {
+ try (InputStream ioFile = appContext.getResource(fileName).getInputStream()) {
+ if (!fileName.contains("file:")) {
+ File targetFile = new File(appContext.getResource(fileName).getFilename());
+ java.nio.file.Files.copy(ioFile, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ return targetFile.getPath();
+ } else {
+ return appContext.getResource(fileName).getFile().getPath();
+ }
+ } catch (IOException e) {
+ logger.error("Unable to open and copy the file: " + fileName, e);
+ return null;
+ }
+
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/model/ClampInformation.java b/src/main/java/org/onap/clamp/clds/model/ClampInformation.java
new file mode 100644
index 000000000..d73e94204
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/model/ClampInformation.java
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2020 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.clamp.clds.model;
+
+import com.google.gson.annotations.Expose;
+import java.util.ArrayList;
+import java.util.List;
+import org.onap.clamp.clds.util.ClampVersioning;
+
+public class ClampInformation {
+ @Expose
+ private String userName;
+ @Expose
+ private String cldsVersion = ClampVersioning.getCldsVersionFromProps();
+ @Expose
+ List<String> allPermissions = new ArrayList<>();
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getCldsVersion() {
+ return cldsVersion;
+ }
+
+ public void setCldsVersion(String cldsVersion) {
+ this.cldsVersion = cldsVersion;
+ }
+
+ public List<String> getAllPermissions() {
+ return allPermissions;
+ }
+
+ public void setAllPermissions(List<String> allPermissions) {
+ this.allPermissions = allPermissions;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/model/CldsHealthCheck.java b/src/main/java/org/onap/clamp/clds/model/CldsHealthCheck.java
new file mode 100644
index 000000000..651997cd3
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/model/CldsHealthCheck.java
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.model;
+
+import com.google.gson.annotations.Expose;
+
+public class CldsHealthCheck {
+ @Expose
+ private String healthCheckComponent;
+ @Expose
+ private String healthCheckStatus;
+ @Expose
+ private String description;
+
+ public String getHealthCheckComponent() {
+ return healthCheckComponent;
+ }
+
+ public void setHealthCheckComponent(String healthCheckComponent) {
+ this.healthCheckComponent = healthCheckComponent;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getHealthCheckStatus() {
+ return healthCheckStatus;
+ }
+
+ public void setHealthCheckStatus(String healthCheckStatus) {
+ this.healthCheckStatus = healthCheckStatus;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java b/src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java
new file mode 100644
index 000000000..66025c479
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * 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.clamp.clds.model.cds;
+
+import com.google.gson.annotations.Expose;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class maps the CDS response to a pojo.
+ */
+public class CdsBpWorkFlowListResponse {
+
+ @Expose
+ private String blueprintName;
+
+ @Expose
+ private String version;
+
+ @Expose
+ private List<String> workflows = new LinkedList<String>();
+
+ public String getBlueprintName() {
+ return blueprintName;
+ }
+
+ public void setBlueprintName(String blueprintName) {
+ this.blueprintName = blueprintName;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public List<String> getWorkflows() {
+ return workflows;
+ }
+
+ public void setWorkflows(List<String> workflows) {
+ this.workflows = workflows;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryCache.java b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryCache.java
new file mode 100644
index 000000000..fc2ca5caa
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryCache.java
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.model.dcae;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This class stores the multiple DcaeInventoryResponse coming back from DCAE.
+ * The structure is a map of list indexed by asdcServiceId. The list is sorted
+ * by asdcResourceId. Therefore it's possible to retrieve all the loops defined
+ * in the DCAE inventory and created by DCAE Mod.
+ */
+public class DcaeInventoryCache {
+
+ private static Map<String, Set<DcaeInventoryResponse>> blueprintsMap = new ConcurrentHashMap<>();
+
+ /**
+ * Add Dcae inventory response.
+ *
+ * @param inventoryResponse the Dcae inventory response
+ */
+ public void addDcaeInventoryResponse(DcaeInventoryResponse inventoryResponse) {
+ Set<DcaeInventoryResponse> responsesSet = blueprintsMap.get(inventoryResponse.getAsdcServiceId());
+ if (responsesSet == null) {
+ responsesSet = new TreeSet<>();
+ blueprintsMap.put(inventoryResponse.getAsdcServiceId(), responsesSet);
+ }
+ responsesSet.add(inventoryResponse);
+ }
+
+ public Set<String> getAllLoopIds() {
+ return this.blueprintsMap.keySet();
+ }
+
+ public Set<DcaeInventoryResponse> getAllBlueprintsPerLoopId(String loopId) {
+ return blueprintsMap.getOrDefault(loopId, new TreeSet<>());
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponse.java b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponse.java
new file mode 100644
index 000000000..67bd026d0
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponse.java
@@ -0,0 +1,102 @@
+
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.model.dcae;
+
+import com.google.gson.annotations.Expose;
+
+/**
+ * This class maps the DCAE inventory answer to a nice pojo.
+ */
+public class DcaeInventoryResponse implements Comparable<DcaeInventoryResponse> {
+
+ @Expose
+ private String typeName;
+
+ @Expose
+ private String typeId;
+
+ @Expose
+ private String blueprintTemplate;
+
+ /**
+ * This field will be used to know all blueprints associated a loop.
+ */
+ @Expose
+ private String asdcServiceId;
+
+ /**
+ * This field will be used to know to order of each blueprint microservice in a
+ * loop.
+ */
+ @Expose
+ private String asdcResourceId;
+
+ public String getTypeName() {
+ return typeName;
+ }
+
+ public void setTypeName(String typeName) {
+ this.typeName = typeName;
+ }
+
+ public String getTypeId() {
+ return typeId;
+ }
+
+ public void setTypeId(String typeId) {
+ this.typeId = typeId;
+ }
+
+ public String getBlueprintTemplate() {
+ return blueprintTemplate;
+ }
+
+ public void setBlueprintTemplate(String blueprintTemplate) {
+ this.blueprintTemplate = blueprintTemplate;
+ }
+
+ public String getAsdcServiceId() {
+ return asdcServiceId;
+ }
+
+ public void setAsdcServiceId(String asdcServiceId) {
+ this.asdcServiceId = asdcServiceId;
+ }
+
+ public String getAsdcResourceId() {
+ return asdcResourceId;
+ }
+
+ public void setAsdcResourceId(String asdcResourceId) {
+ this.asdcResourceId = asdcResourceId;
+ }
+
+ @Override
+ public int compareTo(DcaeInventoryResponse otherResponse) {
+ int thisResourceId = Integer.parseInt(this.asdcResourceId);
+ int otherResourceId = Integer.parseInt(otherResponse.getAsdcResourceId());
+ return (thisResourceId < otherResourceId ? -1 : (thisResourceId > otherResourceId ? 1 : 0));
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/model/dcae/DcaeLinks.java b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeLinks.java
new file mode 100644
index 000000000..368e1b8e6
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeLinks.java
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.model.dcae;
+
+import com.google.gson.annotations.Expose;
+
+public class DcaeLinks {
+ @Expose
+ private String self;
+ @Expose
+ private String status;
+ @Expose
+ private String uninstall;
+
+ public String getSelf() {
+ return self;
+ }
+
+ public void setSelf(String self) {
+ this.self = self;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public String getUninstall() {
+ return uninstall;
+ }
+
+ public void setUninstall(String uninstall) {
+ this.uninstall = uninstall;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/model/dcae/DcaeOperationStatusResponse.java b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeOperationStatusResponse.java
new file mode 100644
index 000000000..aee7d0613
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeOperationStatusResponse.java
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.model.dcae;
+
+import com.google.gson.annotations.Expose;
+
+/**
+ * This class maps the DCAE deployment handler response to a nice pojo.
+ */
+public class DcaeOperationStatusResponse {
+
+ @Expose
+ private String operationType;
+
+ @Expose
+ private String status;
+
+ @Expose
+ private String requestId;
+
+ @Expose
+ private String error;
+
+ @Expose
+ private DcaeLinks links;
+
+ public String getOperationType() {
+ return operationType;
+ }
+
+ public void setOperationType(String operationType) {
+ this.operationType = operationType;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public String getRequestId() {
+ return requestId;
+ }
+
+ public void setRequestId(String requestId) {
+ this.requestId = requestId;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ public DcaeLinks getLinks() {
+ return links;
+ }
+
+ public void setLinks(DcaeLinks links) {
+ this.links = links;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/DistributionStatusMessage.java b/src/main/java/org/onap/clamp/clds/sdc/controller/DistributionStatusMessage.java
new file mode 100644
index 000000000..c80441fa6
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/sdc/controller/DistributionStatusMessage.java
@@ -0,0 +1,84 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.sdc.controller;
+
+import org.onap.sdc.api.consumer.IDistributionStatusMessage;
+import org.onap.sdc.utils.DistributionStatusEnum;
+
+public class DistributionStatusMessage implements IDistributionStatusMessage {
+
+ private String artifactUrl;
+ private String consumerId;
+ private String distributionId;
+ private DistributionStatusEnum distributionStatus;
+ private long timestamp;
+
+ /**
+ * Distribution status message constructor.
+ *
+ * @param artifactUrl
+ * Url of specific SDC artifact(resource)
+ * @param consumerId
+ * Unique ID of SDC component instance
+ * @param distributionId
+ * Distribution ID published in the distribution notification.
+ * @param distributionStatusEnum
+ * Status to send in the message
+ * @param timestamp
+ * Timestamp of the message
+ */
+ public DistributionStatusMessage(final String artifactUrl, final String consumerId, final String distributionId,
+ final DistributionStatusEnum distributionStatusEnum, final long timestamp) {
+ this.artifactUrl = artifactUrl;
+ this.consumerId = consumerId;
+ this.distributionId = distributionId;
+ this.distributionStatus = distributionStatusEnum;
+ this.timestamp = timestamp;
+ }
+
+ @Override
+ public String getArtifactURL() {
+ return artifactUrl;
+ }
+
+ @Override
+ public String getConsumerID() {
+ return consumerId;
+ }
+
+ @Override
+ public String getDistributionID() {
+ return distributionId;
+ }
+
+ @Override
+ public DistributionStatusEnum getStatus() {
+ return distributionStatus;
+ }
+
+ @Override
+ public long getTimestamp() {
+ return timestamp;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java b/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java
new file mode 100644
index 000000000..f9b43abb7
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java
@@ -0,0 +1,435 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018-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============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.sdc.controller;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.util.Date;
+import java.util.Map.Entry;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.clds.config.sdc.SdcSingleControllerConfiguration;
+import org.onap.clamp.clds.exception.sdc.controller.BlueprintParserException;
+import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcControllerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcDownloadException;
+import org.onap.clamp.clds.sdc.controller.installer.BlueprintArtifact;
+import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.clamp.clds.util.LoggingUtils;
+import org.onap.clamp.loop.CsarInstaller;
+import org.onap.sdc.api.IDistributionClient;
+import org.onap.sdc.api.consumer.IComponentDoneStatusMessage;
+import org.onap.sdc.api.consumer.IDistributionStatusMessage;
+import org.onap.sdc.api.consumer.INotificationCallback;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.api.results.IDistributionClientResult;
+import org.onap.sdc.impl.DistributionClientFactory;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+import org.onap.sdc.utils.DistributionActionResultEnum;
+import org.onap.sdc.utils.DistributionStatusEnum;
+
+/**
+ * This class handles one sdc controller defined in the config.
+ */
+public class SdcSingleController {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcSingleController.class);
+ private boolean isSdcClientAutoManaged = false;
+ private CsarInstaller csarInstaller;
+ private ClampProperties refProp;
+ /**
+ * The constant CONFIG_SDC_FOLDER.
+ */
+ public static final String CONFIG_SDC_FOLDER = "sdc.csarFolder";
+ private int nbOfNotificationsOngoing = 0;
+ private SdcSingleControllerStatus controllerStatus = SdcSingleControllerStatus.STOPPED;
+ private SdcSingleControllerConfiguration sdcConfig;
+ private IDistributionClient distributionClient;
+
+ /**
+ * Inner class for Notification callback.
+ */
+ private final class SdcNotificationCallBack implements INotificationCallback {
+
+ private SdcSingleController sdcController;
+
+ /**
+ * Instantiates a new Sdc notification call back.
+ *
+ * @param controller the controller
+ */
+ SdcNotificationCallBack(SdcSingleController controller) {
+ sdcController = controller;
+ }
+
+ /**
+ * This method can be called multiple times at the same moment. The controller
+ * must be thread safe !
+ */
+ @Override
+ public void activateCallback(INotificationData notificationData) {
+ Date startTime = new Date();
+ logger.info("Receive a callback notification in SDC, nb of resources: "
+ + notificationData.getResources().size());
+ sdcController.treatNotification(notificationData);
+ LoggingUtils.setTimeContext(startTime, new Date());
+ LoggingUtils.setResponseContext("0", "SDC Notification received and processed successfully",
+ this.getClass().getName());
+ }
+ }
+
+ /**
+ * Gets nb of notifications ongoing.
+ *
+ * @return the nb of notifications ongoing
+ */
+ public int getNbOfNotificationsOngoing() {
+ return nbOfNotificationsOngoing;
+ }
+
+ private void changeControllerStatusIdle() {
+ if (this.nbOfNotificationsOngoing > 1) {
+ --this.nbOfNotificationsOngoing;
+ } else {
+ this.nbOfNotificationsOngoing = 0;
+ this.controllerStatus = SdcSingleControllerStatus.IDLE;
+ }
+ }
+
+ /**
+ * Change controller status.
+ *
+ * @param newControllerStatus the new controller status
+ */
+ protected final synchronized void changeControllerStatus(SdcSingleControllerStatus newControllerStatus) {
+ switch (newControllerStatus) {
+ case BUSY:
+ ++this.nbOfNotificationsOngoing;
+ this.controllerStatus = newControllerStatus;
+ break;
+ case IDLE:
+ this.changeControllerStatusIdle();
+ break;
+ default:
+ this.controllerStatus = newControllerStatus;
+ break;
+ }
+ }
+
+ /**
+ * Gets controller status.
+ *
+ * @return the controller status
+ */
+ public final synchronized SdcSingleControllerStatus getControllerStatus() {
+ return this.controllerStatus;
+ }
+
+ /**
+ * Instantiates a new Sdc single controller.
+ *
+ * @param clampProp the clamp prop
+ * @param csarInstaller the csar installer
+ * @param sdcSingleConfig the sdc single config
+ * @param distributionClient the distribution client
+ */
+ public SdcSingleController(ClampProperties clampProp, CsarInstaller csarInstaller,
+ SdcSingleControllerConfiguration sdcSingleConfig,
+ IDistributionClient distributionClient) {
+ this.distributionClient = distributionClient;
+ isSdcClientAutoManaged = (distributionClient == null);
+ this.sdcConfig = sdcSingleConfig;
+ this.refProp = clampProp;
+ this.csarInstaller = csarInstaller;
+ }
+
+ /**
+ * This method initializes the SDC Controller and the SDC Client.
+ *
+ * @throws SdcControllerException It throws an exception if the SDC Client
+ * cannot be instantiated or if an init attempt
+ * is done when already initialized
+ */
+ public void initSdc() throws SdcControllerException {
+ logger.info("Attempt to initialize the SDC Controller: " + sdcConfig.getSdcControllerName());
+ if (this.getControllerStatus() != SdcSingleControllerStatus.STOPPED) {
+ throw new SdcControllerException("The controller is already initialized, call the closeSDC method first");
+ }
+ if (distributionClient == null) {
+ distributionClient = DistributionClientFactory.createDistributionClient();
+ }
+ IDistributionClientResult result = distributionClient.init(sdcConfig, new SdcNotificationCallBack(this));
+ if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ logger.error("SDC distribution client init failed with reason:" + result.getDistributionMessageResult());
+ this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+ throw new SdcControllerException("Initialization of the SDC Controller failed with reason: "
+ + result.getDistributionMessageResult());
+ }
+ logger.info("SDC Controller successfully initialized: " + sdcConfig.getSdcControllerName());
+ logger.info("Attempt to start the SDC Controller: " + sdcConfig.getSdcControllerName());
+ result = this.distributionClient.start();
+ if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ logger.error("SDC distribution client start failed with reason:" + result.getDistributionMessageResult());
+ this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+ throw new SdcControllerException(
+ "Startup of the SDC Controller failed with reason: " + result.getDistributionMessageResult());
+ }
+ logger.info("SDC Controller successfully started: " + sdcConfig.getSdcControllerName());
+ this.changeControllerStatus(SdcSingleControllerStatus.IDLE);
+ }
+
+ /**
+ * This method closes the SDC Controller and the SDC Client.
+ *
+ * @throws SdcControllerException It throws an exception if the SDC Client
+ * cannot be closed because it's currently BUSY
+ * in processing notifications.
+ */
+ public void closeSdc() throws SdcControllerException {
+ if (this.getControllerStatus() == SdcSingleControllerStatus.BUSY) {
+ throw new SdcControllerException("Cannot close the SDC controller as it's currently in BUSY state");
+ }
+ if (this.distributionClient != null) {
+ this.distributionClient.stop();
+ // If auto managed we can set it to Null, SdcController controls it.
+ // In the other case the client of this class has specified it, so
+ // we can't reset it
+ if (isSdcClientAutoManaged) {
+ // Next init will initialize it with a new SDC Client
+ this.distributionClient = null;
+ }
+ }
+ this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+ }
+
+ private void sendAllNotificationForCsarHandler(INotificationData notificationData, CsarHandler csar,
+ NotificationType notificationType,
+ DistributionStatusEnum distributionStatus, String errorMessage) {
+ if (csar != null) {
+ // Notify for the CSAR
+ this.sendSdcNotification(notificationType, csar.getArtifactElement().getArtifactURL(),
+ sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus, errorMessage,
+ System.currentTimeMillis());
+ // Notify for all VF resources found
+ for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
+ // Normally always 1 artifact in resource for Clamp as we
+ // specified
+ // only VF_METADATA type
+ this.sendSdcNotification(notificationType,
+ blueprint.getValue().getResourceAttached().getArtifacts().get(0).getArtifactURL(),
+ sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus,
+ errorMessage, System.currentTimeMillis());
+ }
+ } else {
+ this.sendSdcNotification(notificationType, null, sdcConfig.getConsumerID(),
+ notificationData.getDistributionID(), distributionStatus, errorMessage, System.currentTimeMillis());
+ }
+ }
+
+ /**
+ * This method processes the notification received from Sdc.
+ *
+ * @param notificationData The INotificationData
+ */
+ public void treatNotification(INotificationData notificationData) {
+ CsarHandler csar = null;
+ try {
+ // wait for a random time, so that 2 running Clamp will not treat
+ // the same Notification at the same time
+ Thread.sleep(ThreadLocalRandom.current().nextInt(1, 10) * 1000L);
+ logger.info("Notification received for service UUID:" + notificationData.getServiceUUID());
+ this.changeControllerStatus(SdcSingleControllerStatus.BUSY);
+ csar = new CsarHandler(notificationData, this.sdcConfig.getSdcControllerName(),
+ refProp.getStringValue(CONFIG_SDC_FOLDER));
+ csar.save(downloadTheArtifact(csar.getArtifactElement()));
+ if (csarInstaller.isCsarAlreadyDeployed(csar)) {
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+ DistributionStatusEnum.ALREADY_DOWNLOADED, null);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.ALREADY_DEPLOYED, null);
+ } else {
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+ DistributionStatusEnum.DOWNLOAD_OK, null);
+ csarInstaller.installTheCsar(csar);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_OK, null);
+ }
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_OK, null);
+ } catch (SdcArtifactInstallerException | SdcToscaParserException e) {
+ logger.error("SdcArtifactInstallerException exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ } catch (SdcDownloadException | CsarHandlerException e) {
+ logger.error("SdcDownloadException exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+ DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ } catch (InterruptedException e) {
+ logger.error("Interrupt exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ Thread.currentThread().interrupt();
+ } catch (BlueprintParserException e) {
+ logger.error("BlueprintParser exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ } catch (RuntimeException e) {
+ logger.error("Unexpected exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ } finally {
+ this.changeControllerStatus(SdcSingleControllerStatus.IDLE);
+ }
+ }
+
+ private enum NotificationType {
+ /**
+ * Download notification type.
+ */
+ DOWNLOAD,
+ /**
+ * Deploy notification type.
+ */
+ DEPLOY
+ }
+
+ private IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact) throws SdcDownloadException {
+ logger.info("Trying to download the artifact : " + artifact.getArtifactURL() + " UUID: "
+ + artifact.getArtifactUUID());
+ IDistributionClientDownloadResult downloadResult;
+ try {
+ downloadResult = distributionClient.download(artifact);
+ if (null == downloadResult) {
+ logger.info("downloadResult is Null for: " + artifact.getArtifactUUID());
+ return null;
+ }
+ } catch (RuntimeException e) {
+ throw new SdcDownloadException("Exception caught when downloading the artifact", e);
+ }
+ if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
+ logger.info("Successfully downloaded the artifact " + artifact.getArtifactURL() + " UUID "
+ + artifact.getArtifactUUID() + "Size of payload " + downloadResult.getArtifactPayload().length);
+ } else {
+ throw new SdcDownloadException("Artifact " + artifact.getArtifactName()
+ + " could not be downloaded from SDC URL " + artifact.getArtifactURL() + " UUID "
+ + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is "
+ + downloadResult.getDistributionMessageResult() + System.lineSeparator());
+ }
+ return downloadResult;
+ }
+
+ private void sendSdcNotification(NotificationType notificationType, String artifactUrl, String consumerId,
+ String distributionId, DistributionStatusEnum status, String errorReason,
+ long timestamp) {
+ String event = "Sending " + notificationType.name() + "(" + status.name() + ")"
+ + " notification to SDC for artifact:" + artifactUrl;
+ if (errorReason != null) {
+ event = event + "(" + errorReason + ")";
+ }
+ logger.info(event);
+ String action = "";
+ try {
+ IDistributionStatusMessage message = new DistributionStatusMessage(artifactUrl, consumerId, distributionId,
+ status, timestamp);
+ switch (notificationType) {
+ case DOWNLOAD:
+ this.sendDownloadStatus(message, errorReason);
+ action = "sendDownloadStatus";
+ break;
+ case DEPLOY:
+ this.sendDeploymentStatus(message, errorReason);
+ action = "sendDeploymentdStatus";
+ break;
+ default:
+ break;
+ }
+ } catch (RuntimeException e) {
+ logger.warn("Unable to send the SDC Notification (" + action + ") due to an exception", e);
+ }
+ logger.info("SDC Notification sent successfully(" + action + ")");
+ }
+
+ private void sendComponentStatus(INotificationData notificationData, DistributionStatusEnum status,
+ String errorReason) {
+ try {
+ IComponentDoneStatusMessage message = new IComponentDoneStatusMessage() {
+
+ @Override public String getDistributionID() {
+ return notificationData.getDistributionID();
+ }
+
+ @Override public String getConsumerID() {
+ return sdcConfig.getConsumerID();
+ }
+
+ @Override public long getTimestamp() {
+ return System.currentTimeMillis();
+ }
+
+ @Override public DistributionStatusEnum getStatus() {
+ return status;
+ }
+
+ @Override public String getComponentName() {
+ return sdcConfig.getUser();
+ }
+ };
+
+ if (errorReason != null) {
+ this.distributionClient.sendComponentDoneStatus(message, errorReason);
+ } else {
+ this.distributionClient.sendComponentDoneStatus(message);
+ }
+ } catch (RuntimeException e) {
+ logger.warn("Unable to send the SDC Notification (" + status.name() + ") due to an exception", e);
+ }
+ logger.info("SDC Notification sent successfully(" + status.name() + ")");
+ }
+
+ private void sendDownloadStatus(IDistributionStatusMessage message, String errorReason) {
+ if (errorReason != null) {
+ this.distributionClient.sendDownloadStatus(message, errorReason);
+ } else {
+ this.distributionClient.sendDownloadStatus(message);
+ }
+ }
+
+ private void sendDeploymentStatus(IDistributionStatusMessage message, String errorReason) {
+ if (errorReason != null) {
+ this.distributionClient.sendDeploymentStatus(message, errorReason);
+ } else {
+ this.distributionClient.sendDeploymentStatus(message);
+ }
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleControllerStatus.java b/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleControllerStatus.java
new file mode 100644
index 000000000..a50e340e3
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleControllerStatus.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.sdc.controller;
+
+public enum SdcSingleControllerStatus {
+ STOPPED, IDLE, BUSY
+}
diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintArtifact.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintArtifact.java
new file mode 100644
index 000000000..35bc909dc
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintArtifact.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.sdc.controller.installer;
+
+import org.onap.sdc.api.notification.IResourceInstance;
+
+/**
+ * This class is useful to store the information concerning
+ * blueprint artifact extracted from SDC CSAR.
+ */
+public class BlueprintArtifact {
+
+ private String dcaeBlueprint;
+ private String blueprintArtifactName;
+ private String blueprintInvariantServiceUuid;
+ private IResourceInstance resourceAttached;
+
+ public String getDcaeBlueprint() {
+ return dcaeBlueprint;
+ }
+
+ public void setDcaeBlueprint(String dcaeBlueprint) {
+ this.dcaeBlueprint = dcaeBlueprint;
+ }
+
+ public String getBlueprintArtifactName() {
+ return blueprintArtifactName;
+ }
+
+ public void setBlueprintArtifactName(String blueprintArtifactName) {
+ this.blueprintArtifactName = blueprintArtifactName;
+ }
+
+ public String getBlueprintInvariantServiceUuid() {
+ return blueprintInvariantServiceUuid;
+ }
+
+ public void setBlueprintInvariantServiceUuid(String blueprintInvariantServiceUuid) {
+ this.blueprintInvariantServiceUuid = blueprintInvariantServiceUuid;
+ }
+
+ public IResourceInstance getResourceAttached() {
+ return resourceAttached;
+ }
+
+ public void setResourceAttached(IResourceInstance resourceAttached) {
+ this.resourceAttached = resourceAttached;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintMicroService.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintMicroService.java
new file mode 100644
index 000000000..e00ce9430
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintMicroService.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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============================================
+ * Modifications copyright (c) 2019-2020 AT&T
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.sdc.controller.installer;
+
+import java.util.Objects;
+
+public class BlueprintMicroService {
+ private final String name;
+ private final String modelType;
+ private final String inputFrom;
+ private final String modelVersion;
+
+ /**
+ * The Micro service constructor.
+ *
+ * @param name The name in String
+ * @param modelType The model type
+ * @param inputFrom Comes from (single chained)
+ */
+ public BlueprintMicroService(String name, String modelType, String inputFrom, String modelVersion) {
+ this.name = name;
+ this.inputFrom = inputFrom;
+ this.modelType = modelType;
+ this.modelVersion = modelVersion;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getModelType() {
+ return modelType;
+ }
+
+ public String getInputFrom() {
+ return inputFrom;
+ }
+
+ /**
+ * modelVerrsion getter.
+ *
+ * @return the modelVersion
+ */
+ public String getModelVersion() {
+ return modelVersion;
+ }
+
+ @Override
+ public String toString() {
+ return "MicroService {" + "name='" + name + '\'' + ", modelType='" + modelType + '\'' + ", inputFrom='"
+ + inputFrom + '\'' + ", modelVersion='" + modelVersion + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ BlueprintMicroService that = (BlueprintMicroService) obj;
+ return name.equals(that.name) && modelType.equals(that.modelType) && inputFrom.equals(that.inputFrom)
+ && modelVersion.equals(that.modelVersion);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, modelType, inputFrom, modelVersion);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParser.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParser.java
new file mode 100644
index 000000000..5d5027d29
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParser.java
@@ -0,0 +1,222 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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============================================
+ * Modifications copyright (c) 2019 AT&T
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.sdc.controller.installer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import java.util.AbstractMap;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.json.JSONObject;
+import org.onap.clamp.clds.exception.sdc.controller.BlueprintParserException;
+import org.yaml.snakeyaml.Yaml;
+
+public class BlueprintParser {
+
+ static final String TCA = "TCA";
+ private static final String NODE_TEMPLATES = "node_templates";
+ private static final String DCAE_NODES = "dcae.nodes.";
+ private static final String DCAE_NODES_POLICY = ".nodes.policy";
+ private static final String TYPE = "type";
+ private static final String PROPERTIES = "properties";
+ private static final String NAME = "name";
+ private static final String INPUT = "inputs";
+ private static final String GET_INPUT = "get_input";
+ private static final String POLICY_MODEL_ID = "policy_model_id";
+ private static final String POLICY_MODEL_VERSION = "policy_model_version";
+ private static final String RELATIONSHIPS = "relationships";
+ private static final String CLAMP_NODE_RELATIONSHIPS_GETS_INPUT_FROM = "clamp_node.relationships.gets_input_from";
+ private static final String TARGET = "target";
+ public static final String DEFAULT_VERSION = "1.0.0";
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(BlueprintParser.class);
+
+ private BlueprintParser() {
+
+ }
+
+ /**
+ * Get all micro services from blueprint.
+ *
+ * @param blueprintString the blueprint in a String
+ * @return A set of MircoService
+ * @throws BlueprintParserException In case of issues with the parsing
+ */
+ public static Set<BlueprintMicroService> getMicroServices(String blueprintString) throws BlueprintParserException {
+ Set<BlueprintMicroService> microServices = new HashSet<>();
+ JsonObject blueprintJson = BlueprintParser.convertToJson(blueprintString);
+ JsonObject nodeTemplateList = blueprintJson.get(NODE_TEMPLATES).getAsJsonObject();
+ JsonObject inputList = blueprintJson.get(INPUT).getAsJsonObject();
+
+ for (Entry<String, JsonElement> entry : nodeTemplateList.entrySet()) {
+ JsonObject nodeTemplate = entry.getValue().getAsJsonObject();
+ if (!nodeTemplate.get(TYPE).getAsString().contains(DCAE_NODES_POLICY)
+ && nodeTemplate.get(TYPE).getAsString().contains(DCAE_NODES)) {
+ BlueprintMicroService microService = getNodeRepresentation(entry, nodeTemplateList, inputList);
+ if (!microService.getModelType().isBlank()) {
+ microServices.add(microService);
+ } else {
+ logger.warn("Microservice " + microService.getName()
+ + " will NOT be used by CLAMP as the model type is not defined or has not been found");
+ }
+ }
+ }
+ logger.debug("Those microservices have been found in the blueprint:" + microServices);
+ return microServices;
+ }
+
+ /**
+ * Does a fallback to TCA.
+ *
+ * @return The list of microservices
+ */
+ public static List<BlueprintMicroService> fallbackToOneMicroService() {
+ return Collections.singletonList(
+ new BlueprintMicroService(TCA, "onap.policies.monitoring.cdap.tca.hi.lo.app", "", DEFAULT_VERSION));
+ }
+
+ static String getName(Entry<String, JsonElement> entry) {
+ String microServiceYamlName = entry.getKey();
+ JsonObject ob = entry.getValue().getAsJsonObject();
+ if (ob.has(PROPERTIES)) {
+ JsonObject properties = ob.get(PROPERTIES).getAsJsonObject();
+ if (properties.has(NAME)) {
+ return properties.get(NAME).getAsString();
+ }
+ }
+ return microServiceYamlName;
+ }
+
+ static String getInput(Entry<String, JsonElement> entry) {
+ JsonObject ob = entry.getValue().getAsJsonObject();
+ if (ob.has(RELATIONSHIPS)) {
+ JsonArray relationships = ob.getAsJsonArray(RELATIONSHIPS);
+ for (JsonElement element : relationships) {
+ String target = getTarget(element.getAsJsonObject());
+ if (!target.isEmpty()) {
+ return target;
+ }
+ }
+ }
+ return "";
+ }
+
+ static String findPropertyInRelationshipsArray(String propertyName, JsonArray relationshipsArray,
+ JsonObject blueprintNodeTemplateList, JsonObject blueprintInputList) throws BlueprintParserException {
+ for (JsonElement elem : relationshipsArray) {
+ if (blueprintNodeTemplateList.get(elem.getAsJsonObject().get(TARGET).getAsString()) == null) {
+ throw new BlueprintParserException(
+ "The Target mentioned in the blueprint is not a known entry in the blueprint: "
+ + elem.getAsJsonObject().get(TARGET).getAsString());
+ } else {
+ String property = getPropertyValue(propertyName,
+ new AbstractMap.SimpleEntry<String, JsonElement>(
+ elem.getAsJsonObject().get(TARGET).getAsString(), blueprintNodeTemplateList
+ .get(elem.getAsJsonObject().get(TARGET).getAsString()).getAsJsonObject()),
+ blueprintNodeTemplateList, blueprintInputList);
+ if (!property.isEmpty()) {
+ return property;
+ }
+ }
+ }
+ return "";
+ }
+
+ static String getDirectOrInputPropertyValue(String propertyName, JsonObject blueprintInputList,
+ JsonObject nodeTemplateContent) {
+ JsonObject properties = nodeTemplateContent.get(PROPERTIES).getAsJsonObject();
+ if (properties.has(propertyName)) {
+ if (properties.get(propertyName).isJsonObject()) {
+ // it's a blueprint parameter
+ return blueprintInputList
+ .get(properties.get(propertyName).getAsJsonObject().get(GET_INPUT).getAsString())
+ .getAsJsonObject().get("default").getAsString();
+ } else {
+ // It's a direct value
+ return properties.get(propertyName).getAsString();
+ }
+ }
+ return "";
+ }
+
+ static String getPropertyValue(String propertyName, Entry<String, JsonElement> nodeTemplateEntry,
+ JsonObject blueprintNodeTemplateList, JsonObject blueprintIputList) throws BlueprintParserException {
+ JsonObject nodeTemplateContent = nodeTemplateEntry.getValue().getAsJsonObject();
+ // Search first in this node template
+ if (nodeTemplateContent.has(PROPERTIES)) {
+ String propValue = getDirectOrInputPropertyValue(propertyName, blueprintIputList, nodeTemplateContent);
+ if (!propValue.isBlank()) {
+ return propValue;
+ }
+ }
+ // Or it's may be defined in a relationship
+ if (nodeTemplateContent.has(RELATIONSHIPS)) {
+ return findPropertyInRelationshipsArray(propertyName,
+ nodeTemplateContent.get(RELATIONSHIPS).getAsJsonArray(), blueprintNodeTemplateList,
+ blueprintIputList);
+ }
+ return "";
+ }
+
+ static BlueprintMicroService getNodeRepresentation(Entry<String, JsonElement> nodeTemplateEntry,
+ JsonObject blueprintNodeTemplateList, JsonObject blueprintInputList) throws BlueprintParserException {
+ String modelIdFound = getPropertyValue(POLICY_MODEL_ID, nodeTemplateEntry, blueprintNodeTemplateList,
+ blueprintInputList);
+ String versionFound = getPropertyValue(POLICY_MODEL_VERSION, nodeTemplateEntry, blueprintNodeTemplateList,
+ blueprintInputList);
+ if (modelIdFound.isBlank()) {
+ logger.warn("policy_model_id is not defined for the node template:" + nodeTemplateEntry.getKey());
+ }
+ if (versionFound.isBlank()) {
+ logger.warn("policy_model_version is not defined (setting it to a default value) for the node template:"
+ + nodeTemplateEntry.getKey());
+ }
+ return new BlueprintMicroService(getName(nodeTemplateEntry), modelIdFound, getInput(nodeTemplateEntry),
+ !versionFound.isBlank() ? versionFound : DEFAULT_VERSION);
+ }
+
+ private static String getTarget(JsonObject elementObject) {
+ if (elementObject.has(TYPE) && elementObject.has(TARGET)
+ && elementObject.get(TYPE).getAsString().equals(CLAMP_NODE_RELATIONSHIPS_GETS_INPUT_FROM)) {
+ return elementObject.get(TARGET).getAsString();
+ }
+ return "";
+ }
+
+ private static JsonObject convertToJson(String yamlString) {
+ Map<String, Object> map = new Yaml().load(yamlString);
+ return new Gson().fromJson(new JSONObject(map).toString(), JsonObject.class);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/ChainGenerator.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/ChainGenerator.java
new file mode 100644
index 000000000..2bd259c2b
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/ChainGenerator.java
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.clamp.clds.sdc.controller.installer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class ChainGenerator {
+
+ ChainGenerator() {
+ }
+
+ /**
+ * Get list of microservices chain.
+ *
+ * @param input A set of microservices
+ * @return The list of microservice chained
+ */
+ public List<BlueprintMicroService> getChainOfMicroServices(Set<BlueprintMicroService> input) {
+ LinkedList<BlueprintMicroService> returnList = new LinkedList<>();
+ if (preValidate(input)) {
+ LinkedList<BlueprintMicroService> theList = new LinkedList<>();
+ for (BlueprintMicroService ms : input) {
+ insertNodeTemplateIntoChain(ms, theList);
+ }
+ if (postValidate(theList)) {
+ returnList = theList;
+ }
+ }
+ return returnList;
+ }
+
+ private boolean preValidate(Set<BlueprintMicroService> input) {
+ List<BlueprintMicroService> noInputs = input.stream().filter(ms -> "".equals(ms.getInputFrom()))
+ .collect(Collectors.toList());
+ return noInputs.size() == 1;
+ }
+
+ private boolean postValidate(LinkedList<BlueprintMicroService> microServices) {
+ for (int i = 1; i < microServices.size() - 1; i++) {
+ BlueprintMicroService prev = microServices.get(i - 1);
+ BlueprintMicroService current = microServices.get(i);
+ if (!current.getInputFrom().equals(prev.getName())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void insertNodeTemplateIntoChain(BlueprintMicroService microServicetoInsert,
+ LinkedList<BlueprintMicroService> chainOfMicroServices) {
+ int insertIndex = 0;
+ for (int i = 0; i < chainOfMicroServices.size(); i++) {
+ BlueprintMicroService current = chainOfMicroServices.get(i);
+ if (microServicetoInsert.getName().equals(current.getInputFrom())) {
+ insertIndex = i;
+ break;
+ } else if (current.getName().equals(microServicetoInsert.getInputFrom())) {
+ insertIndex = i + 1;
+ break;
+ }
+ }
+ chainOfMicroServices.add(insertIndex, microServicetoInsert);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java
new file mode 100644
index 000000000..471415a37
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java
@@ -0,0 +1,221 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.sdc.controller.installer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.apache.commons.io.IOUtils;
+import org.codehaus.plexus.util.StringUtils;
+import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.notification.IResourceInstance;
+import org.onap.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.tosca.parser.api.ISdcCsarHelper;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory;
+
+/**
+ * CsarDescriptor that will be used to deploy file in CLAMP file system. Some
+ * methods can also be used to get some data from it.
+ */
+public class CsarHandler {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarHandler.class);
+ private IArtifactInfo artifactElement;
+ private String csarFilePath;
+ private String controllerName;
+ private SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance();
+ private ISdcCsarHelper sdcCsarHelper;
+ private Map<String, BlueprintArtifact> mapOfBlueprints = new HashMap<>();
+ public static final String CSAR_TYPE = "TOSCA_CSAR";
+ public static final String BLUEPRINT_TYPE = "DCAE_INVENTORY_BLUEPRINT";
+ private INotificationData sdcNotification;
+ public static final String RESOURCE_INSTANCE_NAME_PREFIX = "/Artifacts/Resources/";
+ public static final String RESOURCE_INSTANCE_NAME_SUFFIX = "/Deployment/";
+ public static final String POLICY_DEFINITION_NAME_SUFFIX = "Definitions/policies.yml";
+ public static final String DATA_DEFINITION_NAME_SUFFIX = "Definitions/data.yml";
+ public static final String DATA_DEFINITION_KEY = "data_types:";
+
+ /**
+ * Constructor for CsarHandler taking sdc notification in input.
+ */
+ public CsarHandler(INotificationData data, String controller, String clampCsarPath) throws CsarHandlerException {
+ this.sdcNotification = data;
+ this.controllerName = controller;
+ this.artifactElement = searchForUniqueCsar(data);
+ this.csarFilePath = buildFilePathForCsar(artifactElement, clampCsarPath);
+ }
+
+ private String buildFilePathForCsar(IArtifactInfo artifactElement, String clampCsarPath) {
+ return clampCsarPath + "/" + controllerName + "/" + artifactElement.getArtifactName();
+ }
+
+ private IArtifactInfo searchForUniqueCsar(INotificationData notificationData) throws CsarHandlerException {
+ List<IArtifactInfo> serviceArtifacts = notificationData.getServiceArtifacts();
+ for (IArtifactInfo artifact : serviceArtifacts) {
+ if (artifact.getArtifactType().equals(CSAR_TYPE)) {
+ return artifact;
+ }
+ }
+ throw new CsarHandlerException("Unable to find a CSAR in the Sdc Notification");
+ }
+
+ /**
+ * This saves the notification to disk and database.
+ *
+ * @param resultArtifact The artifact to install
+ * @throws SdcArtifactInstallerException In case of issues with the installation
+ * @throws SdcToscaParserException In case of issues with the parsing of
+ * the CSAR
+ */
+ public synchronized void save(IDistributionClientDownloadResult resultArtifact)
+ throws SdcArtifactInstallerException, SdcToscaParserException {
+ try {
+ logger.info("Writing CSAR file to: " + csarFilePath + " UUID " + artifactElement.getArtifactUUID() + ")");
+ Path path = Paths.get(csarFilePath);
+ Files.createDirectories(path.getParent());
+ // Create or replace the file
+ try (OutputStream out = Files.newOutputStream(path)) {
+ out.write(resultArtifact.getArtifactPayload(), 0, resultArtifact.getArtifactPayload().length);
+ }
+ sdcCsarHelper = factory.getSdcCsarHelper(csarFilePath);
+ this.loadDcaeBlueprint();
+ } catch (IOException e) {
+ throw new SdcArtifactInstallerException(
+ "Exception caught when trying to write the CSAR on the file system to " + csarFilePath, e);
+ }
+ }
+
+ private IResourceInstance searchForResourceByInstanceName(String blueprintResourceInstanceName)
+ throws SdcArtifactInstallerException {
+ for (IResourceInstance resource : this.sdcNotification.getResources()) {
+ String filteredString = resource.getResourceInstanceName().replaceAll("-", "");
+ filteredString = filteredString.replaceAll(" ", "");
+ if (filteredString.equalsIgnoreCase(blueprintResourceInstanceName)) {
+ return resource;
+ }
+ }
+ throw new SdcArtifactInstallerException("Error when searching for " + blueprintResourceInstanceName
+ + " as ResourceInstanceName in Sdc notification and did not find it");
+ }
+
+ private void loadDcaeBlueprint() throws IOException, SdcArtifactInstallerException {
+ try (ZipFile zipFile = new ZipFile(csarFilePath)) {
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ if (!entry.isDirectory() && entry.getName().contains(BLUEPRINT_TYPE)) {
+ BlueprintArtifact blueprintArtifact = new BlueprintArtifact();
+ blueprintArtifact.setBlueprintArtifactName(
+ entry.getName().substring(entry.getName().lastIndexOf('/') + 1, entry.getName().length()));
+ blueprintArtifact
+ .setBlueprintInvariantServiceUuid(this.getSdcNotification().getServiceInvariantUUID());
+ try (InputStream stream = zipFile.getInputStream(entry)) {
+ blueprintArtifact.setDcaeBlueprint(IOUtils.toString(stream, StandardCharsets.UTF_8));
+ }
+ blueprintArtifact.setResourceAttached(searchForResourceByInstanceName(entry.getName().substring(
+ entry.getName().indexOf(RESOURCE_INSTANCE_NAME_PREFIX)
+ + RESOURCE_INSTANCE_NAME_PREFIX.length(),
+ entry.getName().indexOf(RESOURCE_INSTANCE_NAME_SUFFIX))));
+ this.mapOfBlueprints.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact);
+ logger.info("Found a blueprint entry in the CSAR " + blueprintArtifact.getBlueprintArtifactName()
+ + " for resource instance Name "
+ + blueprintArtifact.getResourceAttached().getResourceInstanceName());
+ }
+ }
+ logger.info(this.mapOfBlueprints.size() + " blueprint(s) will be converted to closed loop");
+ }
+ }
+
+ public IArtifactInfo getArtifactElement() {
+ return artifactElement;
+ }
+
+ public String getFilePath() {
+ return csarFilePath;
+ }
+
+ public String setFilePath(String newPath) {
+ return csarFilePath = newPath;
+ }
+
+ public synchronized ISdcCsarHelper getSdcCsarHelper() {
+ return sdcCsarHelper;
+ }
+
+ public INotificationData getSdcNotification() {
+ return sdcNotification;
+ }
+
+ public Map<String, BlueprintArtifact> getMapOfBlueprints() {
+ return mapOfBlueprints;
+ }
+
+ /**
+ * Get the whole policy model Yaml. It combines the content of policies.yaml and
+ * data.yaml.
+ *
+ * @return The whole policy model yaml
+ * @throws IOException The IO Exception
+ */
+ public Optional<String> getPolicyModelYaml() throws IOException {
+ String result = null;
+ try (ZipFile zipFile = new ZipFile(csarFilePath)) {
+ ZipEntry entry = zipFile.getEntry(POLICY_DEFINITION_NAME_SUFFIX);
+ if (entry != null) {
+ ZipEntry data = zipFile.getEntry(DATA_DEFINITION_NAME_SUFFIX);
+ if (data != null) {
+ String dataStr = IOUtils.toString(zipFile.getInputStream(data), StandardCharsets.UTF_8);
+ String dataStrWithoutHeader = dataStr.substring(dataStr.indexOf(DATA_DEFINITION_KEY));
+ String policyStr = IOUtils.toString(zipFile.getInputStream(entry), StandardCharsets.UTF_8);
+ StringUtils.chomp(policyStr);
+ result = policyStr.concat(dataStrWithoutHeader);
+ } else {
+ result = IOUtils.toString(zipFile.getInputStream(entry), StandardCharsets.UTF_8);
+ }
+ } else {
+ logger.info("Policy model not found inside the CSAR file: " + csarFilePath);
+ }
+ return Optional.ofNullable(result);
+ }
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/service/CldsHealthcheckService.java b/src/main/java/org/onap/clamp/clds/service/CldsHealthcheckService.java
new file mode 100644
index 000000000..3fceace55
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/service/CldsHealthcheckService.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.service;
+
+import java.util.Date;
+import org.onap.clamp.clds.model.CldsHealthCheck;
+import org.onap.clamp.clds.util.LoggingUtils;
+import org.onap.clamp.clds.util.OnapLogConstants;
+import org.onap.clamp.loop.LoopController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+
+/**
+ * Service to retrieve the Health Check of the clds application.
+ *
+ */
+@Component
+public class CldsHealthcheckService {
+
+ @Autowired
+ private LoopController loopController;
+
+ protected static final Logger logger = LoggerFactory.getLogger(CldsHealthcheckService.class);
+
+ /**
+ * REST service that retrieves clds healthcheck information.
+ *
+ * @return CldsHealthCheck class containing healthcheck info
+ */
+ public CldsHealthCheck gethealthcheck() {
+ CldsHealthCheck cldsHealthCheck = new CldsHealthCheck();
+ Date startTime = new Date();
+ LoggingUtils util = new LoggingUtils(logger);
+ LoggingUtils.setRequestContext("CldsService: GET healthcheck", "Clamp-Health-Check");
+ LoggingUtils.setTimeContext(startTime, new Date());
+ try {
+ loopController.getLoopNames();
+ cldsHealthCheck.setHealthCheckComponent("CLDS-APP");
+ cldsHealthCheck.setHealthCheckStatus("UP");
+ cldsHealthCheck.setDescription("OK");
+ LoggingUtils.setResponseContext("0", "Get healthcheck success",
+ this.getClass().getName());
+ util.exiting(HttpStatus.OK.value(), "Healthcheck success", Level.INFO,
+ OnapLogConstants.ResponseStatus.COMPLETE);
+ } catch (Exception e) {
+ logger.error("CLAMP application Heath check failed", e);
+ LoggingUtils.setResponseContext("999", "Get healthcheck failed",
+ this.getClass().getName());
+ cldsHealthCheck.setHealthCheckComponent("CLDS-APP");
+ cldsHealthCheck.setHealthCheckStatus("DOWN");
+ cldsHealthCheck.setDescription("NOT-OK");
+ util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Healthcheck failed", Level.INFO,
+ OnapLogConstants.ResponseStatus.ERROR);
+ }
+ return cldsHealthCheck;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/JsonEditorSchemaConstants.java b/src/main/java/org/onap/clamp/clds/tosca/JsonEditorSchemaConstants.java
new file mode 100644
index 000000000..e3c661698
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/JsonEditorSchemaConstants.java
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018-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.clamp.clds.tosca;
+
+public class JsonEditorSchemaConstants {
+
+ //Data types in JSON Schema
+ public static final String TYPE_OBJECT = "object";
+ public static final String TYPE_ARRAY = "array";
+ public static final String TYPE_MAP = "map";
+ public static final String TYPE_STRING = "string";
+ public static final String TYPE_INTEGER = "integer";
+ public static final String TYPE_DATE_TIME = "datetime";
+
+ //Key elements in JSON Schema
+ public static final String TYPE = "type";
+ public static final String TITLE = "title";
+ public static final String REQUIRED = "required";
+ public static final String DEFAULT = "default";
+ public static final String ENUM = "enum";
+ public static final String ENUM_TITLES = "enum_titles";
+ public static final String OPTIONS = "options";
+ public static final String FORMAT = "format";
+ public static final String ITEMS = "items";
+ public static final String PROPERTIES = "properties";
+ public static final String PROPERTY_ORDER = "propertyOrder";
+ public static final String VALUES = "values";
+ public static final String HEADER_TEMPLATE = "headerTemplate";
+ public static final String HEADER_TEMPLATE_VALUE = "{{self.name}}";
+
+ public static final String MINIMUM = "minimum";
+ public static final String MAXIMUM = "maximum";
+ public static final String MIN_LENGTH = "minLength";
+ public static final String MAX_LENGTH = "maxLength";
+ public static final String EXCLUSIVE_MINIMUM = "exclusiveMinimum";
+ public static final String EXCLUSIVE_MAXIMUM = "exclusiveMaximum";
+ public static final String MINITEMS = "minItems";
+ public static final String MAXITEMS = "maxItems";
+
+ public static final String CUSTOM_KEY_FORMAT = "format";
+ public static final String CUSTOM_KEY_FORMAT_TABS_TOP = "tabs-top";
+ public static final String CUSTOM_KEY_FORMAT_TABS = "tabs";
+ public static final String CUSTOM_KEY_FORMAT_INPUT = "input";
+ public static final String FORMAT_SELECT = "select";
+ public static final String UNIQUE_ITEMS = "uniqueItems";
+ public static final String TRUE = "true";
+ public static final String QSSCHEMA = "qschema";
+ public static final String TYPE_QBLDR = "qbldr";
+
+ public static final String ID = "id";
+ public static final String LABEL = "label";
+ public static final String OPERATORS = "operators";
+ public static final String FILTERS = "filters";
+
+ public static final String SCHEMA = "schema";
+ public static final String CURRENT_VALUES = "currentValues";
+
+ public static final String PLUGIN = "plugin";
+ public static final String DATE_TIME_PICKER = "datetimepicker";
+ public static final String VALIDATION = "validation";
+ public static final String DATE_TIME_FORMAT = "YYYY/MM/DD HH:mm:ss";
+ public static final String INPUT_EVENT = "input_event";
+ public static final String DP_CHANGE = "dp.change";
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/ToscaSchemaConstants.java b/src/main/java/org/onap/clamp/clds/tosca/ToscaSchemaConstants.java
new file mode 100644
index 000000000..d00c431c8
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/ToscaSchemaConstants.java
@@ -0,0 +1,83 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.tosca;
+
+public class ToscaSchemaConstants {
+
+ // Data types in TOSCA Schema
+ public static final String TYPE_LIST = "list";
+ public static final String TYPE_MAP = "map";
+ public static final String TYPE_STRING = "string";
+ public static final String TYPE_INTEGER = "integer";
+ public static final String TYPE_NUMBER = "number";
+ public static final String TYPE_DATE_TIME = "datetime";
+ public static final String TYPE_FLOAT = "float";
+ public static final String TYPE_BOOLEAN = "boolean";
+ public static final String TYPE_USER_DEFINED = "userDefined";
+
+ // Key elements in Tosca
+ public static final String NODE_TYPES = "policy_types";
+ public static final String DATA_TYPES = "data_types";
+ public static final String TYPE = "type";
+ public static final String DESCRIPTION = "description";
+ public static final String DEFAULT = "default";
+ public static final String PROPERTIES = "properties";
+ public static final String REQUIRED = "required";
+ public static final String ENTRY_SCHEMA = "entry_schema";
+
+ public static final String METADATA = "metadata";
+ public static final String METADATA_POLICY_MODEL_TYPE = "policy_model_type";
+ public static final String METADATA_ACRONYM = "acronym";
+ public static final String METADATA_ELEMENT_NAME = "element_name";
+ public static final String METADATA_HEADER_TEMPLATE = "header_template";
+ public static final String METADATA_CLAMP_POSSIBLE_VALUES = "clamp_possible_values";
+
+ // Constraints
+ public static final String CONSTRAINTS = "constraints";
+ public static final String VALID_VALUES = "valid_values";
+ public static final String EQUAL = "equal";
+ public static final String GREATER_THAN = "greater_than";
+ public static final String GREATER_OR_EQUAL = "greater_or_equal";
+ public static final String LESS_THAN = "less_than";
+ public static final String LESS_OR_EQUAL = "less_or_equal";
+ public static final String IN_RANGE = "in_range";
+ public static final String LENGTH = "length";
+ public static final String MIN_LENGTH = "min_length";
+ public static final String MAX_LENGTH = "max_length";
+ public static final String PATTERN = "pattern";
+
+ // Prefix for policy nodes
+ public static final String POLICY_NODE = "onap.policies.";
+
+ // Prefix for data nodes
+ public static final String POLICY_DATA = "onap.datatypes.";
+
+ // Prefix for dictionary elements
+ public static final String DICTIONARY = "Dictionary:";
+
+ // Custom Elements that must exist in the Tosca models
+ public static final String NAME = "name";
+ public static final String CONTEXT = "context";
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertor.java b/src/main/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertor.java
new file mode 100644
index 000000000..45bb87ed8
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertor.java
@@ -0,0 +1,780 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.tosca;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.tosca.Dictionary;
+import org.onap.clamp.tosca.DictionaryElement;
+import org.onap.clamp.tosca.DictionaryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * Tosca Model Yaml parser and convertor to JSON Schema consumable for JSON
+ * Editor.
+ *
+ */
+@Component
+public class ToscaYamlToJsonConvertor {
+
+ @Autowired
+ private DictionaryService dictionaryService;
+
+ @Autowired
+ private ClampProperties refProp;
+
+ private int simpleTypeOrder = 1000;
+ private int complexTypeOrder = 10000;
+ private int complexSimpleTypeOrder = 1;
+
+ private int incrementSimpleTypeOrder() {
+ return simpleTypeOrder++;
+ }
+
+ private int incrementComplexTypeOrder() {
+ return complexTypeOrder = complexTypeOrder + 10000;
+ }
+
+ private int incrementComplexSimpleTypeOrder() {
+ complexSimpleTypeOrder++;
+ return complexTypeOrder + complexSimpleTypeOrder;
+ }
+
+ /**
+ * Parses Tosca YAML string and Converts to JsonObject.
+ *
+ * @param yamlString YAML string
+ * @return JsonObject
+ */
+ public JsonObject validateAndConvertToJson(String yamlString) {
+
+ Yaml yaml = new Yaml();
+ LinkedHashMap<String, Object> loadedYaml = yaml.load(yamlString);
+ if (loadedYaml == null) {
+ return null;
+ }
+
+ JSONObject jsonObject = new JSONObject(loadedYaml);
+ return new Gson().fromJson(jsonObject.toString(), JsonObject.class);
+ }
+
+ /**
+ * return the values by looking up the key in the Toscsa JSON object.
+ *
+ * @param obj Tosca Json Object
+ * @param key the parameter key to look up
+ * @return the value for the provided key
+ */
+ public String getValueFromMetadata(JsonObject obj, String key) {
+ JsonElement jsonElement = obj.get(ToscaSchemaConstants.NODE_TYPES);
+ if (jsonElement.isJsonObject()) {
+ Iterator<Entry<String, JsonElement>> itr =
+ jsonElement.getAsJsonObject().entrySet().iterator();
+ while (itr.hasNext()) {
+ Entry<String, JsonElement> entry = itr.next();
+ if (entry.getValue() != null && entry.getValue().isJsonObject()
+ && entry.getValue().getAsJsonObject().has(ToscaSchemaConstants.METADATA)) {
+ JsonObject metadatas = entry.getValue().getAsJsonObject()
+ .get(ToscaSchemaConstants.METADATA).getAsJsonObject();
+ if (metadatas.has(key)) {
+ return metadatas.get(key).getAsString();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Parses Tosca YAML string.
+ *
+ * @param yamlString YAML string
+ * @param modelTypeToUse The model type that must be used to obtain the Json
+ * Schema
+ * @return JSON string
+ */
+ public String parseToscaYaml(String yamlString, String modelTypeToUse) {
+
+ Yaml yaml = new Yaml();
+ LinkedHashMap<String, Object> loadedYaml = yaml.load(yamlString);
+ if (loadedYaml == null) {
+ return "";
+ }
+ LinkedHashMap<String, Object> nodeTypes = new LinkedHashMap<>();
+ LinkedHashMap<String, Object> dataNodes = new LinkedHashMap<>();
+ JSONObject jsonParentObject = new JSONObject();
+ JSONObject jsonTempObject = new JSONObject();
+ parseNodeAndDataType(loadedYaml, nodeTypes, dataNodes);
+ populateJsonEditorObject(loadedYaml, nodeTypes, dataNodes, jsonParentObject, jsonTempObject,
+ modelTypeToUse);
+
+ String headerTemplate = getValueFromMetadata(validateAndConvertToJson(yamlString),
+ ToscaSchemaConstants.METADATA_HEADER_TEMPLATE);
+ if (headerTemplate != null) {
+ jsonParentObject.put(JsonEditorSchemaConstants.HEADER_TEMPLATE,
+ JsonEditorSchemaConstants.HEADER_TEMPLATE_VALUE);
+ }
+ if (jsonTempObject.length() > 0) {
+ jsonParentObject = jsonTempObject;
+ }
+ JSONObject jsonEditorObject = new JSONObject();
+ jsonEditorObject.put(JsonEditorSchemaConstants.SCHEMA, jsonParentObject);
+ return jsonEditorObject.toString();
+ }
+
+ // Parse node_type and data_type
+ @SuppressWarnings("unchecked")
+ private void parseNodeAndDataType(LinkedHashMap<String, Object> map,
+ LinkedHashMap<String, Object> nodeTypes, LinkedHashMap<String, Object> dataNodes) {
+ map.entrySet().stream().forEach(n -> {
+ if (n.getKey().contains(ToscaSchemaConstants.NODE_TYPES)
+ && n.getValue() instanceof Map) {
+ parseNodeAndDataType((LinkedHashMap<String, Object>) n.getValue(), nodeTypes,
+ dataNodes);
+ } else if (n.getKey().contains(ToscaSchemaConstants.DATA_TYPES)
+ && n.getValue() instanceof Map) {
+ parseNodeAndDataType((LinkedHashMap<String, Object>) n.getValue(), nodeTypes,
+ dataNodes);
+ } else if (n.getKey().contains(ToscaSchemaConstants.POLICY_NODE)) {
+ nodeTypes.put(n.getKey(), n.getValue());
+ } else if (n.getKey().contains(ToscaSchemaConstants.POLICY_DATA)) {
+ dataNodes.put(n.getKey(), n.getValue());
+ }
+ });
+ }
+
+ @SuppressWarnings("unchecked")
+ private void populateJsonEditorObject(LinkedHashMap<String, Object> map,
+ LinkedHashMap<String, Object> nodeTypes, LinkedHashMap<String, Object> dataNodes,
+ JSONObject jsonParentObject, JSONObject jsonTempObject, String modelTypeToUse) {
+
+ Map<String, JSONObject> jsonEntrySchema = new HashMap<>();
+ jsonParentObject.put(JsonEditorSchemaConstants.TYPE, JsonEditorSchemaConstants.TYPE_OBJECT);
+ if (nodeTypes.get(modelTypeToUse) instanceof Map) {
+ ((LinkedHashMap<String, Object>) nodeTypes.get(modelTypeToUse)).entrySet()
+ .forEach(ntElement -> {
+ if (ntElement.getKey().equalsIgnoreCase(ToscaSchemaConstants.PROPERTIES)) {
+ JSONArray rootNodeArray = new JSONArray();
+ if (ntElement.getValue() instanceof Map) {
+ ((LinkedHashMap<String, Object>) ntElement.getValue()).entrySet()
+ .forEach((ntPropertiesElement) -> {
+ boolean isListNode = false;
+ parseDescription(
+ (LinkedHashMap<String, Object>) ntPropertiesElement
+ .getValue(),
+ jsonParentObject);
+ LinkedHashMap<String, Object> parentPropertiesMap =
+ (LinkedHashMap<String, Object>) ntPropertiesElement
+ .getValue();
+ if (parentPropertiesMap.containsKey(ToscaSchemaConstants.TYPE)
+ && ((String) parentPropertiesMap
+ .get(ToscaSchemaConstants.TYPE))
+ .contains(ToscaSchemaConstants.TYPE_MAP)
+ && parentPropertiesMap
+ .containsKey(ToscaSchemaConstants.ENTRY_SCHEMA)) {
+ parentPropertiesMap =
+ (LinkedHashMap<String, Object>) parentPropertiesMap
+ .get(ToscaSchemaConstants.ENTRY_SCHEMA);
+ isListNode = true;
+ }
+ if (parentPropertiesMap.containsKey(ToscaSchemaConstants.TYPE)
+ && ((String) parentPropertiesMap
+ .get(ToscaSchemaConstants.TYPE))
+ .contains(ToscaSchemaConstants.POLICY_DATA)) {
+ ((LinkedHashMap<String, Object>) dataNodes.get(
+ parentPropertiesMap.get(ToscaSchemaConstants.TYPE)))
+ .entrySet().stream().forEach(pmap -> {
+ if (pmap.getKey().equalsIgnoreCase(
+ ToscaSchemaConstants.PROPERTIES)) {
+ parseToscaProperties(
+ ToscaSchemaConstants.POLICY_NODE,
+ (LinkedHashMap<String, Object>) pmap
+ .getValue(),
+ jsonParentObject, rootNodeArray,
+ jsonEntrySchema, dataNodes,
+ incrementSimpleTypeOrder());
+ }
+ });
+ }
+ if (isListNode) {
+ jsonTempObject.put(JsonEditorSchemaConstants.TYPE,
+ JsonEditorSchemaConstants.TYPE_ARRAY);
+ parseDescription(
+ (LinkedHashMap<String, Object>) ntPropertiesElement
+ .getValue(),
+ jsonTempObject);
+ jsonTempObject.put(JsonEditorSchemaConstants.ITEMS,
+ jsonParentObject);
+ jsonTempObject.put(JsonEditorSchemaConstants.FORMAT,
+ JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT_TABS);
+ jsonTempObject.put(JsonEditorSchemaConstants.UNIQUE_ITEMS,
+ JsonEditorSchemaConstants.TRUE);
+ }
+ });
+ }
+ }
+ });
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void parseToscaProperties(String parentKey, LinkedHashMap<String, Object> propertiesMap,
+ JSONObject jsonDataNode, JSONArray array, Map<String, JSONObject> jsonEntrySchema,
+ LinkedHashMap<String, Object> dataNodes, final int order) {
+ JSONObject jsonPropertyNode = new JSONObject();
+ propertiesMap.entrySet().stream().forEach(p -> {
+ // Populate JSON Array for "required" key
+
+ if (p.getValue() instanceof Map) {
+ LinkedHashMap<String, Object> nodeMap =
+ (LinkedHashMap<String, Object>) p.getValue();
+ if (nodeMap.containsKey(ToscaSchemaConstants.REQUIRED)
+ && ((boolean) nodeMap.get(ToscaSchemaConstants.REQUIRED))) {
+ array.put(p.getKey());
+ }
+ // if(nodeMap.containsKey(ToscaSchemaConstants.CONSTRAINTS))
+ parseToscaChildNodeMap(p.getKey(), nodeMap, jsonPropertyNode, jsonEntrySchema,
+ dataNodes, array, incrementSimpleTypeOrder());
+ }
+ });
+ jsonDataNode.put(JsonEditorSchemaConstants.REQUIRED, array);
+ jsonDataNode.put(JsonEditorSchemaConstants.PROPERTIES, jsonPropertyNode);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void parseToscaPropertiesForType(String parentKey,
+ LinkedHashMap<String, Object> propertiesMap, JSONObject jsonDataNode, JSONArray array,
+ Map<String, JSONObject> jsonEntrySchema, LinkedHashMap<String, Object> dataNodes,
+ boolean isType, int order) {
+ JSONObject jsonPropertyNode = new JSONObject();
+
+ propertiesMap.entrySet().stream().forEach(p -> {
+ // array.put(p.getKey());
+ boolean overWriteArray = false;
+ if (p.getValue() instanceof Map) {
+ LinkedHashMap<String, Object> nodeMap =
+ (LinkedHashMap<String, Object>) p.getValue();
+ if (!(parentKey.contains(ToscaSchemaConstants.ENTRY_SCHEMA)
+ || parentKey.contains(ToscaSchemaConstants.POLICY_NODE))
+ && nodeMap.containsKey(ToscaSchemaConstants.TYPE)
+ && (((String) nodeMap.get(ToscaSchemaConstants.TYPE))
+ .contains(ToscaSchemaConstants.POLICY_DATA))) {
+ overWriteArray = true;
+ }
+ if (nodeMap.containsKey(ToscaSchemaConstants.REQUIRED)
+ && ((boolean) nodeMap.get(ToscaSchemaConstants.REQUIRED))) {
+ array.put(p.getKey());
+ }
+ parseToscaChildNodeMap(p.getKey(), nodeMap, jsonPropertyNode, jsonEntrySchema,
+ dataNodes, array, order);
+ }
+ });
+ jsonDataNode.put(JsonEditorSchemaConstants.REQUIRED, array);
+ jsonDataNode.put(JsonEditorSchemaConstants.PROPERTIES, jsonPropertyNode);
+ }
+
+ private void parseToscaChildNodeMap(String childObjectKey,
+ LinkedHashMap<String, Object> childNodeMap, JSONObject jsonPropertyNode,
+ Map<String, JSONObject> jsonEntrySchema, LinkedHashMap<String, Object> dataNodes,
+ JSONArray array, int order) {
+ JSONObject childObject = new JSONObject();
+ // JSONArray childArray = new JSONArray();
+ parseDescription(childNodeMap, childObject);
+ parseTypes(childObjectKey, childNodeMap, childObject, jsonEntrySchema, dataNodes, array,
+ order);
+ parseConstraints(childNodeMap, childObject);
+ parseMetadataPossibleValues(childNodeMap, childObject);
+ parseEntrySchema(childNodeMap, childObject, jsonPropertyNode, jsonEntrySchema, dataNodes);
+
+ jsonPropertyNode.put(childObjectKey, childObject);
+ order++;
+
+ }
+
+ private void parseEntrySchema(LinkedHashMap<String, Object> childNodeMap,
+ JSONObject childObject, JSONObject jsonPropertyNode,
+ Map<String, JSONObject> jsonEntrySchema, LinkedHashMap<String, Object> dataNodes) {
+ if (childNodeMap.get(ToscaSchemaConstants.ENTRY_SCHEMA) != null) {
+ if (childNodeMap.get(ToscaSchemaConstants.ENTRY_SCHEMA) instanceof Map) {
+ LinkedHashMap<String, Object> entrySchemaMap =
+ (LinkedHashMap<String, Object>) childNodeMap
+ .get(ToscaSchemaConstants.ENTRY_SCHEMA);
+ entrySchemaMap.entrySet().stream().forEach(entry -> {
+ if (entry.getKey().equalsIgnoreCase(ToscaSchemaConstants.TYPE)
+ && entry.getValue() != null) {
+ String entrySchemaType = (String) entry.getValue();
+ if (entrySchemaType.contains(ToscaSchemaConstants.POLICY_DATA)) {
+ JSONArray array = new JSONArray();
+ if (jsonEntrySchema.get(entrySchemaType) != null) {
+ // Already traversed
+ JSONObject entrySchemaObject = jsonEntrySchema.get(entrySchemaType);
+ attachEntrySchemaJsonObject(childObject, entrySchemaObject,
+ JsonEditorSchemaConstants.TYPE_OBJECT);
+ } else if (dataNodes.containsKey(entrySchemaType)) {
+
+ JSONObject entrySchemaObject = new JSONObject();
+ // Need to traverse
+ ((LinkedHashMap<String, Object>) dataNodes.get(entrySchemaType))
+ .entrySet().stream().forEach(pmap -> {
+ if (pmap.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.PROPERTIES)) {
+ parseToscaProperties(ToscaSchemaConstants.ENTRY_SCHEMA,
+ (LinkedHashMap<String, Object>) pmap.getValue(),
+ entrySchemaObject, array, jsonEntrySchema,
+ dataNodes, incrementComplexTypeOrder());
+ jsonEntrySchema.put(entrySchemaType, entrySchemaObject);
+ dataNodes.remove(entrySchemaType);
+ attachEntrySchemaJsonObject(childObject,
+ entrySchemaObject,
+ JsonEditorSchemaConstants.TYPE_OBJECT);
+ }
+
+ });
+ }
+ } else if (entrySchemaType
+ .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)
+ || entrySchemaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)
+ || entrySchemaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_FLOAT)) {
+ JSONObject entrySchemaObject = new JSONObject();
+ parseConstraints(entrySchemaMap, entrySchemaObject);
+ parseMetadataPossibleValues(entrySchemaMap, entrySchemaObject);
+ String jsontype = JsonEditorSchemaConstants.TYPE_STRING;
+ if (entrySchemaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)
+ || entrySchemaType
+ .equalsIgnoreCase(ToscaSchemaConstants.TYPE_FLOAT)) {
+ jsontype = JsonEditorSchemaConstants.TYPE_INTEGER;
+ }
+ if (childNodeMap.get(ToscaSchemaConstants.TYPE) != null) {
+ // Only known value of type is String for now
+ if (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String) {
+ String typeValue =
+ (String) childNodeMap.get(ToscaSchemaConstants.TYPE);
+ if (typeValue
+ .equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) {
+ // Custom key for JSON Editor and UI rendering
+ childObject.put(JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT,
+ JsonEditorSchemaConstants.FORMAT_SELECT);
+ // childObject.put(JsonEditorSchemaConstants.UNIQUE_ITEMS,
+ // JsonEditorSchemaConstants.TRUE);
+ }
+ }
+ }
+ attachEntrySchemaJsonObject(childObject, entrySchemaObject, jsontype);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ private void attachEntrySchemaJsonObject(JSONObject childObject, JSONObject entrySchemaObject,
+ String dataType) {
+
+ entrySchemaObject.put(JsonEditorSchemaConstants.TYPE, dataType);
+ childObject.put(JsonEditorSchemaConstants.ITEMS, entrySchemaObject);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void attachTypeJsonObject(JSONObject childObject, JSONObject typeObject) {
+ Iterator<String> keys = typeObject.keys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ childObject.put(key, typeObject.get(key));
+ }
+ }
+
+ /*
+ * private String parseKey(String toscaKey, String lookupString) { return
+ * toscaKey.substring(toscaKey.indexOf(lookupString) + lookupString.length(),
+ * toscaKey.length()); }
+ */
+
+ private void parseDescription(LinkedHashMap<String, Object> childNodeMap,
+ JSONObject childObject) {
+ if (childNodeMap.get(ToscaSchemaConstants.DESCRIPTION) != null) {
+ childObject.put(JsonEditorSchemaConstants.TITLE,
+ childNodeMap.get(ToscaSchemaConstants.DESCRIPTION));
+ }
+ }
+
+ private void parseTypes(String childObjectKey, LinkedHashMap<String, Object> childNodeMap,
+ JSONObject childObject, Map<String, JSONObject> jsonEntrySchema,
+ LinkedHashMap<String, Object> dataNodes, JSONArray array, int order) {
+ if (childNodeMap.get(ToscaSchemaConstants.TYPE) != null) {
+ // Only known value of type is String for now
+ if (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String) {
+ childObject.put(JsonEditorSchemaConstants.PROPERTY_ORDER, order);
+ String typeValue = (String) childNodeMap.get(ToscaSchemaConstants.TYPE);
+ if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)) {
+ childObject.put(JsonEditorSchemaConstants.TYPE,
+ JsonEditorSchemaConstants.TYPE_INTEGER);
+
+ } else if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_FLOAT)) {
+ childObject.put(JsonEditorSchemaConstants.TYPE,
+ JsonEditorSchemaConstants.TYPE_INTEGER);
+ } else if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) {
+ childObject.put(JsonEditorSchemaConstants.TYPE,
+ JsonEditorSchemaConstants.TYPE_ARRAY);
+ // Custom key for JSON Editor and UI rendering
+ childObject.put(JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT,
+ JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT_TABS_TOP);
+ childObject.put(JsonEditorSchemaConstants.UNIQUE_ITEMS,
+ JsonEditorSchemaConstants.TRUE);
+ } else if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_MAP)) {
+ childObject.put(JsonEditorSchemaConstants.TYPE,
+ JsonEditorSchemaConstants.TYPE_OBJECT);
+ } else if (typeValue.contains(ToscaSchemaConstants.POLICY_DATA)) {
+ JSONArray childArray = new JSONArray();
+
+ if (jsonEntrySchema.get(typeValue) != null) {
+ // Already traversed
+ JSONObject entrySchemaObject = jsonEntrySchema.get(typeValue);
+ attachTypeJsonObject(childObject, entrySchemaObject);
+ } else if (dataNodes.containsKey(typeValue)) {
+ JSONObject entrySchemaObject = new JSONObject();
+ // Need to traverse
+ JSONArray jsonArray = new JSONArray();
+ ((LinkedHashMap<String, Object>) dataNodes.get(typeValue)).entrySet()
+ .stream().forEach(pmap -> {
+ if (pmap.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.PROPERTIES)) {
+ parseToscaPropertiesForType(childObjectKey,
+ (LinkedHashMap<String, Object>) pmap.getValue(),
+ entrySchemaObject, childArray, jsonEntrySchema, dataNodes,
+ true, incrementComplexSimpleTypeOrder());
+ jsonEntrySchema.put(typeValue, entrySchemaObject);
+ dataNodes.remove(typeValue);
+ attachTypeJsonObject(childObject, entrySchemaObject);
+ }
+ });
+ }
+ } else {
+ childObject.put(JsonEditorSchemaConstants.TYPE,
+ JsonEditorSchemaConstants.TYPE_STRING);
+ }
+ }
+ if (childNodeMap.get(ToscaSchemaConstants.DEFAULT) != null) {
+ childObject.put(JsonEditorSchemaConstants.DEFAULT,
+ childNodeMap.get(ToscaSchemaConstants.DEFAULT));
+ }
+ }
+ }
+
+ private void parseConstraints(LinkedHashMap<String, Object> childNodeMap,
+ JSONObject childObject) {
+ if (childNodeMap.containsKey(ToscaSchemaConstants.CONSTRAINTS)
+ && childNodeMap.get(ToscaSchemaConstants.CONSTRAINTS) != null) {
+ List<LinkedHashMap<String, Object>> constraintsList =
+ (List<LinkedHashMap<String, Object>>) childNodeMap
+ .get(ToscaSchemaConstants.CONSTRAINTS);
+ constraintsList.stream().forEach(c -> {
+ if (c instanceof Map) {
+ c.entrySet().stream().forEach(constraint -> {
+ if (constraint.getKey().equalsIgnoreCase(ToscaSchemaConstants.MIN_LENGTH)
+ || constraint.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.GREATER_OR_EQUAL)) {
+ // For String min_lenghth is minimum length whereas for number, it will
+ // be
+ // minimum or greater than to the defined value
+ if (childNodeMap.containsKey(ToscaSchemaConstants.TYPE)
+ && (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String)
+ && ((String) childNodeMap.get(ToscaSchemaConstants.TYPE))
+ .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) {
+ childObject.put(JsonEditorSchemaConstants.MIN_LENGTH,
+ constraint.getValue());
+ } else {
+ childObject.put(JsonEditorSchemaConstants.MINIMUM,
+ constraint.getValue());
+ }
+ } else if (constraint.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.MAX_LENGTH)
+ || constraint.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.LESS_OR_EQUAL)) {
+ // For String max_lenghth is maximum length whereas for number, it will
+ // be
+ // maximum or less than the defined value
+ if (childNodeMap.containsKey(ToscaSchemaConstants.TYPE)
+ && (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String)
+ && ((String) childNodeMap.get(ToscaSchemaConstants.TYPE))
+ .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) {
+ childObject.put(JsonEditorSchemaConstants.MAX_LENGTH,
+ constraint.getValue());
+ } else {
+ childObject.put(JsonEditorSchemaConstants.MAXIMUM,
+ constraint.getValue());
+ }
+ } else if (constraint.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.LESS_THAN)) {
+ childObject.put(JsonEditorSchemaConstants.EXCLUSIVE_MAXIMUM,
+ constraint.getValue());
+ } else if (constraint.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.GREATER_THAN)) {
+ childObject.put(JsonEditorSchemaConstants.EXCLUSIVE_MINIMUM,
+ constraint.getValue());
+ } else if (constraint.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.IN_RANGE)) {
+ if (constraint.getValue() instanceof ArrayList<?>) {
+ if (childNodeMap.containsKey(ToscaSchemaConstants.TYPE)
+ && (childNodeMap
+ .get(ToscaSchemaConstants.TYPE) instanceof String)
+ && ((String) childNodeMap.get(ToscaSchemaConstants.TYPE))
+ .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) {
+ childObject.put(JsonEditorSchemaConstants.MIN_LENGTH,
+ ((ArrayList) constraint.getValue()).get(0));
+ childObject.put(JsonEditorSchemaConstants.MAX_LENGTH,
+ ((ArrayList) constraint.getValue()).get(1));
+ } else {
+ childObject.put(JsonEditorSchemaConstants.MINIMUM,
+ ((ArrayList) constraint.getValue()).get(0));
+ childObject.put(JsonEditorSchemaConstants.MAXIMUM,
+ ((ArrayList) constraint.getValue()).get(1));
+ }
+
+ }
+ } else if (constraint.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.VALID_VALUES)) {
+ JSONArray validValuesArray = new JSONArray();
+
+ if (constraint.getValue() instanceof ArrayList<?>) {
+ boolean processDictionary =
+ ((ArrayList<?>) constraint.getValue()).stream().anyMatch(
+ value -> (value instanceof String && ((String) value)
+ .contains(ToscaSchemaConstants.DICTIONARY)));
+ if (!processDictionary) {
+ ((ArrayList<?>) constraint.getValue()).stream()
+ .forEach(value -> {
+ validValuesArray.put(value);
+ });
+ childObject.put(JsonEditorSchemaConstants.ENUM,
+ validValuesArray);
+ } else {
+ ((ArrayList<?>) constraint.getValue()).stream()
+ .forEach(value -> {
+ if ((value instanceof String && ((String) value)
+ .contains(ToscaSchemaConstants.DICTIONARY))) {
+ processDictionaryElements(childObject,
+ (String) value);
+ }
+
+ });
+
+ }
+ }
+
+ }
+ });
+ }
+ });
+ }
+ }
+
+ private void parseMetadataPossibleValues(LinkedHashMap<String, Object> childNodeMap,
+ JSONObject childObject) {
+ if (childNodeMap.containsKey(ToscaSchemaConstants.METADATA)
+ && childNodeMap.get(ToscaSchemaConstants.METADATA) != null) {
+ LinkedHashMap<String, Object> metadataMap =
+ (LinkedHashMap<String, Object>) childNodeMap.get(ToscaSchemaConstants.METADATA);
+ if (metadataMap instanceof Map) {
+ metadataMap.entrySet().stream().forEach(constraint -> {
+ if (constraint.getKey()
+ .equalsIgnoreCase(ToscaSchemaConstants.METADATA_CLAMP_POSSIBLE_VALUES)) {
+ JSONArray validValuesArray = new JSONArray();
+
+ if (constraint.getValue() instanceof ArrayList<?>) {
+ boolean processDictionary = ((ArrayList<?>) constraint.getValue())
+ .stream().anyMatch(value -> (value instanceof String
+ && ((String) value).contains(ToscaSchemaConstants.DICTIONARY)));
+ if (processDictionary) {
+ ((ArrayList<?>) constraint.getValue()).stream().forEach(value -> {
+ if ((value instanceof String && ((String) value)
+ .contains(ToscaSchemaConstants.DICTIONARY))) {
+ processDictionaryElements(childObject, (String) value);
+ }
+
+ });
+
+ }
+ }
+
+ }
+ });
+ }
+ }
+ }
+
+ private void processDictionaryElements(JSONObject childObject, String dictionaryReference) {
+ if (dictionaryReference.contains("#")) {
+ String[] dictionaryKeyArray = dictionaryReference
+ .substring(dictionaryReference.indexOf(ToscaSchemaConstants.DICTIONARY) + 11,
+ dictionaryReference.length())
+ .split("#");
+ // We support only one # as of now.
+ List<DictionaryElement> cldsDictionaryElements = null;
+ List<DictionaryElement> subDictionaryElements = null;
+ if (dictionaryKeyArray != null && dictionaryKeyArray.length == 2) {
+ cldsDictionaryElements = dictionaryService.getDictionary(dictionaryKeyArray[0])
+ .getDictionaryElements().stream().collect(Collectors.toList());
+ subDictionaryElements = dictionaryService.getDictionary(dictionaryKeyArray[1])
+ .getDictionaryElements().stream().collect(Collectors.toList());
+
+ if (cldsDictionaryElements != null) {
+ List<String> subCldsDictionaryNames = subDictionaryElements.stream()
+ .map(DictionaryElement::getShortName).collect(Collectors.toList());
+ JSONArray jsonArray = new JSONArray();
+
+ Optional.ofNullable(cldsDictionaryElements).get().stream().forEach(c -> {
+ JSONObject jsonObject = new JSONObject();
+ if (c.getSubDictionary() != null) {
+ Dictionary subDictionary =
+ dictionaryService.getDictionary(c.getSubDictionary());
+ if (subDictionary != null
+ && !subDictionary.getDictionaryElements().isEmpty()) {
+
+ jsonObject.put(JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT_INPUT,
+ JsonEditorSchemaConstants.FORMAT_SELECT);
+
+ List<String> shortNames = new ArrayList<>();
+ subDictionary.getDictionaryElements().stream().forEach(c1 -> {
+ shortNames.add(c1.getShortName());
+ });
+ jsonObject.put(JsonEditorSchemaConstants.VALUES, shortNames);
+ }
+ }
+ jsonObject.put(JsonEditorSchemaConstants.TYPE, getJsonType(c.getType()));
+
+ if (c.getType() != null
+ && (c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)
+ || c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_DATE_TIME)
+ || c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_MAP))) {
+ jsonObject.put(JsonEditorSchemaConstants.MIN_LENGTH, 1);
+
+ if (c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_DATE_TIME)) {
+ jsonObject.put(JsonEditorSchemaConstants.PLUGIN,
+ JsonEditorSchemaConstants.DATE_TIME_PICKER);
+ jsonObject.put(JsonEditorSchemaConstants.INPUT_EVENT,
+ JsonEditorSchemaConstants.DP_CHANGE);
+ JSONObject formatJsonObject = new JSONObject();
+ formatJsonObject.put(JsonEditorSchemaConstants.FORMAT,
+ JsonEditorSchemaConstants.DATE_TIME_FORMAT);
+ jsonObject.put(JsonEditorSchemaConstants.VALIDATION,
+ formatJsonObject);
+ }
+ }
+
+ jsonObject.put(JsonEditorSchemaConstants.ID, c.getName());
+ jsonObject.put(JsonEditorSchemaConstants.LABEL, c.getShortName());
+ jsonObject.put(JsonEditorSchemaConstants.OPERATORS, subCldsDictionaryNames);
+ jsonArray.put(jsonObject);
+ });;
+ JSONObject filterObject = new JSONObject();
+ filterObject.put(JsonEditorSchemaConstants.FILTERS, jsonArray);
+
+ childObject.put(JsonEditorSchemaConstants.TYPE,
+ JsonEditorSchemaConstants.TYPE_QBLDR);
+ // TO invoke validation on such parameters
+ childObject.put(JsonEditorSchemaConstants.MIN_LENGTH, 1);
+ childObject.put(JsonEditorSchemaConstants.QSSCHEMA, filterObject);
+
+ }
+ }
+ } else {
+ String dictionaryKey = dictionaryReference.substring(
+ dictionaryReference.indexOf(ToscaSchemaConstants.DICTIONARY) + 11,
+ dictionaryReference.length());
+
+ if (dictionaryKey != null) {
+ if (dictionaryKey.contains(ToscaSchemaConstants.TYPE_USER_DEFINED)) {
+ childObject.put(JsonEditorSchemaConstants.ENUM, new ArrayList<>());
+ // Add Enum titles for generated translated values during
+ // JSON instance generation
+ JSONObject enumTitles = new JSONObject();
+ enumTitles.put(JsonEditorSchemaConstants.ENUM_TITLES, new ArrayList<>());
+ childObject.put(JsonEditorSchemaConstants.OPTIONS, enumTitles);
+ } else {
+ List<DictionaryElement> cldsDictionaryElements =
+ dictionaryService.getDictionary(dictionaryKey).getDictionaryElements()
+ .stream().collect(Collectors.toList());
+ if (cldsDictionaryElements != null) {
+ List<String> cldsDictionaryNames = new ArrayList<>();
+ List<String> cldsDictionaryFullNames = new ArrayList<>();
+ cldsDictionaryElements.stream().forEach(c -> {
+ // Json type will be translated before Policy creation
+ if (c.getType() != null && !c.getType().equalsIgnoreCase("json")) {
+ cldsDictionaryFullNames.add(c.getName());
+ }
+ cldsDictionaryNames.add(c.getShortName());
+ });
+
+ if (!cldsDictionaryFullNames.isEmpty()) {
+ childObject.put(JsonEditorSchemaConstants.ENUM,
+ cldsDictionaryFullNames);
+ // Add Enum titles for generated translated values during JSON instance
+ // generation
+ JSONObject enumTitles = new JSONObject();
+ enumTitles.put(JsonEditorSchemaConstants.ENUM_TITLES,
+ cldsDictionaryNames);
+ childObject.put(JsonEditorSchemaConstants.OPTIONS, enumTitles);
+ } else {
+ childObject.put(JsonEditorSchemaConstants.ENUM, cldsDictionaryNames);
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ private String getJsonType(String toscaType) {
+ String jsonType = null;
+ if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)
+ || toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_NUMBER)) {
+ jsonType = JsonEditorSchemaConstants.TYPE_INTEGER;
+ } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_DATE_TIME)) {
+ jsonType = JsonEditorSchemaConstants.TYPE_DATE_TIME;
+ } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) {
+ jsonType = JsonEditorSchemaConstants.TYPE_ARRAY;
+ } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_MAP)) {
+ jsonType = JsonEditorSchemaConstants.TYPE_MAP;
+ } else {
+ jsonType = JsonEditorSchemaConstants.TYPE_STRING;
+ }
+ return jsonType;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java b/src/main/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java
new file mode 100644
index 000000000..5832986a1
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java
@@ -0,0 +1,98 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser;
+import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParserWithDictionarySupport;
+import org.onap.clamp.clds.tosca.update.templates.JsonTemplateManager;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.loop.service.Service;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ToscaConverterWithDictionarySupport {
+
+ private static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(ToscaConverterWithDictionarySupport.class);
+
+ private ClampProperties clampProperties;
+ private ToscaMetadataParser metadataParser;
+
+ /**
+ * Constructor with Spring support.
+ *
+ * @param clampProperties Clamp Spring properties
+ * @param metadataParser Metadata parser
+ */
+ @Autowired
+ public ToscaConverterWithDictionarySupport(ClampProperties clampProperties,
+ ToscaMetadataParserWithDictionarySupport metadataParser) {
+ this.clampProperties = clampProperties;
+ this.metadataParser = metadataParser;
+ }
+
+ /**
+ * This method converts a tosca file to a json schema.
+ * It uses some parameters specified in the application.properties.
+ *
+ * @param toscaFile The tosca file as String
+ * @param policyTypeToDecode The policy type to decode
+ * @param serviceModel The service model associated so that the clamp enrichment could be done if required by
+ * the tosca model
+ * @return A json object being a json schema
+ */
+ public JsonObject convertToscaToJsonSchemaObject(String toscaFile, String policyTypeToDecode,
+ Service serviceModel) {
+ try {
+ return new JsonTemplateManager(toscaFile,
+ clampProperties.getFileContent("tosca.converter.default.datatypes"),
+ clampProperties.getFileContent("tosca.converter.json.schema.templates"))
+ .getJsonSchemaForPolicyType(policyTypeToDecode, Boolean.parseBoolean(clampProperties.getStringValue(
+ "tosca.converter.dictionary.support.enabled")) ? metadataParser : null, serviceModel);
+ } catch (IOException | UnknownComponentException e) {
+ logger.error("Unable to convert the tosca properly, exception caught during the decoding",
+ e);
+ return new JsonObject();
+ }
+ }
+
+ /**
+ * This method converts a tosca file to a json schema.
+ * It uses some parameters specified in the application.properties.
+ *
+ * @param toscaFile The tosca file as String
+ * @param policyTypeToDecode The policy type to decode
+ * @param serviceModel The service Model so that clamp enrichment could be done if required by tosca model
+ * @return A String containing the json schema
+ */
+ public String convertToscaToJsonSchemaString(String toscaFile, String policyTypeToDecode, Service serviceModel) {
+ return JsonUtils.GSON.toJson(this.convertToscaToJsonSchemaObject(toscaFile, policyTypeToDecode, serviceModel));
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/UnknownComponentException.java b/src/main/java/org/onap/clamp/clds/tosca/update/UnknownComponentException.java
new file mode 100644
index 000000000..e30f9158b
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/UnknownComponentException.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update;
+
+public class UnknownComponentException extends Exception {
+ public UnknownComponentException(String nameEntry) {
+ this.getWrongName(nameEntry);
+ }
+
+ public String getWrongName(String nameEntry) {
+ return "Unknown Component: " + nameEntry;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/elements/ArrayField.java b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ArrayField.java
new file mode 100644
index 000000000..83f792f3f
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ArrayField.java
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.elements;
+
+import com.google.gson.JsonArray;
+import java.util.ArrayList;
+
+public class ArrayField {
+
+ private ArrayList<Object> complexFields;
+
+ /**
+ * Constructor from arraryList.
+ *
+ * @param arrayProperties the array properties
+ */
+ public ArrayField(ArrayList<Object> arrayProperties) {
+ this.complexFields = arrayProperties;
+ }
+
+ /**
+ * Each LinkedHashMap is parsed to extract the Array and each of its value. They are casted for the JsonObject.
+ *
+ * @return JsonArray
+ */
+ public JsonArray deploy() {
+
+ JsonArray subPropertyValuesArray = new JsonArray();
+ for (Object arrayElement : complexFields) {
+ //Cast for each Primitive Type
+ String typeValue = arrayElement.getClass().getSimpleName();
+ switch (typeValue) {
+ case "String":
+ subPropertyValuesArray.add((String) arrayElement);
+ break;
+ case "Boolean":
+ subPropertyValuesArray.add((Boolean) arrayElement);
+ break;
+ case "Double":
+ subPropertyValuesArray.add((Number) arrayElement);
+ break;
+ case "Integer":
+ subPropertyValuesArray.add((Number) arrayElement);
+ break;
+ default:
+ break;
+ }
+ }
+ return subPropertyValuesArray;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/elements/Constraint.java b/src/main/java/org/onap/clamp/clds/tosca/update/elements/Constraint.java
new file mode 100644
index 000000000..d6bd355e3
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/elements/Constraint.java
@@ -0,0 +1,222 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.elements;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+import org.onap.clamp.clds.tosca.update.templates.JsonTemplate;
+
+public class Constraint {
+
+ private LinkedHashMap<String, Object> constraints;
+ private JsonTemplate jsonTemplate;
+
+ public Constraint(LinkedHashMap<String, Object> constraints, JsonTemplate jsonTemplate) {
+ this.jsonTemplate = jsonTemplate;
+ this.constraints = constraints;
+ }
+
+ /**
+ * Deploy the linkedhashmap which contains the constraints, to extract them one to one.
+ *
+ * @param jsonSchema The json Schema
+ * @param typeProperty The ype property
+ * @return the json object
+ */
+ public JsonObject deployConstraints(JsonObject jsonSchema, String typeProperty) {
+ for (Entry<String, Object> constraint : constraints.entrySet()) {
+ this.parseConstraint(jsonSchema, constraint.getKey(), constraint.getValue(), typeProperty);
+ }
+ return jsonSchema;
+ }
+
+ /**
+ * Each case of Tosca constraints below parse specifically the field in the JsonObject.
+ *
+ * @param jsonSchema Json Schema
+ * @param nameConstraint Name constraint
+ * @param valueConstraint value constraint
+ * @param typeProperty Type Property
+ */
+ @SuppressWarnings("unchecked")
+ public void parseConstraint(JsonObject jsonSchema, String nameConstraint, Object valueConstraint,
+ String typeProperty) {
+ switch (nameConstraint) {
+ case "equal":
+ checkTemplateField("const", jsonSchema, valueConstraint);
+ break;
+ case "greater_than":
+ checkTemplateField("exclusiveMinimum", jsonSchema, valueConstraint);
+ break;
+ case "greater_or_equal":
+ checkTemplateField("minimum", jsonSchema, valueConstraint);
+ break;
+ case "less_than":
+ checkTemplateField("exclusiveMaximum", jsonSchema, valueConstraint);
+ break;
+ case "less_or_equal":
+ checkTemplateField("maximum", jsonSchema, valueConstraint);
+ break;
+ case "in_range":
+ ArrayList<Integer> limitValues = (ArrayList<Integer>) valueConstraint;
+ checkTemplateField("minimum", jsonSchema, limitValues.get(0));
+ checkTemplateField("maximum", jsonSchema, limitValues.get(1));
+ break;
+ case "pattern":
+ jsonSchema.addProperty(nameConstraint, (String) valueConstraint);
+ break;
+ case "length":
+ this.getSpecificLength(jsonSchema, valueConstraint, typeProperty);
+ break;
+ case "min_length":
+ String[] prefixValues = nameConstraint.split("_");
+ this.getLimitValue(jsonSchema, valueConstraint, typeProperty, prefixValues[0]);
+ break;
+ case "max_length":
+ String[] maxtab = nameConstraint.split("_");
+ this.getLimitValue(jsonSchema, valueConstraint, typeProperty, maxtab[0]);
+ break;
+ default://valid_value
+ this.getValueArray(jsonSchema, valueConstraint, typeProperty);
+ break;
+ }
+
+ }
+
+ /**
+ * To be done.
+ *
+ * @param jsonSchema json schema
+ * @param fieldValue field value
+ * @param typeProperty For the complex components, get a specific number of items/properties
+ */
+ public void getSpecificLength(JsonObject jsonSchema, Object fieldValue, String typeProperty) {
+ switch (typeProperty.toLowerCase()) {
+ case "string":
+ checkTemplateField("minLength", jsonSchema, fieldValue);
+ checkTemplateField("maxLength", jsonSchema, fieldValue);
+ break;
+ case "array":
+ if (fieldValue.equals(1) && jsonTemplate.hasFields("uniqueItems")) {
+ jsonSchema.addProperty("uniqueItems", true);
+ } else {
+ checkTemplateField("minItems", jsonSchema, fieldValue);
+ checkTemplateField("maxItems", jsonSchema, fieldValue);
+ }
+ break;
+ default:// Map && List
+ checkTemplateField("minProperties", jsonSchema, fieldValue);
+ checkTemplateField("maxProperties", jsonSchema, fieldValue);
+ break;
+ }
+
+ }
+
+ /**
+ * To be done.
+ *
+ * @param jsonSchema json schema
+ * @param fieldValue field value
+ * @param typeProperty type property
+ * @param side Get the limits fieldValue for the properties : depend of the type of the component
+ */
+ public void getLimitValue(JsonObject jsonSchema, Object fieldValue, String typeProperty, String side) {
+ switch (typeProperty) {
+ case "string":
+ if (side.equals("min")) {
+ checkTemplateField("minLength", jsonSchema, fieldValue);
+ } else {
+ checkTemplateField("maxLength", jsonSchema, fieldValue);
+ }
+ break;
+ default:// Array
+ if (side.equals("min")) {
+ checkTemplateField("minItems", jsonSchema, fieldValue);
+ } else {
+ checkTemplateField("maxItems", jsonSchema, fieldValue);
+ }
+ break;
+ }
+
+ }
+
+ /**
+ * To be done.
+ *
+ * @param jsonSchema Json schema
+ * @param fieldValue field value
+ * @param typeProperty Get as Enum the valid values for the property
+ */
+ public void getValueArray(JsonObject jsonSchema, Object fieldValue, String typeProperty) {
+ if (jsonTemplate.hasFields("enum")) {
+ JsonArray enumeration = new JsonArray();
+ if (typeProperty.equals("string") || typeProperty.equals("String")) {
+ ArrayList<String> arrayValues = (ArrayList<String>) fieldValue;
+ for (String arrayItem : arrayValues) {
+ enumeration.add(arrayItem);
+ }
+ jsonSchema.add("enum", enumeration);
+ } else {
+ ArrayList<Number> arrayValues = (ArrayList<Number>) fieldValue;
+ for (Number arrayItem : arrayValues) {
+ enumeration.add(arrayItem);
+ }
+ jsonSchema.add("enum", enumeration);
+ }
+ }
+ }
+
+ /**
+ * To be done.
+ *
+ * @param field Field
+ * @param jsonSchema Json schema
+ * @param fieldValue Simple way to avoid code duplication
+ */
+ public void checkTemplateField(String field, JsonObject jsonSchema, Object fieldValue) {
+ if (jsonTemplate.hasFields(field)) {
+ String typeField = fieldValue.getClass().getSimpleName();
+ switch (typeField) {
+ case "String":
+ jsonSchema.addProperty(field, (String) fieldValue);
+ break;
+ case "Integer":
+ jsonSchema.addProperty(field, (Integer) fieldValue);
+ break;
+ case "Number":
+ jsonSchema.addProperty(field, (Number) fieldValue);
+ break;
+ case "Boolean":
+ jsonSchema.addProperty(field, (Boolean) fieldValue);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElement.java b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElement.java
new file mode 100644
index 000000000..9035a5806
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElement.java
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.elements;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+
+public class ToscaElement {
+
+ /**
+ * name parameter is used as "key", in the LinkedHashMap of Components.
+ */
+ private String name;
+ private String derivedFrom;
+ private String version;
+ private String typeVersion;
+ private String description;
+ private LinkedHashMap<String, ToscaElementProperty> properties;
+
+ public ToscaElement() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name name
+ * @param derivedFrom derivedFrom
+ * @param description description
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public ToscaElement(String name, String derivedFrom, String description) {
+ super();
+ this.name = name;
+ this.derivedFrom = derivedFrom;
+ this.description = description;
+ this.properties = new LinkedHashMap();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDerivedFrom() {
+ return derivedFrom;
+ }
+
+ public void setDerivedFrom(String derivedFrom) {
+ this.derivedFrom = derivedFrom;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getTypeVersion() {
+ return typeVersion;
+ }
+
+ public void setTypeVersion(String typeVersion) {
+ this.typeVersion = typeVersion;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public LinkedHashMap<String, ToscaElementProperty> getProperties() {
+ return properties;
+ }
+
+ public void setProperties(LinkedHashMap<String, ToscaElementProperty> properties) {
+ this.properties = properties;
+ }
+
+ public void addProperties(ToscaElementProperty toscaElementProperty) {
+ this.properties.put(toscaElementProperty.getName(), toscaElementProperty);
+ }
+
+ public ArrayList<String> propertiesNames() {
+ return new ArrayList<>(properties.keySet());
+ }
+
+ @Override
+ public String toString() {
+ return name + ": " + description + ", version: " + version + ", nb de properties: " + properties.size()
+ + System.getProperty("line.separator") + propertiesNames();
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElementProperty.java b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElementProperty.java
new file mode 100644
index 000000000..c5ab5a18e
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElementProperty.java
@@ -0,0 +1,135 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.elements;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import org.onap.clamp.clds.tosca.update.templates.JsonTemplate;
+
+public class ToscaElementProperty {
+
+ /**
+ * name parameter is used as "key", in the LinkedHashMap of Components.
+ */
+ private String name;
+ private LinkedHashMap<String, Object> items;
+
+ /**
+ * Constructor.
+ *
+ * @param name the name
+ * @param items the items
+ */
+ public ToscaElementProperty(String name, LinkedHashMap<String, Object> items) {
+ super();
+ this.name = name;
+ this.items = items;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public LinkedHashMap<String, Object> getItems() {
+ return items;
+ }
+
+ public void setItems(LinkedHashMap<String, Object> items) {
+ this.items = items;
+ }
+
+ /**
+ * For each primitive value, requires to get each field Value and cast it and add it in a Json.
+ *
+ * @param fieldsContent field
+ * @param fieldName field
+ * @param value value
+ */
+ public void addFieldToJson(JsonObject fieldsContent, String fieldName, Object value) {
+ if (value != null) {
+ String typeValue = value.getClass().getSimpleName();
+ switch (typeValue) {
+ case "String":
+ fieldsContent.addProperty(fieldName, (String) value);
+ break;
+ case "Boolean":
+ fieldsContent.addProperty(fieldName, (Boolean) value);
+ break;
+ case "Double":
+ fieldsContent.addProperty(fieldName, (Number) value);
+ break;
+ case "Integer":
+ fieldsContent.addProperty(fieldName, (Integer) value);
+ break;
+ default:
+ fieldsContent.add(fieldName, parseArray((ArrayList) value));
+ break;
+ }
+ }
+ }
+
+ /**
+ * If a field value is an Array, create an Instance of ArrayField to insert if in the JsonObject.
+ *
+ * @param arrayProperties array pro
+ * @return a json array
+ */
+ public JsonArray parseArray(ArrayList<Object> arrayProperties) {
+ JsonArray arrayContent = new JsonArray();
+ ArrayList<Object> arrayComponent = new ArrayList<>();
+ for (Object itemArray : arrayProperties) {
+ arrayComponent.add(itemArray);
+ }
+ ArrayField af = new ArrayField(arrayComponent);
+ arrayContent = af.deploy();
+ return arrayContent;
+ }
+
+ /**
+ * Create an instance of Constraint, to extract the values and add it to the Json (according to the type
+ * * of the current property).
+ *
+ * @param json a json
+ * @param constraints constraints
+ * @param jsonTemplate template
+ */
+ @SuppressWarnings("unchecked")
+ public void addConstraintsAsJson(JsonObject json, ArrayList<Object> constraints, JsonTemplate jsonTemplate) {
+ for (Object constraint : constraints) {
+ if (constraint instanceof LinkedHashMap) {
+ LinkedHashMap<String, Object> valueConstraint = (LinkedHashMap<String, Object>) constraint;
+ Constraint constraintParser = new Constraint(valueConstraint, jsonTemplate);
+ constraintParser.deployConstraints(json, (String) getItems().get("type"));
+ }
+ }
+
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java b/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java
new file mode 100644
index 000000000..885e755bd
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.execution;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import org.onap.clamp.clds.tosca.update.execution.cds.ToscaMetadataCdsProcess;
+import org.onap.clamp.clds.tosca.update.execution.target.ToscaMetadataTargetProcess;
+import org.onap.clamp.loop.service.Service;
+import org.onap.clamp.tosca.DictionaryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class is used to execute a code based on a key found in the metadata section.
+ */
+@Component
+public class ToscaMetadataExecutor {
+
+ private static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(ToscaMetadataExecutor.class);
+
+ @Autowired
+ private DictionaryService dictionaryService;
+
+ private Map<String, ToscaMetadataProcess> mapOfProcesses = new HashMap<>();
+
+ /**
+ * This method executes the required process specified in processInfo.
+ *
+ * @param processInfo A String containing the process to execute, like "cds/param1:value1/param2:value2"
+ * @param childObject The jsonObject
+ * @param serviceModel The service model associated to do clamp enrichment
+ */
+ public void executeTheProcess(String processInfo, JsonObject childObject, Service serviceModel) {
+ String[] processParameters = (processInfo + "/ ").split("/");
+ logger.info("Executing the Tosca clamp process " + processParameters[0] + " with parameters "
+ + processParameters[1].trim());
+ mapOfProcesses.get(processParameters[0].trim())
+ .executeProcess(processParameters[1].trim(), childObject, serviceModel);
+ }
+
+ /**
+ * Init method.
+ */
+ @PostConstruct
+ public void init() {
+ mapOfProcesses.put("CDS", new ToscaMetadataCdsProcess());
+ mapOfProcesses.put("CSAR_RESOURCES", new ToscaMetadataTargetProcess());
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java b/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java
new file mode 100644
index 000000000..214eadb03
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.execution;
+
+import com.google.gson.JsonObject;
+import org.onap.clamp.loop.service.Service;
+
+/**
+ * This code is the interface that must be implemented to have a tosca process.
+ */
+public abstract class ToscaMetadataProcess {
+
+ /**
+ * This method add some elements to the JsonObject childObject passed in argument.
+ * The process can take multiple parameters in arguments.
+ *
+ * @param parameters The parameters required by the process
+ * @param childObject The Json Object modified by the current process
+ * @param serviceModel The service model associated to do clamp enrichment
+ */
+ public abstract void executeProcess(String parameters, JsonObject childObject, Service serviceModel);
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java b/src/main/java/org/onap/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java
new file mode 100644
index 000000000..39fa25a2b
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java
@@ -0,0 +1,220 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.execution.cds;
+
+import static org.onap.clamp.clds.tosca.ToscaSchemaConstants.TYPE;
+import static org.onap.clamp.clds.tosca.ToscaSchemaConstants.TYPE_LIST;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.util.Map;
+import java.util.Set;
+import org.onap.clamp.clds.tosca.update.execution.ToscaMetadataProcess;
+import org.onap.clamp.loop.service.Service;
+
+/**
+ * This class is there to add the JsonObject for CDS in the json Schema according to what is found in the Tosca model.
+ */
+public class ToscaMetadataCdsProcess extends ToscaMetadataProcess {
+
+ @Override
+ public void executeProcess(String parameters, JsonObject childObject, Service serviceModel) {
+ switch (parameters) {
+ case "actor":
+ JsonArray jsonArray = new JsonArray();
+ jsonArray.add("CDS");
+ addToJsonArray(childObject, "enum", jsonArray);
+ break;
+ case "payload":
+ generatePayload(childObject, serviceModel);
+ break;
+ case "operation":
+ generateOperation(childObject, serviceModel);
+ break;
+ default:
+ }
+ }
+
+ private static void generatePayload(JsonObject childObject, Service serviceModel) {
+ JsonArray schemaAnyOf = new JsonArray();
+ schemaAnyOf.addAll(createBlankEntry());
+ schemaAnyOf.addAll(generatePayloadPerResource("VF", serviceModel));
+ schemaAnyOf.addAll(generatePayloadPerResource("PNF", serviceModel));
+ addToJsonArray(childObject, "anyOf", schemaAnyOf);
+ }
+
+ private static void generateOperation(JsonObject childObject, Service serviceModel) {
+ generateOperationPerResource(childObject, "VF", serviceModel);
+ generateOperationPerResource(childObject, "PNF", serviceModel);
+ }
+
+ private static void generateOperationPerResource(JsonObject childObject, String resourceName,
+ Service serviceModel) {
+ JsonArray schemaEnum = new JsonArray();
+ JsonArray schemaTitle = new JsonArray();
+ for (Map.Entry<String, JsonElement> entry : serviceModel.getResourceDetails().getAsJsonObject(resourceName)
+ .entrySet()) {
+ JsonObject controllerProperties = entry.getValue().getAsJsonObject()
+ .getAsJsonObject("controllerProperties");
+ if (controllerProperties != null && controllerProperties.getAsJsonObject("workflows") != null) {
+ for (String workflowsEntry : controllerProperties.getAsJsonObject("workflows").keySet()) {
+ schemaEnum.add(workflowsEntry);
+ schemaTitle.add(workflowsEntry + " (CDS operation)");
+ }
+ }
+ }
+ addToJsonArray(childObject, "enum", schemaEnum);
+ if (childObject.get("options") == null) {
+ JsonObject optionsSection = new JsonObject();
+ childObject.add("options", optionsSection);
+ }
+ addToJsonArray(childObject.getAsJsonObject("options"), "enum_titles", schemaTitle);
+
+ }
+
+ private static JsonArray generatePayloadPerResource(String resourceName,
+ Service serviceModel) {
+ JsonArray schemaAnyOf = new JsonArray();
+
+ for (Map.Entry<String, JsonElement> entry : serviceModel.getResourceDetails().getAsJsonObject(resourceName)
+ .entrySet()) {
+ JsonObject controllerProperties = entry.getValue().getAsJsonObject()
+ .getAsJsonObject("controllerProperties");
+ if (controllerProperties != null && controllerProperties.getAsJsonObject("workflows") != null) {
+ for (Map.Entry<String, JsonElement> workflowsEntry : controllerProperties.getAsJsonObject("workflows")
+ .entrySet()) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty("title", workflowsEntry.getKey());
+ obj.add("properties",
+ createInputPropertiesForPayload(workflowsEntry.getValue().getAsJsonObject(),
+ controllerProperties,
+ workflowsEntry.getKey()));
+ schemaAnyOf.add(obj);
+ }
+ }
+ }
+ return schemaAnyOf;
+ }
+
+ private static JsonArray createBlankEntry() {
+ JsonArray result = new JsonArray();
+ JsonObject blankObject = new JsonObject();
+ blankObject.addProperty("title", "User defined");
+ blankObject.add("properties", new JsonObject());
+ result.add(blankObject);
+ return result;
+ }
+
+ private static JsonObject createAnyOfJsonProperty(String name,
+ String defaultValue,
+ boolean readOnlyFlag) {
+ JsonObject result = new JsonObject();
+ result.addProperty("title", name);
+ result.addProperty("type", "string");
+ result.addProperty("default", defaultValue);
+ result.addProperty("readOnly", readOnlyFlag);
+ return result;
+ }
+
+ private static void addToJsonArray(JsonObject childObject, String section, JsonArray value) {
+ if (childObject.getAsJsonArray(section) != null) {
+ childObject.getAsJsonArray(section).addAll(value);
+ } else {
+ childObject.add(section, value);
+ }
+ }
+
+ /**
+ * Returns the properties of payload based on the cds work flows.
+ *
+ * @param workFlow cds work flows to update payload
+ * @param controllerProperties cds properties to get blueprint name and
+ * version
+ * @param workFlowName work flow name
+ * @return returns the properties of payload
+ */
+ public static JsonObject createInputPropertiesForPayload(JsonObject workFlow,
+ JsonObject controllerProperties,
+ String workFlowName) {
+ String artifactName = controllerProperties.get("sdnc_model_name").getAsString();
+ String artifactVersion = controllerProperties.get("sdnc_model_version").getAsString();
+ JsonObject inputs = workFlow.getAsJsonObject("inputs");
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.add("artifact_name", createAnyOfJsonProperty(
+ "artifact name", artifactName, true));
+ jsonObject.add("artifact_version", createAnyOfJsonProperty(
+ "artifact version", artifactVersion, true));
+ jsonObject.add("mode", createAnyOfJsonProperty(
+ "mode", "async", false));
+ jsonObject.add("data", createDataProperty(inputs, workFlowName));
+ return jsonObject;
+ }
+
+ private static JsonObject createDataProperty(JsonObject inputs, String workFlowName) {
+ JsonObject data = new JsonObject();
+ data.addProperty("title", "data");
+ data.addProperty("type", "string");
+ data.addProperty("format", "textarea");
+ JsonObject defaultValue = new JsonObject();
+ addDefaultValueForData(inputs, defaultValue, workFlowName);
+ data.addProperty("default", defaultValue.toString());
+ return data;
+ }
+
+ private static void addDefaultValueForData(JsonObject inputs,
+ JsonObject defaultValue,
+ String workFlowName) {
+ Set<Map.Entry<String, JsonElement>> entrySet = inputs.entrySet();
+ for (Map.Entry<String, JsonElement> entry : entrySet) {
+ String key = entry.getKey();
+ JsonObject inputProperty = inputs.getAsJsonObject(key);
+ if (key.equalsIgnoreCase(workFlowName + "-properties")) {
+ addDefaultValueForData(entry.getValue().getAsJsonObject().get("properties")
+ .getAsJsonObject(), defaultValue, workFlowName);
+ } else if ("object".equalsIgnoreCase(inputProperty.get(TYPE).getAsString())) {
+ JsonObject object = new JsonObject();
+ addDefaultValueForData(entry.getValue().getAsJsonObject().get("properties")
+ .getAsJsonObject(), object, workFlowName);
+ defaultValue.add(entry.getKey(), object);
+ } else if (TYPE_LIST.equalsIgnoreCase(inputProperty.get(TYPE).getAsString())) {
+ defaultValue.add(entry.getKey(), handleListType(entry.getValue().getAsJsonObject(), workFlowName));
+ } else {
+ defaultValue.addProperty(entry.getKey(), "");
+ }
+ }
+ }
+
+ private static JsonArray handleListType(JsonObject inputs,
+ String workFlowName) {
+
+ JsonObject object = new JsonObject();
+ if (inputs.get("properties") != null) {
+ addDefaultValueForData(inputs.get("properties").getAsJsonObject(), object, workFlowName);
+ }
+ JsonArray arr = new JsonArray();
+ arr.add(object);
+ return arr;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/execution/target/ToscaMetadataTargetProcess.java b/src/main/java/org/onap/clamp/clds/tosca/update/execution/target/ToscaMetadataTargetProcess.java
new file mode 100644
index 000000000..8b8fa1784
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/execution/target/ToscaMetadataTargetProcess.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.execution.target;
+
+import com.google.gson.JsonObject;
+import org.onap.clamp.clds.tosca.update.execution.ToscaMetadataProcess;
+import org.onap.clamp.loop.service.Service;
+import org.onap.clamp.policy.operational.OperationalPolicyRepresentationBuilder;
+
+/**
+ * This class is there to add the JsonObject for CDS in the json Schema according to what is found in the Tosca model.
+ */
+public class ToscaMetadataTargetProcess extends ToscaMetadataProcess {
+
+ @Override
+ public void executeProcess(String parameters, JsonObject childObject, Service serviceModel) {
+ childObject.add("anyOf", OperationalPolicyRepresentationBuilder.createAnyOfArray(serviceModel, false));
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java b/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java
new file mode 100644
index 000000000..9721e33d9
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java
@@ -0,0 +1,346 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.parser;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+import org.onap.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser;
+import org.onap.clamp.clds.tosca.update.templates.JsonTemplate;
+import org.onap.clamp.loop.service.Service;
+
+public class ToscaConverterToJsonSchema {
+ private LinkedHashMap<String, ToscaElement> components;
+ private LinkedHashMap<String, JsonTemplate> templates;
+
+ private ToscaMetadataParser metadataParser;
+
+ private Service serviceModel;
+
+ /**
+ * Constructor.
+ *
+ * @param toscaElementsMap All the tosca elements found (policy type + data types + native tosca datatypes)
+ * @param jsonSchemaTemplates All Json schema templates to use
+ * @param metadataParser The metadata parser to use for metadata section
+ * @param serviceModel The service model for clamp enrichment
+ */
+ public ToscaConverterToJsonSchema(LinkedHashMap<String, ToscaElement> toscaElementsMap,
+ LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates,
+ ToscaMetadataParser metadataParser, Service serviceModel) {
+ this.components = toscaElementsMap;
+ this.templates = jsonSchemaTemplates;
+ this.metadataParser = metadataParser;
+ this.serviceModel = serviceModel;
+ }
+
+ /**
+ * For a given component, launch process to parse it in Json.
+ *
+ * @param toscaElementKey name components
+ * @return return
+ */
+ public JsonObject getJsonSchemaOfToscaElement(String toscaElementKey) {
+ return this.getFieldAsObject(getToscaElement(toscaElementKey));
+ }
+
+ /**
+ * Return the classical/general fields of the component, & launch the properties deployment.
+ *
+ * @param toscaElement the compo
+ * @return a json object
+ */
+ public JsonObject getFieldAsObject(ToscaElement toscaElement) {
+
+ JsonObject globalFields = new JsonObject();
+ if (templates.get("object").hasFields("title")) {
+ globalFields.addProperty("title", toscaElement.getName());
+ }
+ if (templates.get("object").hasFields("type")) {
+ globalFields.addProperty("type", "object");
+ }
+ if (templates.get("object").hasFields("description")) {
+ if (toscaElement.getDescription() != null) {
+ globalFields.addProperty("description", toscaElement.getDescription());
+ }
+ }
+ if (templates.get("object").hasFields("required")) {
+ globalFields.add("required", this.getRequirements(toscaElement.getName()));
+ }
+ if (templates.get("object").hasFields("properties")) {
+ globalFields.add("properties", this.deploy(toscaElement.getName()));
+ }
+ return globalFields;
+ }
+
+ /**
+ * Get the required properties of the Component, including the parents properties requirements.
+ *
+ * @param nameComponent name component
+ * @return a json array
+ */
+ public JsonArray getRequirements(String nameComponent) {
+ JsonArray requirements = new JsonArray();
+ ToscaElement toParse = components.get(nameComponent);
+ //Check for a father component, and launch the same process
+ if (!toParse.getDerivedFrom().equals("tosca.datatypes.Root")
+ && !toParse.getDerivedFrom().equals("tosca.policies.Root")) {
+ requirements.addAll(getRequirements(toParse.getDerivedFrom()));
+ }
+ //Each property is checked, and add to the requirement array if it's required
+ Collection<ToscaElementProperty> properties = toParse.getProperties().values();
+ for (ToscaElementProperty toscaElementProperty : properties) {
+ if (toscaElementProperty.getItems().containsKey("required")
+ && toscaElementProperty.getItems().get("required").equals(true)) {
+ requirements.add(toscaElementProperty.getName());
+ }
+ }
+ return requirements;
+ }
+
+ /**
+ * The beginning of the recursive process. Get the parents (or not) to launch the same process, and otherwise
+ * deploy and parse the properties.
+ *
+ * @param nameComponent name component
+ * @return a json object
+ */
+ public JsonObject deploy(String nameComponent) {
+ JsonObject jsonSchema = new JsonObject();
+ ToscaElement toParse = components.get(nameComponent);
+ //Check for a father component, and launch the same process
+ if (!toParse.getDerivedFrom().equals("tosca.datatypes.Root")
+ && !toParse.getDerivedFrom().equals("tosca.policies.Root")) {
+ jsonSchema = this.getParent(toParse.getDerivedFrom());
+ }
+ //For each component property, check if its a complex properties (a component) or not. In that case,
+ //launch the analyse of the property.
+ for (Entry<String, ToscaElementProperty> property : toParse.getProperties().entrySet()) {
+ if (getToscaElement((String) property.getValue().getItems().get("type")) != null) {
+ jsonSchema.add(property.getValue().getName(),
+ this.getJsonSchemaOfToscaElement((String) property.getValue().getItems().get("type")));
+ }
+ else {
+ jsonSchema.add(property.getValue().getName(), this.complexParse(property.getValue()));
+ }
+ }
+ return jsonSchema;
+ }
+
+ /**
+ * If a component has a parent, it is deploy in the same way.
+ *
+ * @param nameComponent name component
+ * @return a json object
+ */
+ public JsonObject getParent(String nameComponent) {
+ return deploy(nameComponent);
+ }
+
+ /**
+ * to be done.
+ *
+ * @param toscaElementProperty property
+ * @return a json object
+ */
+ @SuppressWarnings("unchecked")
+ public JsonObject complexParse(ToscaElementProperty toscaElementProperty) {
+ JsonObject propertiesInJson = new JsonObject();
+ JsonTemplate currentPropertyJsonTemplate;
+ String typeProperty = (String) toscaElementProperty.getItems().get("type");
+ if (typeProperty.toLowerCase().equals("list") || typeProperty.toLowerCase().equals("map")) {
+ currentPropertyJsonTemplate = templates.get("object");
+ }
+ else {
+ String propertyType = (String) toscaElementProperty.getItems().get("type");
+ currentPropertyJsonTemplate = templates.get(propertyType.toLowerCase());
+ }
+ //Each "special" field is analysed, and has a specific treatment
+ for (String propertyField : toscaElementProperty.getItems().keySet()) {
+ switch (propertyField) {
+ case "type":
+ if (currentPropertyJsonTemplate.hasFields(propertyField)) {
+ String fieldtype = (String) toscaElementProperty.getItems().get(propertyField);
+ switch (fieldtype.toLowerCase()) {
+ case "list":
+ propertiesInJson.addProperty("type", "array");
+ break;
+ case "map":
+ propertiesInJson.addProperty("type", "object");
+ break;
+ case "scalar-unit.time":
+ case "scalar-unit.frequency":
+ case "scalar-unit.size":
+ propertiesInJson.addProperty("type", "string");
+ break;
+ case "timestamp":
+ propertiesInJson.addProperty("type", "string");
+ propertiesInJson.addProperty("format", "date-time");
+ break;
+ case "float":
+ propertiesInJson.addProperty("type", "number");
+ break;
+ case "range":
+ propertiesInJson.addProperty("type", "integer");
+ if (!checkConstraintPresence(toscaElementProperty, "greater_than")
+ && currentPropertyJsonTemplate.hasFields("exclusiveMinimum")) {
+ propertiesInJson.addProperty("exclusiveMinimum", false);
+ }
+ if (!checkConstraintPresence(toscaElementProperty, "less_than")
+ && currentPropertyJsonTemplate.hasFields("exclusiveMaximum")) {
+ propertiesInJson.addProperty("exclusiveMaximum", false);
+ }
+ break;
+ default:
+ propertiesInJson.addProperty("type", currentPropertyJsonTemplate.getName());
+ break;
+ }
+ }
+ break;
+ case "metadata":
+ if (metadataParser != null) {
+ metadataParser.processAllMetadataElement(toscaElementProperty, serviceModel).entrySet()
+ .forEach((jsonEntry) -> {
+ propertiesInJson.add(jsonEntry.getKey(),
+ jsonEntry.getValue());
+
+ });
+ }
+ break;
+ case "constraints":
+ toscaElementProperty.addConstraintsAsJson(propertiesInJson,
+ (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"),
+ currentPropertyJsonTemplate);
+ break;
+ case "entry_schema":
+ //Here, a way to check if entry is a component (datatype) or a simple string
+ if (getToscaElement(this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema"))
+ != null) {
+ String nameComponent = this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema");
+ ToscaConverterToJsonSchema child = new ToscaConverterToJsonSchema(components, templates,
+ metadataParser, serviceModel);
+ JsonObject propertiesContainer = new JsonObject();
+
+ switch ((String) toscaElementProperty.getItems().get("type")) {
+ case "map": // Get it as an object
+ JsonObject componentAsProperty = child.getJsonSchemaOfToscaElement(nameComponent);
+ propertiesContainer.add(nameComponent, componentAsProperty);
+ if (currentPropertyJsonTemplate.hasFields("properties")) {
+ propertiesInJson.add("properties", propertiesContainer);
+ }
+ break;
+ default://list : get it as an Array
+ JsonObject componentAsItem = child.getJsonSchemaOfToscaElement(nameComponent);
+ if (currentPropertyJsonTemplate.hasFields("properties")) {
+ propertiesInJson.add("items", componentAsItem);
+ propertiesInJson.addProperty("format", "tabs-top");
+ }
+ break;
+ }
+
+ }
+ // Native cases
+ else if (toscaElementProperty.getItems().get("type").equals("list")) {
+ JsonObject itemContainer = new JsonObject();
+ String valueInEntrySchema =
+ this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema");
+ itemContainer.addProperty("type", valueInEntrySchema);
+ propertiesInJson.add("items", itemContainer);
+ propertiesInJson.addProperty("format", "tabs-top");
+ }
+ // MAP Case, for now nothing
+
+ break;
+ default:
+ //Each classical field : type, description, default..
+ if (currentPropertyJsonTemplate.hasFields(propertyField) && !propertyField.equals("required")) {
+ toscaElementProperty.addFieldToJson(propertiesInJson, propertyField,
+ toscaElementProperty.getItems().get(propertyField));
+ }
+ break;
+ }
+ }
+ return propertiesInJson;
+ }
+
+ /**
+ * Look for a matching Component for the name parameter, in the components list.
+ *
+ * @param name the tosca element name to search for
+ * @return a tosca element
+ */
+ public ToscaElement getToscaElement(String name) {
+ ToscaElement correspondingToscaElement = null;
+ if (components == null) {
+ return null;
+ }
+ for (ToscaElement toscaElement : components.values()) {
+ if (toscaElement.getName().equals(name)) {
+ correspondingToscaElement = toscaElement;
+ }
+ }
+ return correspondingToscaElement;
+ }
+
+ /**
+ * Simple method to extract quickly a type field from particular property item.
+ *
+ * @param toscaElementProperty the property
+ * @param fieldName the fieldname
+ * @return a string
+ */
+ @SuppressWarnings("unchecked")
+ public String extractSpecificFieldFromMap(ToscaElementProperty toscaElementProperty, String fieldName) {
+ LinkedHashMap<String, String> entrySchemaFields =
+ (LinkedHashMap<String, String>) toscaElementProperty.getItems().get(fieldName);
+ return entrySchemaFields.get("type");
+ }
+
+ /**
+ * Check if a constraint, for a specific property, is there.
+ *
+ * @param toscaElementProperty property
+ * @param nameConstraint name constraint
+ * @return a flag boolean
+ */
+ public boolean checkConstraintPresence(ToscaElementProperty toscaElementProperty, String nameConstraint) {
+ boolean presentConstraint = false;
+ if (toscaElementProperty.getItems().containsKey("constraints")) {
+ ArrayList<Object> constraints = (ArrayList) toscaElementProperty.getItems().get("constraints");
+ for (Object constraint : constraints) {
+ if (constraint instanceof LinkedHashMap) {
+ if (((LinkedHashMap) constraint).containsKey(nameConstraint)) {
+ presentConstraint = true;
+ }
+ }
+ }
+ }
+ return presentConstraint;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaElementParser.java b/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaElementParser.java
new file mode 100644
index 000000000..090fcfcfa
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaElementParser.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.parser;
+
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+import org.onap.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.yaml.snakeyaml.Yaml;
+
+public class ToscaElementParser {
+ /**
+ * Constructor.
+ */
+ private ToscaElementParser() {
+ }
+
+ private static LinkedHashMap<String, Object> searchAllDataTypesAndPolicyTypes(String toscaYaml) {
+ LinkedHashMap<String, LinkedHashMap<String, Object>> file =
+ (LinkedHashMap<String, LinkedHashMap<String, Object>>) new Yaml().load(toscaYaml);
+ LinkedHashMap<String, Object> allDataTypesFound = file.get("data_types");
+ LinkedHashMap<String, Object> allPolicyTypesFound = file.get("policy_types");
+ LinkedHashMap<String, Object> allItemsFound = new LinkedHashMap<>();
+ // Put the policies and datatypes in the same collection
+ allItemsFound = (allDataTypesFound == null) ? (new LinkedHashMap<>()) : allDataTypesFound;
+ allItemsFound.putAll(allPolicyTypesFound == null ? new LinkedHashMap<>() : allPolicyTypesFound);
+ return allItemsFound;
+ }
+
+ private static LinkedHashMap<String, Object> searchAllNativeToscaDataTypes(String toscaNativeYaml) {
+ return ((LinkedHashMap<String, LinkedHashMap<String, Object>>) new Yaml().load(toscaNativeYaml))
+ .get("data_types");
+ }
+
+ /**
+ * Yaml Parse gets raw policies and datatypes, in different sections : necessary to extract
+ * all entities and put them at the same level.
+ *
+ * @param toscaYaml the tosca model content
+ * @param nativeToscaYaml the tosca native datatype content
+ * @return a map of Tosca Element containing all tosca elements found (policy types and datatypes)
+ */
+ public static LinkedHashMap<String, ToscaElement> searchAllToscaElements(String toscaYaml,
+ String nativeToscaYaml) {
+ LinkedHashMap<String, Object> allItemsFound = searchAllDataTypesAndPolicyTypes(toscaYaml);
+ allItemsFound.putAll(searchAllNativeToscaDataTypes(nativeToscaYaml));
+ return parseAllItemsFound(allItemsFound);
+ }
+
+ /**
+ * With all the component, get as Map, Components and Components properties are created.
+ *
+ * @param allMaps maps
+ */
+ private static LinkedHashMap<String, ToscaElement> parseAllItemsFound(LinkedHashMap<String, Object> allMaps) {
+ LinkedHashMap<String, ToscaElement> allItemsFound = new LinkedHashMap<String, ToscaElement>();
+ //Component creations, from the file maps
+ for (Entry<String, Object> itemToParse : allMaps.entrySet()) {
+ LinkedHashMap<String, Object> componentBody = (LinkedHashMap<String, Object>) itemToParse.getValue();
+ ToscaElement toscaElement =
+ new ToscaElement(itemToParse.getKey(), (String) componentBody.get("derived_from"),
+ (String) componentBody.get("description"));
+ //If policy, version and type_version :
+ if (componentBody.get("type_version") != null) {
+ toscaElement.setVersion((String) componentBody.get("type_version"));
+ toscaElement.setTypeVersion((String) componentBody.get("type_version"));
+ }
+ //Properties creation, from the map
+ if (componentBody.get("properties") != null) {
+ LinkedHashMap<String, Object> properties =
+ (LinkedHashMap<String, Object>) componentBody.get("properties");
+ for (Entry<String, Object> itemToProperty : properties.entrySet()) {
+ ToscaElementProperty toscaElementProperty = new ToscaElementProperty(itemToProperty.getKey(),
+ (LinkedHashMap<String, Object>) itemToProperty.getValue());
+ toscaElement.addProperties(toscaElementProperty);
+ }
+ }
+ allItemsFound.put(toscaElement.getName(), toscaElement);
+ }
+ return allItemsFound;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java b/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java
new file mode 100644
index 000000000..f4a48139e
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.parser.metadata;
+
+import com.google.gson.JsonObject;
+import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.onap.clamp.loop.service.Service;
+
+public interface ToscaMetadataParser {
+ JsonObject processAllMetadataElement(ToscaElementProperty toscaElementProperty, Service serviceModel);
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java b/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java
new file mode 100644
index 000000000..33e084279
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java
@@ -0,0 +1,219 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.parser.metadata;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Optional;
+import org.onap.clamp.clds.tosca.JsonEditorSchemaConstants;
+import org.onap.clamp.clds.tosca.ToscaSchemaConstants;
+import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.onap.clamp.clds.tosca.update.execution.ToscaMetadataExecutor;
+import org.onap.clamp.loop.service.Service;
+import org.onap.clamp.tosca.DictionaryElement;
+import org.onap.clamp.tosca.DictionaryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ToscaMetadataParserWithDictionarySupport implements ToscaMetadataParser {
+
+ @Autowired
+ private ToscaMetadataExecutor toscaMetadataExecutor;
+
+ @Autowired
+ private DictionaryService dictionaryService;
+
+ /**
+ * This method is used to start the processing of the metadata field.
+ *
+ * @param toscaElementProperty The property metadata as Json Object
+ * @return The jsonObject structure that must be added to the json schema
+ */
+ public JsonObject processAllMetadataElement(ToscaElementProperty toscaElementProperty, Service serviceModel) {
+ if (dictionaryService != null) {
+ return parseMetadataPossibleValues(toscaElementProperty.getItems(), dictionaryService, serviceModel,
+ toscaMetadataExecutor);
+ }
+ else {
+ return null;
+ }
+ }
+
+ private static JsonObject parseMetadataPossibleValues(LinkedHashMap<String, Object> childNodeMap,
+ DictionaryService dictionaryService, Service serviceModel,
+ ToscaMetadataExecutor toscaMetadataExecutor) {
+ JsonObject childObject = new JsonObject();
+ if (childNodeMap.containsKey(ToscaSchemaConstants.METADATA)
+ && childNodeMap.get(ToscaSchemaConstants.METADATA) != null) {
+ ((LinkedHashMap<String, Object>) childNodeMap.get(ToscaSchemaConstants.METADATA)).forEach((key,
+ value) -> {
+ if (key.equalsIgnoreCase(ToscaSchemaConstants.METADATA_CLAMP_POSSIBLE_VALUES)) {
+ String[] multipleValues = ((String) value).split(",");
+ for (String multipleValue : multipleValues) {
+ if (multipleValue.contains(ToscaSchemaConstants.DICTIONARY)) {
+ processDictionaryElements(multipleValue, childObject, dictionaryService);
+ }
+ if (multipleValue.contains("ClampExecution:")) {
+ executeClampProcess(multipleValue.replaceAll("ClampExecution:", ""), childObject,
+ serviceModel, toscaMetadataExecutor);
+ }
+ }
+
+ }
+ });
+ }
+ return childObject;
+ }
+
+ private static void executeClampProcess(String processInfo, JsonObject childObject, Service serviceModel,
+ ToscaMetadataExecutor toscaMetadataExecutor) {
+ toscaMetadataExecutor.executeTheProcess(processInfo, childObject, serviceModel);
+ }
+
+ /**
+ * For dictionary with multiple levels (defined by #).
+ *
+ * @param dictionaryKeyArray the array containing the different elements
+ * @param childObject the structure getting the new entries
+ * @param dictionaryService the dictionary service bean
+ */
+ private static void processComplexDictionaryElements(String[] dictionaryKeyArray, JsonObject childObject,
+ DictionaryService dictionaryService) {
+ // We support only one # as of now.
+ List<DictionaryElement> dictionaryElements = null;
+ if (dictionaryKeyArray.length == 2) {
+ dictionaryElements = new ArrayList<>(dictionaryService.getDictionary(dictionaryKeyArray[0])
+ .getDictionaryElements());
+ JsonArray subDictionaryNames = new JsonArray();
+ new ArrayList<DictionaryElement>(dictionaryService.getDictionary(dictionaryKeyArray[1])
+ .getDictionaryElements()).forEach(elem -> subDictionaryNames.add(elem.getShortName()));
+
+ JsonArray jsonArray = new JsonArray();
+
+ Optional.of(dictionaryElements).get().forEach(c -> {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty(JsonEditorSchemaConstants.TYPE, getJsonType(c.getType()));
+ if (c.getType() != null
+ && c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) {
+ jsonObject.addProperty(JsonEditorSchemaConstants.MIN_LENGTH, 1);
+
+ }
+ jsonObject.addProperty(JsonEditorSchemaConstants.ID, c.getName());
+ jsonObject.addProperty(JsonEditorSchemaConstants.LABEL, c.getShortName());
+ jsonObject.add(JsonEditorSchemaConstants.OPERATORS, subDictionaryNames);
+ jsonArray.add(jsonObject);
+ });
+
+ JsonObject filterObject = new JsonObject();
+ filterObject.add(JsonEditorSchemaConstants.FILTERS, jsonArray);
+
+ childObject.addProperty(JsonEditorSchemaConstants.TYPE,
+ JsonEditorSchemaConstants.TYPE_QBLDR);
+ // TO invoke validation on such parameters
+ childObject.addProperty(JsonEditorSchemaConstants.MIN_LENGTH, 1);
+ childObject.add(JsonEditorSchemaConstants.QSSCHEMA, filterObject);
+
+ }
+ }
+
+ /**
+ * For dictionary with single entry.
+ *
+ * @param dictionaryKeyArray the array containing the different elements
+ * @param childObject the structure getting the new entries
+ * @param dictionaryService the dictionary service bean
+ */
+ private static void processSimpleDictionaryElements(String[] dictionaryKeyArray, JsonObject childObject,
+ DictionaryService dictionaryService) {
+ JsonArray dictionaryNames = new JsonArray();
+ JsonArray dictionaryFullNames = new JsonArray();
+ dictionaryService.getDictionary(dictionaryKeyArray[0]).getDictionaryElements().forEach(c -> {
+ // Json type will be translated before Policy creation
+ if (c.getType() != null && !c.getType().equalsIgnoreCase("json")) {
+ dictionaryFullNames.add(c.getName());
+ }
+ dictionaryNames.add(c.getShortName());
+ });
+
+ if (dictionaryFullNames.size() > 0) {
+ if (childObject.get(JsonEditorSchemaConstants.ENUM) != null) {
+ childObject.get(JsonEditorSchemaConstants.ENUM).getAsJsonArray().add(dictionaryFullNames);
+ }
+ else {
+ childObject.add(JsonEditorSchemaConstants.ENUM, dictionaryFullNames);
+ }
+ // Add Enum titles for generated translated values during JSON instance
+ // generation
+ JsonObject enumTitles = new JsonObject();
+ enumTitles.add(JsonEditorSchemaConstants.ENUM_TITLES, dictionaryNames);
+ if (childObject.get(JsonEditorSchemaConstants.OPTIONS) != null) {
+ childObject.get(JsonEditorSchemaConstants.OPTIONS).getAsJsonArray().add(enumTitles);
+ }
+ else {
+ childObject.add(JsonEditorSchemaConstants.OPTIONS, enumTitles);
+ }
+
+ }
+ else {
+ if (childObject.get(JsonEditorSchemaConstants.ENUM) != null) {
+ childObject.get(JsonEditorSchemaConstants.ENUM).getAsJsonArray().add(dictionaryNames);
+ }
+ else {
+ childObject.add(JsonEditorSchemaConstants.ENUM, dictionaryNames);
+ }
+ }
+ }
+
+ private static void processDictionaryElements(String dictionaryReference, JsonObject childObject,
+ DictionaryService dictionaryService) {
+ String[] dictionaryKeyArray =
+ dictionaryReference.substring(dictionaryReference.indexOf(ToscaSchemaConstants.DICTIONARY) + 11,
+ dictionaryReference.length()).split("#");
+ if (dictionaryKeyArray.length > 1) {
+ processComplexDictionaryElements(dictionaryKeyArray, childObject, dictionaryService);
+ }
+ else {
+ processSimpleDictionaryElements(dictionaryKeyArray, childObject, dictionaryService);
+ }
+ }
+
+ private static String getJsonType(String toscaType) {
+ String jsonType = null;
+ if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)) {
+ jsonType = JsonEditorSchemaConstants.TYPE_INTEGER;
+ }
+ else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) {
+ jsonType = JsonEditorSchemaConstants.TYPE_ARRAY;
+ }
+ else {
+ jsonType = JsonEditorSchemaConstants.TYPE_STRING;
+ }
+ return jsonType;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplate.java b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplate.java
new file mode 100644
index 000000000..f64ba68cf
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplate.java
@@ -0,0 +1,224 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.templates;
+
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.List;
+
+public class JsonTemplate {
+
+ /**
+ * name parameter is used as "key", in the LinkedHashMap of Templates.
+ */
+ private String name;
+ private List<JsonTemplateField> jsonTemplateFields;
+
+ public JsonTemplate(String name) {
+ this.name = name;
+ this.jsonTemplateFields = new ArrayList<>();
+ }
+
+ public JsonTemplate(String name, List<JsonTemplateField> jsonTemplateFields) {
+ this.name = name;
+ this.jsonTemplateFields = jsonTemplateFields;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List<JsonTemplateField> getJsonTemplateFields() {
+ return jsonTemplateFields;
+ }
+
+ public void setJsonTemplateFields(List<JsonTemplateField> jsonTemplateFields) {
+ this.jsonTemplateFields = jsonTemplateFields;
+ }
+
+ /**
+ * Search in fields if fieldName exists.
+ *
+ * @param fieldName The field name
+ * @return Ture if it exists, false otherwise
+ */
+ public boolean hasFields(String fieldName) {
+ for (JsonTemplateField jsonTemplateField : this.getJsonTemplateFields()) {
+ if (jsonTemplateField.getTitle().equals(fieldName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get a specific Field.
+ *
+ * @param fieldName The field name
+ * @return THe Field found
+ */
+ public JsonTemplateField getSpecificField(String fieldName) {
+ for (JsonTemplateField jsonTemplateField : this.getJsonTemplateFields()) {
+ if (jsonTemplateField.getTitle().equals(fieldName)) {
+ return jsonTemplateField;
+ }
+ }
+ return null;
+ }
+
+ public void addField(JsonTemplateField jsonTemplateField) {
+ jsonTemplateFields.add(jsonTemplateField);
+ }
+
+ public void removeField(JsonTemplateField jsonTemplateField) {
+ jsonTemplateFields.remove(jsonTemplateField);
+ }
+
+ /**
+ * Enable or disable the visibility.
+ *
+ * @param nameField THe field name
+ * @param state True or false
+ */
+ public void setVisibility(String nameField, boolean state) {
+ for (JsonTemplateField jsonTemplateField : this.jsonTemplateFields) {
+ if (jsonTemplateField.getTitle().equals(nameField)) {
+ jsonTemplateField.setVisible(state);
+ }
+ }
+ }
+
+ /**
+ * This method defines if a field is static or not.
+ *
+ * @param nameField The name of the field
+ * @param state true or false
+ */
+ public void setStatic(String nameField, boolean state) {
+ for (JsonTemplateField jsonTemplateField : this.jsonTemplateFields) {
+ if (jsonTemplateField.getTitle().equals(nameField)) {
+ jsonTemplateField.setStaticValue(state);
+ }
+ }
+ }
+
+ /**
+ * This method updates the value of a specfic field.
+ *
+ * @param nameField The name of the field
+ * @param newValue The new value as Object
+ */
+ public void updateValueField(String nameField, Object newValue) {
+ for (JsonTemplateField jsonTemplateField : this.jsonTemplateFields) {
+ if (jsonTemplateField.getTitle().equals(nameField)) {
+ jsonTemplateField.setValue(newValue);
+ }
+ }
+ }
+
+ /**
+ * Compare two templates : size and their contents.
+ *
+ * @param jsonTemplate the template
+ * @return a boolean
+ */
+ public boolean checkFields(JsonTemplate jsonTemplate) {
+ boolean duplicateFields = false;
+ if (jsonTemplate.getJsonTemplateFields().size() == this.getJsonTemplateFields().size()) {
+ int countMatchingFields = 0;
+ //loop each component of first
+ for (JsonTemplateField jsonTemplateFieldToCheck : jsonTemplate.getJsonTemplateFields()) {
+ for (JsonTemplateField jsonTemplateField : this.getJsonTemplateFields()) {
+ if (jsonTemplateFieldToCheck.compareWithField(jsonTemplateField)) {
+ countMatchingFields++;
+ }
+ }
+ }
+
+ if (jsonTemplate.getJsonTemplateFields().size() == countMatchingFields) {
+ duplicateFields = true;
+ }
+ }
+ return duplicateFields;
+ }
+
+ /**
+ * This method gets the specific field status.
+ *
+ * @param field The field name
+ * @return true or false
+ */
+ public boolean fieldStaticStatus(String field) {
+ if (this.hasFields(field) && this.getSpecificField(field).getStaticValue().equals(true)
+ && this.getSpecificField(field).getValue() != null) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isVisible(String field) {
+ return this.getSpecificField(field).getVisible();
+ }
+
+ /**
+ * Set the value of a property of the Field in the json.
+ *
+ * @param jsonSchema The Json schema
+ * @param fieldName The Field name
+ * @param value The value
+ */
+ public void setValue(JsonObject jsonSchema, String fieldName, String value) {
+ if (isVisible(fieldName)) {
+ if (fieldStaticStatus(fieldName)) {
+ String defaultValue = (String) this.getSpecificField(fieldName).getValue();
+ jsonSchema.addProperty(fieldName, defaultValue);
+ }
+ else {
+ jsonSchema.addProperty(fieldName, value);
+ }
+ }
+ }
+
+ /**
+ * Inject a static value in the json.
+ *
+ * @param jsonSchema The json schema object
+ * @param fieldName The field name
+ */
+ public void injectStaticValue(JsonObject jsonSchema, String fieldName) {
+ if (isVisible(fieldName)) {
+ JsonTemplateField toInject = this.getSpecificField(fieldName);
+ jsonSchema.addProperty(fieldName, (String) toInject.getValue());
+ }
+ }
+
+ @Override
+ public String toString() {
+ return " templateFields : " + jsonTemplateFields;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateField.java b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateField.java
new file mode 100644
index 000000000..a1e15307c
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateField.java
@@ -0,0 +1,149 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.templates;
+
+public class JsonTemplateField {
+ private String title;
+ private Object value;
+ private Boolean visible;
+ private Boolean staticValue;
+
+ public JsonTemplateField(String title) {
+ this.title = title;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param title The title
+ * @param value The value
+ * @param visible visible or not
+ * @param staticValue The static value
+ */
+ public JsonTemplateField(String title, Object value, Boolean visible, Boolean staticValue) {
+ this.title = title;
+ this.value = value;
+ this.visible = visible;
+ this.staticValue = staticValue;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ public Boolean getVisible() {
+ return visible;
+ }
+
+ public void setVisible(Boolean visible) {
+ this.visible = visible;
+ }
+
+ public Boolean getStaticValue() {
+ return staticValue;
+ }
+
+ public void setStaticValue(Boolean staticValue) {
+ this.staticValue = staticValue;
+ }
+
+ public String toString() {
+ return title + " " + value + " " + visible + " " + staticValue;
+ }
+
+ /**
+ * This method compares two fields.
+ *
+ * @param otherField Compare the current object with the one specified
+ * @return true if they are totally equals, false otherwise
+ */
+ public boolean compareWithField(Object otherField) {
+ if (this == otherField) {
+ return true;
+ }
+ if (otherField == null || getClass() != otherField.getClass()) {
+ return false;
+ }
+
+ JsonTemplateField jsonTemplateField = (JsonTemplateField) otherField;
+
+ if (title != null ? !title.equals(jsonTemplateField.title) : jsonTemplateField.title != null) {
+ return false;
+ }
+ if (value != null ? !value.equals(jsonTemplateField.value) : jsonTemplateField.value != null) {
+ return false;
+ }
+ if (visible != null ? !visible.equals(jsonTemplateField.visible) : jsonTemplateField.visible != null) {
+ return false;
+ }
+ return staticValue != null ? staticValue.equals(jsonTemplateField.staticValue) :
+ jsonTemplateField.staticValue == null;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object == null || getClass() != object.getClass()) {
+ return false;
+ }
+
+ JsonTemplateField jsonTemplateField = (JsonTemplateField) object;
+
+ return title != null ? title.equals(jsonTemplateField.title) : jsonTemplateField.title == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return title != null ? title.hashCode() : 0;
+ }
+
+ /**
+ * This method test the entire equality.
+ *
+ * @param jsonTemplateField1 object one
+ * @param jsonTemplateField2 object two
+ * @return true if they are totally equals (all attributes, false otherwise
+ */
+ public static boolean fieldsEquals(JsonTemplateField jsonTemplateField1, JsonTemplateField jsonTemplateField2) {
+ return (jsonTemplateField2.getTitle().equals(jsonTemplateField1.getTitle())
+ && jsonTemplateField2.getValue().equals(jsonTemplateField1.getValue())
+ && jsonTemplateField2.getVisible().equals(jsonTemplateField1.getVisible())
+ && jsonTemplateField2.getStaticValue().equals(jsonTemplateField1.getStaticValue()));
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateManager.java b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateManager.java
new file mode 100644
index 000000000..0b399ba0b
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateManager.java
@@ -0,0 +1,187 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.clds.tosca.update.templates;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.onap.clamp.clds.tosca.update.UnknownComponentException;
+import org.onap.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.clamp.clds.tosca.update.parser.ToscaConverterToJsonSchema;
+import org.onap.clamp.clds.tosca.update.parser.ToscaElementParser;
+import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.loop.service.Service;
+
+public class JsonTemplateManager {
+ private LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates;
+ private LinkedHashMap<String, ToscaElement> toscaElements;
+
+ /**
+ * Constructor.
+ *
+ * @param toscaYamlContent Policy Tosca Yaml content as string
+ * @param nativeToscaDatatypes The tosca yaml with tosca native datatypes
+ * @param jsonSchemaTemplates template properties as string
+ */
+ public JsonTemplateManager(String toscaYamlContent, String nativeToscaDatatypes, String jsonSchemaTemplates) {
+ if (toscaYamlContent != null && !toscaYamlContent.isEmpty()) {
+ this.toscaElements = ToscaElementParser.searchAllToscaElements(toscaYamlContent, nativeToscaDatatypes);
+ this.jsonSchemaTemplates = initializeTemplates(jsonSchemaTemplates);
+ }
+ else {
+ toscaElements = null;
+ }
+ }
+
+ //GETTERS & SETTERS
+ public LinkedHashMap<String, ToscaElement> getToscaElements() {
+ return toscaElements;
+ }
+
+ public void setToscaElements(LinkedHashMap<String, ToscaElement> toscaElements) {
+ this.toscaElements = toscaElements;
+ }
+
+ public LinkedHashMap<String, JsonTemplate> getJsonSchemaTemplates() {
+ return jsonSchemaTemplates;
+ }
+
+ public void setJsonSchemaTemplates(LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates) {
+ this.jsonSchemaTemplates = jsonSchemaTemplates;
+ }
+
+ /**
+ * Add a template.
+ *
+ * @param name name
+ * @param jsonTemplateFields fields
+ */
+ public void addTemplate(String name, List<JsonTemplateField> jsonTemplateFields) {
+ JsonTemplate jsonTemplate = new JsonTemplate(name, jsonTemplateFields);
+ //If it is true, the operation does not have any interest :
+ // replace OR put two different object with the same body
+ if (!jsonSchemaTemplates.containsKey(jsonTemplate.getName()) || !this.hasTemplate(jsonTemplate)) {
+ this.jsonSchemaTemplates.put(jsonTemplate.getName(), jsonTemplate);
+ }
+ }
+
+ /**
+ * By name, find and remove a given template.
+ *
+ * @param nameTemplate name template
+ */
+ public void removeTemplate(String nameTemplate) {
+ this.jsonSchemaTemplates.remove(nameTemplate);
+ }
+
+ /**
+ * Update Template : adding with true flag, removing with false.
+ *
+ * @param nameTemplate name template
+ * @param jsonTemplateField field name
+ * @param operation operation
+ */
+ public void updateTemplate(String nameTemplate, JsonTemplateField jsonTemplateField, Boolean operation) {
+ // Operation = true && field is not present => add Field
+ if (operation
+ && !this.jsonSchemaTemplates.get(nameTemplate).getJsonTemplateFields().contains(jsonTemplateField)) {
+ this.jsonSchemaTemplates.get(nameTemplate).addField(jsonTemplateField);
+ }
+ // Operation = false && field is present => remove Field
+ else if (!operation
+ && this.jsonSchemaTemplates.get(nameTemplate).getJsonTemplateFields().contains(jsonTemplateField)) {
+ this.jsonSchemaTemplates.get(nameTemplate).removeField(jsonTemplateField);
+ }
+ }
+
+ /**
+ * Check if the JSONTemplates have the same bodies.
+ *
+ * @param jsonTemplate template
+ * @return a boolean
+ */
+ public boolean hasTemplate(JsonTemplate jsonTemplate) {
+ boolean duplicateTemplate = false;
+ Collection<String> templatesName = jsonSchemaTemplates.keySet();
+ if (templatesName.contains(jsonTemplate.getName())) {
+ JsonTemplate existingJsonTemplate = jsonSchemaTemplates.get(jsonTemplate.getName());
+ duplicateTemplate = existingJsonTemplate.checkFields(jsonTemplate);
+ }
+ return duplicateTemplate;
+ }
+
+ /**
+ * For a given policy type, get a corresponding JsonObject from the tosca model.
+ *
+ * @param policyType The policy type in the tosca
+ * @param toscaMetadataParser The MetadataParser class that must be used if metadata section are encountered, if null
+ * they will be skipped
+ * @return an json object defining the equivalent json schema from the tosca for a given policy type
+ */
+ public JsonObject getJsonSchemaForPolicyType(String policyType, ToscaMetadataParser toscaMetadataParser,
+ Service serviceModel)
+ throws UnknownComponentException {
+ ToscaConverterToJsonSchema
+ toscaConverterToJsonSchema = new ToscaConverterToJsonSchema(toscaElements, jsonSchemaTemplates,
+ toscaMetadataParser, serviceModel);
+ if (toscaConverterToJsonSchema.getToscaElement(policyType) == null) {
+ throw new UnknownComponentException(policyType);
+ }
+ return toscaConverterToJsonSchema.getJsonSchemaOfToscaElement(policyType);
+ }
+
+ /**
+ * Create and complete several Templates from file.properties.
+ *
+ * @param jsonTemplates The template properties as String
+ * @return a map
+ */
+ @SuppressWarnings("unused")
+ private LinkedHashMap<String, JsonTemplate> initializeTemplates(String jsonTemplates) {
+
+ LinkedHashMap<String, JsonTemplate> generatedTemplates = new LinkedHashMap<>();
+ JsonObject templates = JsonUtils.GSON.fromJson(jsonTemplates, JsonObject.class);
+
+ for (Map.Entry<String, JsonElement> templateAsJson : templates.entrySet()) {
+ JsonTemplate jsonTemplate = new JsonTemplate(templateAsJson.getKey());
+ JsonObject templateBody = (JsonObject) templateAsJson.getValue();
+ for (Map.Entry<String, JsonElement> field : templateBody.entrySet()) {
+ String fieldName = field.getKey();
+ JsonObject bodyFieldAsJson = (JsonObject) field.getValue();
+ Object fieldValue = bodyFieldAsJson.get("defaultValue").getAsString();
+ Boolean fieldVisible = bodyFieldAsJson.get("visible").getAsBoolean();
+ Boolean fieldStatic = bodyFieldAsJson.get("static").getAsBoolean();
+ JsonTemplateField
+ bodyJsonTemplateField = new JsonTemplateField(fieldName, fieldValue, fieldVisible, fieldStatic);
+ jsonTemplate.getJsonTemplateFields().add(bodyJsonTemplateField);
+ }
+ generatedTemplates.put(jsonTemplate.getName(), jsonTemplate);
+ }
+ return generatedTemplates;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/util/ClampVersioning.java b/src/main/java/org/onap/clamp/clds/util/ClampVersioning.java
new file mode 100644
index 000000000..ec0162cb1
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/util/ClampVersioning.java
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * This class give a way to know the Clamp version easily, the version in that
+ * file is set by maven at build time.
+ *
+ */
+public class ClampVersioning {
+ private static final String RESOURCE_NAME = "clds-version.properties";
+ private static final String CLDS_VERSION_PROPERTY = "clds.version";
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ClampVersioning.class);
+
+ private ClampVersioning() {
+ }
+
+ /**
+ * Returns Clds version from properties.
+ *
+ * @return Clds version from properties
+ */
+ public static String getCldsVersionFromProps() {
+ String cldsVersion = "";
+ Properties props = new Properties();
+ try (InputStream resourceStream = ResourceFileUtils.getResourceAsStream(RESOURCE_NAME)) {
+ props.load(resourceStream);
+ cldsVersion = props.getProperty(CLDS_VERSION_PROPERTY);
+ } catch (Exception ex) {
+ LOGGER.error("Exception caught during the " + CLDS_VERSION_PROPERTY + " property reading", ex);
+ }
+ return cldsVersion;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/util/CryptoUtils.java b/src/main/java/org/onap/clamp/clds/util/CryptoUtils.java
new file mode 100644
index 000000000..1ddf3a90a
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/util/CryptoUtils.java
@@ -0,0 +1,168 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.common.base.Charsets;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.util.Properties;
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * CryptoUtils for encrypting/decrypting string based on a Key defined in
+ * application.properties (Spring config file).
+ */
+public final class CryptoUtils {
+
+ /**
+ * Used to log CryptoUtils class.
+ */
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(CryptoUtils.class);
+ // Openssl commands:
+ // Encrypt: echo -n "123456" | openssl aes-128-cbc -e -K <Private Hex key>
+ // -iv <16 Bytes iv (HEX), be careful it's 32 Hex Chars> | xxd -u -g100
+ // Final result is to put in properties file is: IV + Outcome of openssl
+ // command
+ // ************************************************************
+ // Decrypt: echo -n 'Encrypted string' | xxd -r -ps | openssl aes-128-cbc -d
+ // -K
+ // <Private Hex Key> -iv <16 Bytes IV extracted from Encrypted String, be
+ // careful it's 32 Hex Chars>
+ /**
+ * Definition of encryption algorithm.
+ */
+ private static final String ALGORITHM = "AES";
+
+ /**
+ * AES Encryption Key environment variable for external configuration.
+ */
+ private static final String AES_ENCRYPTION_KEY = "AES_ENCRYPTION_KEY";
+
+ /**
+ * Detailed definition of encryption algorithm.
+ */
+ private static final String ALGORITHM_DETAILS = ALGORITHM + "/CBC/PKCS5PADDING";
+ private static final int IV_BLOCK_SIZE_IN_BITS = 128;
+ /**
+ * An Initial Vector of 16 Bytes, so 32 Hexadecimal Chars.
+ */
+ private static final int IV_BLOCK_SIZE_IN_BYTES = IV_BLOCK_SIZE_IN_BITS / 8;
+ /**
+ * Key to read in the key.properties file.
+ */
+ private static final String KEY_PARAM = "org.onap.clamp.encryption.aes.key";
+ private static final String PROPERTIES_FILE_NAME = "clds/key.properties";
+ /**
+ * The SecretKeySpec created from the Base 64 String key.
+ */
+ private static final SecretKeySpec SECRET_KEY_SPEC = readSecretKeySpec(PROPERTIES_FILE_NAME);
+
+ /**
+ * Private constructor to avoid creating instances of util class.
+ */
+ private CryptoUtils() {
+ }
+
+ /**
+ * Encrypt a value based on the Clamp Encryption Key.
+ *
+ * @param value The value to encrypt
+ * @return The encrypted string
+ * @throws GeneralSecurityException In case of issue with the encryption
+ * @throws UnsupportedEncodingException In case of issue with the charset
+ * conversion
+ */
+ public static String encrypt(String value) throws GeneralSecurityException {
+ Cipher cipher = Cipher.getInstance(ALGORITHM_DETAILS, "SunJCE");
+ byte[] iv = new byte[IV_BLOCK_SIZE_IN_BYTES];
+ SecureRandom.getInstance("SHA1PRNG").nextBytes(iv);
+ IvParameterSpec ivspec = new IvParameterSpec(iv);
+ cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY_SPEC, ivspec);
+ return Hex.encodeHexString(ArrayUtils.addAll(iv, cipher.doFinal(value.getBytes(Charsets.UTF_8))));
+ }
+
+ /**
+ * Decrypt a value based on the Clamp Encryption Key.
+ *
+ * @param message The encrypted string that must be decrypted using the Clamp
+ * Encryption Key
+ * @return The String decrypted
+ * @throws GeneralSecurityException In case of issue with the encryption
+ * @throws DecoderException In case of issue to decode the HexString
+ */
+ public static String decrypt(String message) throws GeneralSecurityException, DecoderException {
+ byte[] encryptedMessage = Hex.decodeHex(message.toCharArray());
+ Cipher cipher = Cipher.getInstance(ALGORITHM_DETAILS, "SunJCE");
+ IvParameterSpec ivspec = new IvParameterSpec(ArrayUtils.subarray(encryptedMessage, 0, IV_BLOCK_SIZE_IN_BYTES));
+ byte[] realData = ArrayUtils.subarray(encryptedMessage, IV_BLOCK_SIZE_IN_BYTES, encryptedMessage.length);
+ cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY_SPEC, ivspec);
+ byte[] decrypted = cipher.doFinal(realData);
+ return new String(decrypted);
+ }
+
+ /**
+ * Method used to generate the SecretKeySpec from a Base64 String.
+ *
+ * @param keyString The key as a string in Base 64
+ * @return The SecretKeySpec created
+ * @throws DecoderException In case of issues with the decoding of Base64
+ */
+ private static SecretKeySpec getSecretKeySpec(String keyString) throws DecoderException {
+ byte[] key = Hex.decodeHex(keyString.toCharArray());
+ return new SecretKeySpec(key, ALGORITHM);
+ }
+
+ /**
+ * Reads SecretKeySpec from file specified by propertiesFileName.
+ *
+ * @param propertiesFileName File name with properties
+ * @return SecretKeySpec secret key spec read from propertiesFileName
+ */
+ private static SecretKeySpec readSecretKeySpec(String propertiesFileName) {
+ Properties props = new Properties();
+ try {
+ // Workaround fix to make encryption key configurable
+ // System environment variable takes precedence for over clds/key.properties
+ String encryptionKey = System.getenv(AES_ENCRYPTION_KEY);
+ if (encryptionKey != null && encryptionKey.trim().length() > 0) {
+ return getSecretKeySpec(encryptionKey);
+ } else {
+ props.load(ResourceFileUtils.getResourceAsStream(propertiesFileName));
+ return getSecretKeySpec(props.getProperty(KEY_PARAM));
+ }
+ } catch (IOException | DecoderException e) {
+ logger.error("Exception occurred during the key reading", e);
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/util/JsonUtils.java b/src/main/java/org/onap/clamp/clds/util/JsonUtils.java
new file mode 100644
index 000000000..8024331f2
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/util/JsonUtils.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018-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.clamp.clds.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import java.time.Instant;
+
+import org.onap.clamp.authorization.SecureServicePermission;
+import org.onap.clamp.authorization.SecureServicePermissionDeserializer;
+import org.onap.clamp.dao.model.gson.converter.InstantDeserializer;
+import org.onap.clamp.dao.model.gson.converter.InstantSerializer;
+
+/**
+ * This class is used to access the GSON with restricted type access.
+ */
+public class JsonUtils {
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(JsonUtils.class);
+
+ public static final Gson GSON = new GsonBuilder()
+ .registerTypeAdapter(SecureServicePermission.class, new SecureServicePermissionDeserializer()).create();
+
+ public static final Gson GSON_JPA_MODEL = new GsonBuilder()
+ .registerTypeAdapter(Instant.class, new InstantSerializer())
+ .registerTypeAdapter(Instant.class, new InstantDeserializer()).setPrettyPrinting()
+ .excludeFieldsWithoutExposeAnnotation().create();
+
+ private JsonUtils() {
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/util/LogMessages.java b/src/main/java/org/onap/clamp/clds/util/LogMessages.java
new file mode 100644
index 000000000..7f4c8781f
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/util/LogMessages.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.util;
+
+import com.att.eelf.i18n.EELFResolvableErrorEnum;
+import com.att.eelf.i18n.EELFResourceManager;
+
+public enum LogMessages implements EELFResolvableErrorEnum {
+ LOGSERVICE_HELLO_MESSAGE, LOGSERVICE_EMAIL_ERROR, LOGSERVICE_EMAIL_CLASS, LOGSERVICE_EMAIL_CLASS_NULL,
+ PROCESS_INSTANCE_ID;
+
+ static {
+ EELFResourceManager.loadMessageBundle("logmessages");
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java
new file mode 100644
index 000000000..0ac1a14fc
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java
@@ -0,0 +1,414 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.util;
+
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.URLConnection;
+import java.net.UnknownHostException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.UUID;
+import javax.net.ssl.HttpsURLConnection;
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.constraints.NotNull;
+import org.onap.clamp.authorization.AuthorizationController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.slf4j.event.Level;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+/**
+ * This class handles the special info that appear in the log, like RequestID,
+ * time context, ...
+ */
+public class LoggingUtils {
+
+ protected static final Logger logger = LoggerFactory.getLogger(LoggingUtils.class);
+
+ private static final DateFormat DATE_FORMAT = createDateFormat();
+
+ private static final String DATE_FORMATTER_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
+
+ /** String constant for messages <tt>ENTERING</tt>, <tt>EXITING</tt>, etc. */
+ private static final String EMPTY_MESSAGE = "";
+
+ /** Logger delegate. */
+ private Logger mlogger;
+
+ /** Automatic UUID, overrideable per adapter or per invocation. */
+ private static UUID sInstanceUUID = UUID.randomUUID();
+
+ /**
+ * Constructor.
+ */
+ public LoggingUtils(final Logger loggerP) {
+ this.mlogger = checkNotNull(loggerP);
+ }
+
+ /**
+ * Set request related logging variables in thread local data via MDC.
+ *
+ * @param service Service Name of API (ex. "PUT template")
+ * @param partner Partner name (client or user invoking API)
+ */
+ public static void setRequestContext(String service, String partner) {
+ MDC.put("RequestId", UUID.randomUUID().toString());
+ MDC.put("ServiceName", service);
+ MDC.put("PartnerName", partner);
+ // Defaulting to HTTP/1.1 protocol
+ MDC.put("Protocol", "HTTP/1.1");
+ try {
+ MDC.put("ServerFQDN", InetAddress.getLocalHost().getCanonicalHostName());
+ MDC.put("ServerIPAddress", InetAddress.getLocalHost().getHostAddress());
+ } catch (UnknownHostException e) {
+ logger.error("Failed to initiate setRequestContext", e);
+ }
+ }
+
+ /**
+ * Set time related logging variables in thread local data via MDC.
+ *
+ * @param beginTimeStamp Start time
+ * @param endTimeStamp End time
+ */
+ public static void setTimeContext(@NotNull Date beginTimeStamp, @NotNull Date endTimeStamp) {
+ MDC.put("EntryTimestamp", generateTimestampStr(beginTimeStamp));
+ MDC.put("EndTimestamp", generateTimestampStr(endTimeStamp));
+ MDC.put("ElapsedTime", String.valueOf(endTimeStamp.getTime() - beginTimeStamp.getTime()));
+ }
+
+ /**
+ * Set response related logging variables in thread local data via MDC.
+ *
+ * @param code Response code ("0" indicates success)
+ * @param description Response description
+ * @param className class name of invoking class
+ */
+ public static void setResponseContext(String code, String description, String className) {
+ MDC.put("ResponseCode", code);
+ MDC.put("StatusCode", "0".equals(code) ? "COMPLETE" : "ERROR");
+ MDC.put("ResponseDescription", description != null ? description : "");
+ MDC.put("ClassName", className != null ? className : "");
+ }
+
+ /**
+ * Set target related logging variables in thread local data via MDC.
+ *
+ * @param targetEntity Target entity (an external/sub component, for ex. "sdc")
+ * @param targetServiceName Target service name (name of API invoked on target)
+ */
+ public static void setTargetContext(String targetEntity, String targetServiceName) {
+ MDC.put("TargetEntity", targetEntity != null ? targetEntity : "");
+ MDC.put("TargetServiceName", targetServiceName != null ? targetServiceName : "");
+ }
+
+ /**
+ * Set error related logging variables in thread local data via MDC.
+ *
+ * @param code Error code
+ * @param description Error description
+ */
+ public static void setErrorContext(String code, String description) {
+ MDC.put("ErrorCode", code);
+ MDC.put("ErrorDescription", description != null ? description : "");
+ }
+
+ private static String generateTimestampStr(Date timeStamp) {
+ return DATE_FORMAT.format(timeStamp);
+ }
+
+ /**
+ * Get a previously stored RequestID for the thread local data via MDC. If
+ * one was not previously stored, generate one, store it, and return that
+ * one.
+ *
+ * @return A string with the request ID
+ */
+ public static String getRequestId() {
+ String requestId = MDC.get(OnapLogConstants.Mdcs.REQUEST_ID);
+ if (requestId == null || requestId.isEmpty()) {
+ requestId = UUID.randomUUID().toString();
+ MDC.put(OnapLogConstants.Mdcs.REQUEST_ID, requestId);
+ }
+ return requestId;
+ }
+
+ private static DateFormat createDateFormat() {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return dateFormat;
+ }
+
+ /*********************************************************************************************
+ * Method for ONAP Application Logging Specification v1.2
+ ********************************************************************************************/
+
+ /**
+ * Report <tt>ENTERING</tt> marker.
+ *
+ * @param request non-null incoming request (wrapper)
+ * @param serviceName service name
+ */
+ public void entering(HttpServletRequest request, String serviceName) {
+ // MDC.clear();
+ checkNotNull(request);
+ // Extract MDC values from standard HTTP headers.
+ final String requestId =
+ defaultToUuid(request.getHeader(OnapLogConstants.Headers.REQUEST_ID));
+ final String invocationId =
+ defaultToUuid(request.getHeader(OnapLogConstants.Headers.INVOCATION_ID));
+ final String partnerName =
+ defaultToEmpty(request.getHeader(OnapLogConstants.Headers.PARTNER_NAME));
+
+ // Default the partner name to the user name used to login to clamp
+ if (partnerName.equalsIgnoreCase(EMPTY_MESSAGE)) {
+ MDC.put(OnapLogConstants.Mdcs.PARTNER_NAME,
+ AuthorizationController.getPrincipalName(SecurityContextHolder.getContext()));
+ }
+
+ // Set standard MDCs. Override this entire method if you want to set
+ // others, OR set them BEFORE or AFTER the invocation of #entering,
+ // depending on where you need them to appear, OR extend the
+ // ServiceDescriptor to add them.
+ MDC.put(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP, ZonedDateTime.now(ZoneOffset.UTC)
+ .format(DateTimeFormatter.ofPattern(DATE_FORMATTER_ISO)));
+ MDC.put(OnapLogConstants.Mdcs.REQUEST_ID, requestId);
+ MDC.put(OnapLogConstants.Mdcs.INVOCATION_ID, invocationId);
+ MDC.put(OnapLogConstants.Mdcs.CLIENT_IP_ADDRESS, defaultToEmpty(request.getRemoteAddr()));
+ MDC.put(OnapLogConstants.Mdcs.SERVER_FQDN, defaultToEmpty(request.getServerName()));
+ MDC.put(OnapLogConstants.Mdcs.INSTANCE_UUID, defaultToEmpty(sInstanceUUID));
+
+ // Default the service name to the requestURI, in the event that
+ // no value has been provided.
+ if (serviceName == null || serviceName.equalsIgnoreCase(EMPTY_MESSAGE)) {
+ MDC.put(OnapLogConstants.Mdcs.SERVICE_NAME, request.getRequestURI());
+ } else {
+ MDC.put(OnapLogConstants.Mdcs.SERVICE_NAME, serviceName);
+ }
+
+ // Set the Response Status code to in progress
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE,
+ OnapLogConstants.ResponseStatus.INPROGRESS.toString());
+ setElapsedTime();
+
+ this.mlogger.info(OnapLogConstants.Markers.ENTRY, "Entering");
+ }
+
+ /**
+ * Report <tt>EXITING</tt> marker.
+ *
+ *
+ * @param code response code
+ * @param descrption response description
+ * @param severity response severity
+ * @param status response status code
+ */
+ public void exiting(int code, String descrption, Level severity,
+ OnapLogConstants.ResponseStatus status) {
+ try {
+
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_CODE, defaultToEmpty(code));
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_DESCRIPTION, defaultToEmpty(descrption));
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_SEVERITY, defaultToEmpty(severity));
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE, defaultToEmpty(status));
+
+ setElapsedTime();
+ this.mlogger.info(OnapLogConstants.Markers.EXIT, "Exiting");
+ } finally {
+ MDC.clear();
+ }
+ }
+
+ private void setElapsedTime() {
+ ZonedDateTime startTime =
+ ZonedDateTime.parse(MDC.get(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP),
+ DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneOffset.UTC));
+ ZonedDateTime endTime = ZonedDateTime.now(ZoneOffset.UTC);
+ long duration = ChronoUnit.MILLIS.between(startTime, endTime);
+ MDC.put(OnapLogConstants.Mdcs.ELAPSED_TIME, String.valueOf(duration));
+ }
+
+ /**
+ * Get the property value.
+ *
+ * @param name The name of the property
+ * @return The value of the property
+ */
+ public String getProperties(String name) {
+ return MDC.get(name);
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE</tt> marker,
+ * setting standard ONAP logging headers automatically.
+ *
+ * @param con The HTTP url connection
+ * @param targetEntity The target entity
+ * @param targetServiceName The target service name
+ * @return The HTTP url connection
+ */
+ public HttpURLConnection invoke(final HttpURLConnection con, String targetEntity,
+ String targetServiceName) {
+ return this.invokeGeneric(con, targetEntity, targetServiceName);
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE</tt> marker,
+ * setting standard ONAP logging headers automatically.
+ *
+ * @param targetEntity The target entity
+ * @param targetServiceName The target service name
+ */
+ public void invoke(String targetEntity, String targetServiceName) {
+ final String invocationId = UUID.randomUUID().toString();
+
+ invokeContext(targetEntity, targetServiceName, invocationId);
+
+ // Log INVOKE*, with the invocationID as the message body.
+ // (We didn't really want this kind of behavior in the standard,
+ // but is it worse than new, single-message MDC?)
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE, "INVOKE");
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE_SYNCHRONOUS + "{" + invocationId + "}");
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE</tt> marker,
+ * setting standard ONAP logging headers automatically.
+ *
+ * @param con The HTTPS url connection
+ * @param targetEntity The target entity
+ * @param targetServiceName The target service name
+ * @return The HTTPS url connection
+ */
+ public HttpsURLConnection invokeHttps(final HttpsURLConnection con, String targetEntity,
+ String targetServiceName) {
+ return this.invokeGeneric(con, targetEntity, targetServiceName);
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE-RETURN</tt> marker.
+ */
+ public void invokeReturn() {
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE,
+ OnapLogConstants.ResponseStatus.COMPLETE.toString());
+ // Add the Invoke-return marker and clear the needed MDC
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE_RETURN, "INVOKE-RETURN");
+ invokeReturnContext();
+ }
+
+ /**
+ * Dependency-free nullcheck.
+ *
+ * @param in to be checked
+ * @param <T> argument (and return) type
+ * @return input arg
+ */
+ private static <T> T checkNotNull(final T in) {
+ if (in == null) {
+ throw new NullPointerException();
+ }
+ return in;
+ }
+
+ /**
+ * Dependency-free string default.
+ *
+ * @param in to be filtered
+ * @return input string or null
+ */
+ private static String defaultToEmpty(final Object in) {
+ if (in == null) {
+ return "";
+ }
+ return in.toString();
+ }
+
+ /**
+ * Dependency-free string default.
+ *
+ * @param in to be filtered
+ * @return input string or null
+ */
+ private static String defaultToUuid(final String in) {
+ if (in == null) {
+ return UUID.randomUUID().toString();
+ }
+ return in;
+ }
+
+ /**
+ * Set target related logging variables in thread local data via MDC.
+ *
+ * @param targetEntity Target entity (an external/sub component, for ex. "sdc")
+ * @param targetServiceName Target service name (name of API invoked on target)
+ * @param invocationId The invocation ID
+ */
+ private void invokeContext(String targetEntity, String targetServiceName, String invocationId) {
+ MDC.put(OnapLogConstants.Mdcs.TARGET_ENTITY, defaultToEmpty(targetEntity));
+ MDC.put(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME, defaultToEmpty(targetServiceName));
+ MDC.put(OnapLogConstants.Mdcs.INVOCATIONID_OUT, invocationId);
+ MDC.put(OnapLogConstants.Mdcs.INVOKE_TIMESTAMP, ZonedDateTime.now(ZoneOffset.UTC)
+ .format(DateTimeFormatter.ofPattern(DATE_FORMATTER_ISO)));
+ }
+
+ /**
+ * Clear target related logging variables in thread local data via MDC.
+ */
+ private void invokeReturnContext() {
+ MDC.remove(OnapLogConstants.Mdcs.TARGET_ENTITY);
+ MDC.remove(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME);
+ MDC.remove(OnapLogConstants.Mdcs.INVOCATIONID_OUT);
+ MDC.remove(OnapLogConstants.Mdcs.INVOKE_TIMESTAMP);
+ MDC.remove(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE);
+ }
+
+ private <T extends URLConnection> T invokeGeneric(final T con, String targetEntity,
+ String targetServiceName) {
+ final String invocationId = UUID.randomUUID().toString();
+
+ // Set standard HTTP headers on (southbound request) builder.
+ con.setRequestProperty(OnapLogConstants.Headers.REQUEST_ID,
+ defaultToEmpty(MDC.get(OnapLogConstants.Mdcs.REQUEST_ID)));
+ con.setRequestProperty(OnapLogConstants.Headers.INVOCATION_ID, invocationId);
+ con.setRequestProperty(OnapLogConstants.Headers.PARTNER_NAME,
+ defaultToEmpty(MDC.get(OnapLogConstants.Mdcs.PARTNER_NAME)));
+
+ invokeContext(targetEntity, targetServiceName, invocationId);
+
+ // Log INVOKE*, with the invocationID as the message body.
+ // (We didn't really want this kind of behavior in the standard,
+ // but is it worse than new, single-message MDC?)
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE, "");
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE_SYNCHRONOUS + "{" + invocationId + "}");
+ return con;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/util/OnapLogConstants.java b/src/main/java/org/onap/clamp/clds/util/OnapLogConstants.java
new file mode 100644
index 000000000..8952e5df1
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/util/OnapLogConstants.java
@@ -0,0 +1,304 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.clds.util;
+
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+/**
+ * Constants for standard ONAP headers, MDCs, etc.
+ */
+public final class OnapLogConstants {
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Constructors.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Hide and forbid construction.
+ */
+ private OnapLogConstants() {
+ throw new UnsupportedOperationException();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Inner classes.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Marker constants.
+ */
+ public static final class Markers {
+
+ /** Marker reporting invocation. */
+ public static final Marker INVOKE = MarkerFactory.getMarker("INVOKE");
+
+ /** Marker reporting invocation return. */
+ public static final Marker INVOKE_RETURN = MarkerFactory.getMarker("INVOKE-RETURN");
+
+ /** Marker reporting synchronous invocation. */
+ public static final Marker INVOKE_SYNCHRONOUS = build("INVOKE", "SYNCHRONOUS");
+
+ /** Marker reporting asynchronous invocation. */
+ public static final Marker INVOKE_ASYNCHRONOUS = build("INVOKE", "ASYNCHRONOUS");
+
+ /** Marker reporting entry into a component. */
+ public static final Marker ENTRY = MarkerFactory.getMarker("ENTRY");
+
+ /** Marker reporting exit from a component. */
+ public static final Marker EXIT = MarkerFactory.getMarker("EXIT");
+
+ /**
+ * Build nested, detached marker.
+ *
+ * @param m1 top token.
+ * @param m2 sub-token.
+ * @return detached Marker.
+ */
+ private static Marker build(final String m1, final String m2) {
+ final Marker marker = MarkerFactory.getDetachedMarker(m1);
+ marker.add(MarkerFactory.getDetachedMarker(m2));
+ return marker;
+ }
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Markers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * MDC name constants.
+ */
+ public static final class Mdcs {
+
+ // Tracing. ////////////////////////////////////////////////////////////
+
+ /** MDC correlating messages for an invocation. */
+ public static final String INVOCATION_ID = "InvocationID";
+
+ public static final String SERVER_INVOCATION_ID = "ServerInvocationId";
+
+ public static final String CLIENT_INVOCATION_ID = "ClientInvocationId";
+
+ /** MDC correlating messages for a logical transaction. */
+ public static final String REQUEST_ID = "RequestID";
+
+ /** MDC recording calling partner name. */
+ public static final String PARTNER_NAME = "PartnerName";
+
+ /** MDC recording current service. */
+ public static final String SERVICE_NAME = "ServiceName";
+
+ /** MDC recording target service. */
+ public static final String TARGET_SERVICE_NAME = "TargetServiceName";
+
+ /** MDC recording InvocationID Out. */
+ public static final String INVOCATIONID_OUT = "InvocationIDOut";
+
+ /** MDC recording target entity. */
+ public static final String TARGET_ENTITY = "TargetEntity";
+
+ /** MDC recording target element. */
+ public static final String TARGET_ELEMENT = "TargetElement";
+
+ /** MDC recording current service instance id. */
+ public static final String SERVICE_INSTANCE_ID = "ServiceInstanceID";
+
+ /** MDC recording current instance id. */
+ public static final String INSTANCE_UUID = "InstanceID";
+
+ // Network. ////////////////////////////////////////////////////////////
+
+ /** MDC recording caller address. */
+ public static final String CLIENT_IP_ADDRESS = "ClientIPAddress";
+
+ /** MDC recording server IP address. */
+ public static final String SERVER_IP_ADDRESS = "ServerIPAddress";
+
+ /** MDC recording server FQDN. */
+ public static final String SERVER_FQDN = "ServerFQDN";
+
+ /** MDC recording virtual server name. */
+ public static final String VIRTUAL_SERVER_NAME = "VirtualServerName";
+
+ /** MDC recording context name. */
+ public static final String CONTEXT_NAME = "ContextName";
+
+ /**
+ * MDC recording timestamp at the start of the current request,
+ * with the same scope as {@link #REQUEST_ID}.
+ *
+ * <p>
+ * Open issues:
+ * <ul>
+ * <ul>
+ * Easily confused with {@link #INVOKE_TIMESTAMP}.
+ * </ul>
+ * <ul>
+ * No mechanism for propagation between components, e.g. via HTTP headers.
+ * </ul>
+ * <ul>
+ * Whatever mechanism we define, it's going to be costly.
+ * </ul>
+ * </ul>
+ * </p>
+ */
+ public static final String ENTRY_TIMESTAMP = "EntryTimestamp";
+
+ /** MDC recording timestamp at the start of the current invocation. */
+ public static final String INVOKE_TIMESTAMP = "InvokeTimestamp";
+
+ /** MDC recording elapsed time. */
+ public static final String ELAPSED_TIME = "ElapsedTime";
+
+ /** MDC recording log timestamp. */
+ public static final String LOG_TIMESTAMP = "LogTimestamp";
+
+ // Outcomes. ///////////////////////////////////////////////////////////
+
+ /** MDC reporting outcome code. */
+ public static final String RESPONSE_CODE = "ResponseCode";
+
+ /** MDC reporting outcome description. */
+ public static final String RESPONSE_DESCRIPTION = "ResponseDesc";
+
+ /** MDC reporting severity */
+ public static final String RESPONSE_SEVERITY = "Severity";
+
+ /** MDC reporting response status code */
+ public static final String RESPONSE_STATUS_CODE = "StatusCode";
+
+ /** MDC recording error code. */
+ public static final String ERROR_CODE = "ErrorCode";
+
+ /** MDC recording error description. */
+ public static final String ERROR_DESC = "ErrorDesc";
+
+ // Unsorted. ///////////////////////////////////////////////////////////
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Mdcs() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Header name constants.
+ */
+ public static final class Headers {
+
+ /** HTTP <tt>X-ONAP-RequestID</tt> header. */
+ public static final String REQUEST_ID = "X-ONAP-RequestID";
+
+ /** HTTP <tt>X-InvocationID</tt> header. */
+ public static final String INVOCATION_ID = "X-ONAP-InvocationID";
+
+ /** HTTP <tt>X-ONAP-PartnerName</tt> header. */
+ public static final String PARTNER_NAME = "X-ONAP-PartnerName";
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Headers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Enums.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Response success or not, for setting <tt>StatusCode</tt>.
+ */
+ public enum ResponseStatus {
+
+ /** Success. */
+ COMPLETE,
+
+ /** Not. */
+ ERROR,
+
+ /** In Progress. */
+ INPROGRESS
+ }
+
+ /**
+ * Synchronous or asynchronous execution, for setting invocation marker.
+ */
+ public enum InvocationMode {
+
+ /** Synchronous, blocking. */
+ SYNCHRONOUS("SYNCHRONOUS", Markers.INVOKE_SYNCHRONOUS),
+
+ /** Asynchronous, non-blocking. */
+ ASYNCHRONOUS("ASYNCHRONOUS", Markers.INVOKE_ASYNCHRONOUS);
+
+ /** Enum value. */
+ private String mString;
+
+ /** Corresponding marker. */
+ private Marker mMarker;
+
+ /**
+ * Construct enum.
+ *
+ * @param s enum value.
+ * @param m corresponding Marker.
+ */
+ InvocationMode(final String s, final Marker m) {
+ this.mString = s;
+ this.mMarker = m;
+ }
+
+ /**
+ * Get Marker for enum.
+ *
+ * @return Marker.
+ */
+ public Marker getMarker() {
+ return this.mMarker;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return this.mString;
+ }
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/clds/util/ResourceFileUtils.java b/src/main/java/org/onap/clamp/clds/util/ResourceFileUtils.java
new file mode 100644
index 000000000..f858ed2b8
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/util/ResourceFileUtils.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Scanner;
+
+/**
+ * Utility methods supporting resources accesses.
+ */
+public final class ResourceFileUtils {
+
+ /**
+ * getResourceAsStram supports the "file:" prefix as they use URL.
+ * So here we want to eliminate classpath: prefix, so that this class can get
+ * files from jar resource or file system.
+ */
+
+ private static final String CLASSPATH_PREFIX = "classpath:";
+
+ /**
+ * Private constructor to avoid creating instances of util class.
+ */
+ private ResourceFileUtils() {
+ }
+
+ /**
+ * Method to access a file from the jar resource folder or file system.
+ * Give the prefix "classpath:" so that it accesses the jar resource folder (default case)
+ * or the prefix "file:" so that it accesses the file system.
+ *
+ * @param fileName The path of the resource (no prefix it will be a classpath access,
+ * "classpath:/myfilename" or "file:/myfilename")
+ * @return The file as inputStream
+ */
+ public static InputStream getResourceAsStream(String fileName) {
+ InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(
+ fileName.startsWith(CLASSPATH_PREFIX) ? fileName.replaceFirst(CLASSPATH_PREFIX, "") : fileName);
+ if (is == null) {
+ throw new IllegalArgumentException("Unable to find resource: " + fileName);
+ }
+ return is;
+ }
+
+ /**
+ * Method to access a resource file as a string.
+ * Give the prefix "classpath:" so that it accesses the jar resource folder (default case)
+ * or the prefix "file:" so that it accesses the file system.
+ *
+ * @param fileName The path of the resource (no prefix it will be a classpath access,
+ * "classpath:/myfilename" or "file:/myfilename")
+ * @return The file as String
+ * @throws IOException In case of failure to find the file.
+ */
+ public static String getResourceAsString(String fileName) throws IOException {
+ try (InputStream is = getResourceAsStream(fileName)) {
+ return streamToString(is);
+ }
+ }
+
+ private static String streamToString(InputStream inputStream) {
+ try (Scanner scanner = new Scanner(inputStream)) {
+ Scanner delimitedScanner = scanner.useDelimiter("\\A");
+ return delimitedScanner.hasNext() ? delimitedScanner.next() : "";
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/configuration/ClampGsonDataFormat.java b/src/main/java/org/onap/clamp/configuration/ClampGsonDataFormat.java
new file mode 100644
index 000000000..ca5f37656
--- /dev/null
+++ b/src/main/java/org/onap/clamp/configuration/ClampGsonDataFormat.java
@@ -0,0 +1,172 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.configuration;
+
+import com.google.gson.Gson;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.DataFormatName;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.IOHelper;
+import org.onap.clamp.clds.util.JsonUtils;
+
+public class ClampGsonDataFormat extends ServiceSupport implements DataFormat, DataFormatName {
+ private Gson gson;
+ private Class<?> unmarshalType;
+ private Type unmarshalGenericType;
+ private boolean contentTypeHeader = true;
+
+ public ClampGsonDataFormat() {
+ this(Object.class);
+ }
+
+ /**
+ * Use the default Gson {@link Gson} and with a custom unmarshal type.
+ *
+ * @param unmarshalType the custom unmarshal type
+ */
+ public ClampGsonDataFormat(Class<?> unmarshalType) {
+ this(null, unmarshalType);
+ }
+
+ /**
+ * Use a custom Gson mapper and and unmarshal type.
+ *
+ * @param gson the custom mapper
+ * @param unmarshalType the custom unmarshal type
+ */
+ public ClampGsonDataFormat(Gson gson, Class<?> unmarshalType) {
+ this.gson = gson;
+ this.unmarshalType = unmarshalType;
+ }
+
+ /**
+ * Use the default Gson {@link Gson} and with a custom unmarshal generic type.
+ *
+ * @param unmarshalGenericType the custom unmarshal generic type
+ */
+ public ClampGsonDataFormat(Type unmarshalGenericType) {
+ this(null, unmarshalGenericType);
+ }
+
+ /**
+ * Use a custom Gson mapper and and unmarshal token type.
+ *
+ * @param gson the custom mapper
+ * @param unmarshalGenericType the custom unmarshal generic type
+ */
+ public ClampGsonDataFormat(Gson gson, Type unmarshalGenericType) {
+ this.gson = gson;
+ this.unmarshalGenericType = unmarshalGenericType;
+ }
+
+ @Override
+ public String getDataFormatName() {
+ return "clamp-gson";
+ }
+
+ @Override
+ public void marshal(final Exchange exchange, final Object graph, final OutputStream stream) throws Exception {
+ try (final OutputStreamWriter osw = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
+ final BufferedWriter writer = IOHelper.buffered(osw)) {
+ gson.toJson(graph, writer);
+ }
+
+ if (contentTypeHeader) {
+ if (exchange.hasOut()) {
+ exchange.getOut().setHeader(Exchange.CONTENT_TYPE, "application/json");
+ } else {
+ exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
+ }
+ }
+ }
+
+ @Override
+ public Object unmarshal(final Exchange exchange, final InputStream stream) throws Exception {
+ try (final InputStreamReader isr = new InputStreamReader(stream, StandardCharsets.UTF_8);
+ final BufferedReader reader = IOHelper.buffered(isr)) {
+ if (unmarshalGenericType == null) {
+ return gson.fromJson(reader, unmarshalType);
+ } else {
+ return gson.fromJson(reader, unmarshalGenericType);
+ }
+ }
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ if (gson == null) {
+ gson = JsonUtils.GSON_JPA_MODEL;
+ }
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ // noop
+ }
+
+ // Properties
+ // -------------------------------------------------------------------------
+
+ public Class<?> getUnmarshalType() {
+ return this.unmarshalType;
+ }
+
+ public void setUnmarshalType(Class<?> unmarshalType) {
+ this.unmarshalType = unmarshalType;
+ }
+
+ public Type getUnmarshalGenericType() {
+ return this.unmarshalGenericType;
+ }
+
+ public void setUnmarshalGenericType(Type unmarshalGenericType) {
+ this.unmarshalGenericType = unmarshalGenericType;
+ }
+
+ public boolean isContentTypeHeader() {
+ return contentTypeHeader;
+ }
+
+ /**
+ * If enabled then Gson will set the Content-Type header to
+ * <tt>application/json</tt> when marshalling.
+ */
+ public void setContentTypeHeader(boolean contentTypeHeader) {
+ this.contentTypeHeader = contentTypeHeader;
+ }
+
+ public Gson getGson() {
+ return this.gson;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantDeserializer.java b/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantDeserializer.java
new file mode 100644
index 000000000..2d63e55fa
--- /dev/null
+++ b/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantDeserializer.java
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.dao.model.gson.converter;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+
+import java.lang.reflect.Type;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Locale;
+
+public class InstantDeserializer implements JsonDeserializer<Instant> {
+
+ DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.US)
+ .withZone(ZoneId.systemDefault());
+
+ @Override
+ public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
+ return Instant.parse(json.getAsString());
+
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantSerializer.java b/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantSerializer.java
new file mode 100644
index 000000000..cdb439e46
--- /dev/null
+++ b/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantSerializer.java
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.dao.model.gson.converter;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+import java.lang.reflect.Type;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+public class InstantSerializer implements JsonSerializer<Instant> {
+
+ @Override
+ public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(DateTimeFormatter.ISO_INSTANT.format(src));
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java b/src/main/java/org/onap/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java
new file mode 100644
index 000000000..f5aba4e11
--- /dev/null
+++ b/src/main/java/org/onap/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java
@@ -0,0 +1,109 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.dao.model.jsontype;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.hibernate.type.descriptor.ValueBinder;
+import org.hibernate.type.descriptor.ValueExtractor;
+import org.hibernate.type.descriptor.WrapperOptions;
+import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
+import org.hibernate.type.descriptor.sql.BasicBinder;
+import org.hibernate.type.descriptor.sql.BasicExtractor;
+import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
+
+public class JsonStringSqlTypeDescriptor implements SqlTypeDescriptor {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 1103168570216921981L;
+
+ public static final JsonStringSqlTypeDescriptor INSTANCE = new JsonStringSqlTypeDescriptor();
+
+ @Override
+ public int getSqlType() {
+ return Types.OTHER;
+ }
+
+ @Override
+ public boolean canBeRemapped() {
+ return true;
+ }
+
+ @Override
+ public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
+ return new BasicBinder<X>(javaTypeDescriptor, this) {
+ @Override
+ protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
+ throws SQLException {
+ st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
+ }
+
+ @Override
+ protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
+ throws SQLException {
+ st.setString(name, javaTypeDescriptor.unwrap(value, String.class, options));
+ }
+ };
+ }
+
+ @Override
+ public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
+ return new BasicExtractor<X>(javaTypeDescriptor, this) {
+ @Override
+ protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap(extractJson(rs, name), options);
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap(extractJson(statement, index), options);
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
+ throws SQLException {
+ return javaTypeDescriptor.wrap(extractJson(statement, name), options);
+ }
+ };
+ }
+
+ protected Object extractJson(ResultSet rs, String name) throws SQLException {
+ return rs.getObject(name);
+ }
+
+ protected Object extractJson(CallableStatement statement, int index) throws SQLException {
+ return statement.getObject(index);
+ }
+
+ protected Object extractJson(CallableStatement statement, String name) throws SQLException {
+ return statement.getObject(name);
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/dao/model/jsontype/JsonTypeDescriptor.java b/src/main/java/org/onap/clamp/dao/model/jsontype/JsonTypeDescriptor.java
new file mode 100644
index 000000000..518ec2d04
--- /dev/null
+++ b/src/main/java/org/onap/clamp/dao/model/jsontype/JsonTypeDescriptor.java
@@ -0,0 +1,107 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.dao.model.jsontype;
+
+import com.google.gson.JsonObject;
+
+import java.io.Serializable;
+
+import org.hibernate.type.descriptor.WrapperOptions;
+import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
+import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
+import org.onap.clamp.clds.util.JsonUtils;
+
+public class JsonTypeDescriptor extends AbstractTypeDescriptor<JsonObject> {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -3439698221196089003L;
+
+ public static final JsonTypeDescriptor INSTANCE = new JsonTypeDescriptor();
+
+ /**
+ * Creates an instance of JsonTypeDescriptor.
+ */
+ public JsonTypeDescriptor() {
+ super(JsonObject.class, new ImmutableMutabilityPlan<JsonObject>() {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 1169396106518110214L;
+
+ @Override
+ public Serializable disassemble(JsonObject value) {
+ return JsonUtils.GSON_JPA_MODEL.toJson(value);
+ }
+
+ @Override
+ public JsonObject assemble(Serializable cached) {
+ return JsonUtils.GSON_JPA_MODEL.fromJson((String) cached, JsonObject.class);
+ }
+
+ });
+ }
+
+ @Override
+ public String toString(JsonObject value) {
+ return JsonUtils.GSON_JPA_MODEL.toJson(value);
+ }
+
+ @Override
+ public JsonObject fromString(String string) {
+ return JsonUtils.GSON_JPA_MODEL.fromJson(string, JsonObject.class);
+ }
+
+ @Override
+ public <X> X unwrap(JsonObject value, Class<X> type, WrapperOptions options) {
+ if (value == null) {
+ return null;
+ }
+
+ if (String.class.isAssignableFrom(type)) {
+ return (X) toString(value);
+ }
+
+ if (JsonObject.class.isAssignableFrom(type)) {
+ return (X) JsonUtils.GSON_JPA_MODEL.toJson(toString(value));
+ }
+ throw unknownUnwrap(type);
+ }
+
+ @Override
+ public <X> JsonObject wrap(X value, WrapperOptions options) {
+ if (value == null) {
+ return null;
+ }
+
+ if (String.class.isInstance(value)) {
+ return JsonUtils.GSON_JPA_MODEL.fromJson((String) value, JsonObject.class);
+ }
+
+ throw unknownWrap(value.getClass());
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/dao/model/jsontype/StringJsonUserType.java b/src/main/java/org/onap/clamp/dao/model/jsontype/StringJsonUserType.java
new file mode 100644
index 000000000..621fa8dad
--- /dev/null
+++ b/src/main/java/org/onap/clamp/dao/model/jsontype/StringJsonUserType.java
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.dao.model.jsontype;
+
+import com.google.gson.JsonObject;
+
+import org.hibernate.type.AbstractSingleColumnStandardBasicType;
+import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
+import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
+
+public class StringJsonUserType extends AbstractSingleColumnStandardBasicType<JsonObject> {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -7929809808079327767L;
+
+ public StringJsonUserType() {
+ super(JsonStringSqlTypeDescriptor.INSTANCE, JsonTypeDescriptor.INSTANCE);
+ }
+
+ public StringJsonUserType(SqlTypeDescriptor sqlTypeDescriptor, JavaTypeDescriptor<JsonObject> javaTypeDescriptor) {
+ super(sqlTypeDescriptor, javaTypeDescriptor);
+ }
+
+ @Override
+ public String getName() {
+ return "json";
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/flow/log/FlowLogOperation.java b/src/main/java/org/onap/clamp/flow/log/FlowLogOperation.java
new file mode 100644
index 000000000..e31406b2c
--- /dev/null
+++ b/src/main/java/org/onap/clamp/flow/log/FlowLogOperation.java
@@ -0,0 +1,101 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.flow.log;
+
+import javax.servlet.http.HttpServletRequest;
+import org.apache.camel.Exchange;
+import org.onap.clamp.clds.util.LoggingUtils;
+import org.onap.clamp.clds.util.OnapLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+
+/**
+ * The Flow log operations.
+ */
+@Component
+public class FlowLogOperation {
+
+ protected static final Logger logger = LoggerFactory.getLogger(FlowLogOperation.class);
+ private LoggingUtils util = new LoggingUtils(logger);
+
+ @Autowired
+ private HttpServletRequest request;
+
+ /**
+ * Generate the entry log.
+ *
+ * @param serviceDesc
+ * The service description the loop name
+ */
+ public void startLog(Exchange exchange, String serviceDesc) {
+ util.entering(request, serviceDesc);
+ exchange.setProperty(OnapLogConstants.Headers.REQUEST_ID,
+ util.getProperties(OnapLogConstants.Mdcs.REQUEST_ID));
+ exchange.setProperty(OnapLogConstants.Headers.INVOCATION_ID,
+ util.getProperties(OnapLogConstants.Mdcs.INVOCATION_ID));
+ exchange.setProperty(OnapLogConstants.Headers.PARTNER_NAME,
+ util.getProperties(OnapLogConstants.Mdcs.PARTNER_NAME));
+ }
+
+ /**
+ * Generate the exiting log.
+ */
+ public void endLog() {
+ util.exiting(HttpStatus.OK.value(), "Successful", Level.INFO,
+ OnapLogConstants.ResponseStatus.COMPLETE);
+ }
+
+ /**
+ * Generate the error exiting log.
+ */
+ public void errorLog() {
+ util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Failed", Level.INFO,
+ OnapLogConstants.ResponseStatus.ERROR);
+ }
+
+ /**
+ * Generate the error exiting log.
+ */
+ public void httpErrorLog() {
+
+ }
+
+ /**
+ * Generate the invoke log.
+ */
+ public void invokeLog(String targetEntity, String targetServiceName) {
+ util.invoke(targetEntity, targetServiceName);
+ }
+
+ /**
+ * Generate the invoke return marker.
+ */
+ public void invokeReturnLog() {
+ util.invokeReturn();
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/CsarInstaller.java b/src/main/java/org/onap/clamp/loop/CsarInstaller.java
new file mode 100644
index 000000000..6752a1a36
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/CsarInstaller.java
@@ -0,0 +1,210 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import org.json.simple.parser.ParseException;
+import org.onap.clamp.clds.client.DcaeInventoryServices;
+import org.onap.clamp.clds.client.PolicyEngineServices;
+import org.onap.clamp.clds.exception.sdc.controller.BlueprintParserException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.clamp.clds.model.dcae.DcaeInventoryResponse;
+import org.onap.clamp.clds.sdc.controller.installer.BlueprintArtifact;
+import org.onap.clamp.clds.sdc.controller.installer.BlueprintMicroService;
+import org.onap.clamp.clds.sdc.controller.installer.BlueprintParser;
+import org.onap.clamp.clds.sdc.controller.installer.ChainGenerator;
+import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.clamp.loop.cds.CdsDataInstaller;
+import org.onap.clamp.loop.service.CsarServiceInstaller;
+import org.onap.clamp.loop.service.Service;
+import org.onap.clamp.loop.template.LoopElementModel;
+import org.onap.clamp.loop.template.LoopTemplate;
+import org.onap.clamp.loop.template.LoopTemplatesRepository;
+import org.onap.clamp.loop.template.PolicyModel;
+import org.onap.clamp.loop.template.PolicyModelId;
+import org.onap.clamp.loop.template.PolicyModelsRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class will be instantiated by spring config, and used by Sdc Controller.
+ * There is no state kept by the bean. It's used to deploy the csar/notification
+ * received from SDC in DB.
+ */
+@Component
+@Qualifier("csarInstaller")
+public class CsarInstaller {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarInstaller.class);
+
+ @Autowired
+ private PolicyModelsRepository policyModelsRepository;
+
+ @Autowired
+ private LoopTemplatesRepository loopTemplatesRepository;
+
+ @Autowired
+ private ChainGenerator chainGenerator;
+
+ @Autowired
+ private DcaeInventoryServices dcaeInventoryService;
+
+ @Autowired
+ private CsarServiceInstaller csarServiceInstaller;
+
+ @Autowired
+ private CdsDataInstaller cdsDataInstaller;
+
+ @Autowired
+ private PolicyEngineServices policyEngineServices;
+
+ /**
+ * Verify whether Csar is deployed.
+ *
+ * @param csar The Csar Handler
+ * @return The flag indicating whether Csar is deployed
+ * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
+ */
+ public boolean isCsarAlreadyDeployed(CsarHandler csar) throws SdcArtifactInstallerException {
+ boolean alreadyInstalled = csarServiceInstaller.isServiceAlreadyDeployed(csar);
+
+ for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
+ alreadyInstalled = alreadyInstalled
+ && loopTemplatesRepository.existsById(LoopTemplate.generateLoopTemplateName(
+ csar.getSdcNotification().getServiceName(), csar.getSdcNotification().getServiceVersion(),
+ blueprint.getValue().getResourceAttached().getResourceInstanceName(),
+ blueprint.getValue().getBlueprintArtifactName()));
+ }
+ return alreadyInstalled;
+ }
+
+ /**
+ * Install the service and loop templates from the csar.
+ *
+ * @param csar The Csar Handler
+ * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
+ * @throws InterruptedException The InterruptedException
+ * @throws BlueprintParserException In case of issues with the blueprint
+ * parsing
+ */
+ public void installTheCsar(CsarHandler csar)
+ throws SdcArtifactInstallerException, InterruptedException, BlueprintParserException {
+ logger.info("Installing the CSAR " + csar.getFilePath());
+ Service associatedService = csarServiceInstaller.installTheService(csar);
+ cdsDataInstaller.installCdsServiceProperties(csar, associatedService);
+
+ installTheLoopTemplates(csar, associatedService);
+ logger.info("Successfully installed the CSAR " + csar.getFilePath());
+ }
+
+ /**
+ * Install the loop templates from the csar.
+ *
+ * @param csar The Csar Handler
+ * @param service The service object that is related to the loop
+ * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
+ * @throws InterruptedException The InterruptedException
+ * @throws BlueprintParserException In case of issues with the blueprint
+ * parsing
+ */
+ public void installTheLoopTemplates(CsarHandler csar, Service service)
+ throws SdcArtifactInstallerException, InterruptedException, BlueprintParserException {
+ try {
+ logger.info("Installing the Loops");
+ for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
+ logger.info("Processing blueprint " + blueprint.getValue().getBlueprintArtifactName());
+ loopTemplatesRepository.save(createLoopTemplateFromBlueprint(csar, blueprint.getValue(), service));
+ }
+ logger.info("Successfully installed the Loops ");
+ } catch (IOException e) {
+ throw new SdcArtifactInstallerException("Exception caught during the Loop installation in database", e);
+ } catch (ParseException e) {
+ throw new SdcArtifactInstallerException("Exception caught during the Dcae query to get ServiceTypeId", e);
+ }
+ }
+
+ private LoopTemplate createLoopTemplateFromBlueprint(CsarHandler csar, BlueprintArtifact blueprintArtifact,
+ Service service)
+ throws IOException, ParseException, InterruptedException, BlueprintParserException,
+ SdcArtifactInstallerException {
+ LoopTemplate newLoopTemplate = new LoopTemplate();
+ newLoopTemplate.setBlueprint(blueprintArtifact.getDcaeBlueprint());
+ newLoopTemplate.setName(LoopTemplate.generateLoopTemplateName(csar.getSdcNotification().getServiceName(),
+ csar.getSdcNotification().getServiceVersion(),
+ blueprintArtifact.getResourceAttached().getResourceInstanceName(),
+ blueprintArtifact.getBlueprintArtifactName()));
+ List<BlueprintMicroService> microServicesChain = chainGenerator
+ .getChainOfMicroServices(BlueprintParser.getMicroServices(blueprintArtifact.getDcaeBlueprint()));
+ if (microServicesChain.isEmpty()) {
+ microServicesChain = BlueprintParser.fallbackToOneMicroService();
+ }
+ newLoopTemplate.setModelService(service);
+ newLoopTemplate.addLoopElementModels(createMicroServiceModels(blueprintArtifact, microServicesChain));
+ newLoopTemplate.setMaximumInstancesAllowed(0);
+ DcaeInventoryResponse dcaeResponse = queryDcaeToGetServiceTypeId(blueprintArtifact);
+ newLoopTemplate.setDcaeBlueprintId(dcaeResponse.getTypeId());
+ return newLoopTemplate;
+ }
+
+ private HashSet<LoopElementModel> createMicroServiceModels(BlueprintArtifact blueprintArtifact,
+ List<BlueprintMicroService> microServicesChain)
+ throws SdcArtifactInstallerException {
+ HashSet<LoopElementModel> newSet = new HashSet<>();
+ for (BlueprintMicroService microService : microServicesChain) {
+ LoopElementModel loopElementModel =
+ new LoopElementModel(microService.getModelType(), LoopElementModel.MICRO_SERVICE_TYPE,
+ null);
+ newSet.add(loopElementModel);
+ PolicyModel newPolicyModel = policyEngineServices.createPolicyModelFromPolicyEngine(microService);
+ if (newPolicyModel != null) {
+ loopElementModel.addPolicyModel(newPolicyModel);
+ } else {
+ throw new SdcArtifactInstallerException(
+ "Unable to find the policy specified in the blueprint " +
+ blueprintArtifact.getBlueprintArtifactName() + ") on the Policy Engine:" +
+ microService.getModelType() + "/" + microService.getModelVersion());
+ }
+ }
+ return newSet;
+ }
+
+ /**
+ * Get the service blueprint Id in the Dcae inventory using the SDC UUID.
+ *
+ * @return The DcaeInventoryResponse object containing the dcae values
+ */
+ private DcaeInventoryResponse queryDcaeToGetServiceTypeId(BlueprintArtifact blueprintArtifact)
+ throws IOException, ParseException, InterruptedException {
+ return dcaeInventoryService.getDcaeInformation(blueprintArtifact.getBlueprintArtifactName(),
+ blueprintArtifact.getBlueprintInvariantServiceUuid(),
+ blueprintArtifact.getResourceAttached().getResourceInvariantUUID());
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/Loop.java b/src/main/java/org/onap/clamp/loop/Loop.java
new file mode 100644
index 000000000..36f74221e
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/Loop.java
@@ -0,0 +1,391 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop;
+
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.hibernate.annotations.SortNatural;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.clamp.loop.common.AuditEntity;
+import org.onap.clamp.loop.components.external.DcaeComponent;
+import org.onap.clamp.loop.components.external.ExternalComponent;
+import org.onap.clamp.loop.components.external.PolicyComponent;
+import org.onap.clamp.loop.deploy.DcaeDeployParameters;
+import org.onap.clamp.loop.log.LoopLog;
+import org.onap.clamp.loop.service.Service;
+import org.onap.clamp.loop.template.LoopElementModel;
+import org.onap.clamp.loop.template.LoopTemplate;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.operational.OperationalPolicy;
+
+@Entity
+@Table(name = "loops")
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class Loop extends AuditEntity implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701388642L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "dcae_deployment_id")
+ private String dcaeDeploymentId;
+
+ @Expose
+ @Column(name = "dcae_deployment_status_url")
+ private String dcaeDeploymentStatusUrl;
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "global_properties_json")
+ private JsonObject globalPropertiesJson;
+
+ @Expose
+ @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
+ @JoinColumn(name = "service_uuid")
+ private Service modelService;
+
+ @Expose
+ @Column(nullable = false, name = "last_computed_state")
+ @Enumerated(EnumType.STRING)
+ private LoopState lastComputedState;
+
+ @Expose
+ @Transient
+ private final Map<String, ExternalComponent> components = new HashMap<>();
+
+ @Expose
+ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "loop", orphanRemoval = true)
+ private Set<OperationalPolicy> operationalPolicies = new HashSet<>();
+
+ @Expose
+ @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
+ @JoinTable(name = "loops_to_microservicepolicies", joinColumns = @JoinColumn(name = "loop_name"),
+ inverseJoinColumns = @JoinColumn(name = "microservicepolicy_name"))
+ private Set<MicroServicePolicy> microServicePolicies = new HashSet<>();
+
+ @Expose
+ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "loop", orphanRemoval = true)
+ @SortNatural
+ private SortedSet<LoopLog> loopLogs = new TreeSet<>();
+
+ @Expose
+ @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
+ @JoinColumn(name = "loop_template_name", nullable = false)
+ private LoopTemplate loopTemplate;
+
+ private void initializeExternalComponents() {
+ this.addComponent(new PolicyComponent());
+ this.addComponent(new DcaeComponent());
+ }
+
+ /**
+ * Public constructor.
+ */
+ public Loop() {
+ initializeExternalComponents();
+ }
+
+ /**
+ * Constructor.
+ */
+ public Loop(String name) {
+ this.name = name;
+ this.lastComputedState = LoopState.DESIGN;
+ this.globalPropertiesJson = new JsonObject();
+ initializeExternalComponents();
+ }
+
+ /**
+ * This constructor creates a loop from a loop template.
+ *
+ * @param name The loop name
+ * @param loopTemplate The loop template from which a new loop instance must be created
+ */
+ public Loop(String name, LoopTemplate loopTemplate, ToscaConverterWithDictionarySupport toscaConverter) {
+ this(name);
+ this.setLoopTemplate(loopTemplate);
+ this.setModelService(loopTemplate.getModelService());
+ loopTemplate.getLoopElementModelsUsed().forEach(element -> {
+ if (LoopElementModel.MICRO_SERVICE_TYPE.equals(element.getLoopElementModel().getLoopElementType())) {
+ this.addMicroServicePolicy((MicroServicePolicy) element.getLoopElementModel()
+ .createPolicyInstance(this, toscaConverter));
+ }
+ else if (LoopElementModel.OPERATIONAL_POLICY_TYPE
+ .equals(element.getLoopElementModel().getLoopElementType())) {
+ this.addOperationalPolicy((OperationalPolicy) element.getLoopElementModel()
+ .createPolicyInstance(this, toscaConverter));
+ }
+ });
+ this.setGlobalPropertiesJson(DcaeDeployParameters.getDcaeDeploymentParametersInJson(this));
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDcaeDeploymentId() {
+ return dcaeDeploymentId;
+ }
+
+ void setDcaeDeploymentId(String dcaeDeploymentId) {
+ this.dcaeDeploymentId = dcaeDeploymentId;
+ }
+
+ public String getDcaeDeploymentStatusUrl() {
+ return dcaeDeploymentStatusUrl;
+ }
+
+ void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) {
+ this.dcaeDeploymentStatusUrl = dcaeDeploymentStatusUrl;
+ }
+
+ public LoopState getLastComputedState() {
+ return lastComputedState;
+ }
+
+ void setLastComputedState(LoopState lastComputedState) {
+ this.lastComputedState = lastComputedState;
+ }
+
+ public Set<OperationalPolicy> getOperationalPolicies() {
+ return operationalPolicies;
+ }
+
+ void setOperationalPolicies(Set<OperationalPolicy> operationalPolicies) {
+ this.operationalPolicies = operationalPolicies;
+ }
+
+ public Set<MicroServicePolicy> getMicroServicePolicies() {
+ return microServicePolicies;
+ }
+
+ void setMicroServicePolicies(Set<MicroServicePolicy> microServicePolicies) {
+ this.microServicePolicies = microServicePolicies;
+ }
+
+ public JsonObject getGlobalPropertiesJson() {
+ return globalPropertiesJson;
+ }
+
+ void setGlobalPropertiesJson(JsonObject globalPropertiesJson) {
+ this.globalPropertiesJson = globalPropertiesJson;
+ }
+
+ public Set<LoopLog> getLoopLogs() {
+ return loopLogs;
+ }
+
+ void setLoopLogs(SortedSet<LoopLog> loopLogs) {
+ this.loopLogs = loopLogs;
+ }
+
+ /**
+ * This method adds an operational policy to the loop.
+ *
+ * @param opPolicy the operationalPolicy to add
+ */
+ public void addOperationalPolicy(OperationalPolicy opPolicy) {
+ operationalPolicies.add(opPolicy);
+ opPolicy.setLoop(this);
+ }
+
+ /**
+ * This method removes an operational policy to the loop.
+ *
+ * @param opPolicy the operationalPolicy to add
+ */
+ public void removeOperationalPolicy(OperationalPolicy opPolicy) {
+ operationalPolicies.remove(opPolicy);
+ }
+
+ /**
+ * This method adds an micro service policy to the loop.
+ *
+ * @param microServicePolicy the micro service to add
+ */
+ public void addMicroServicePolicy(MicroServicePolicy microServicePolicy) {
+ microServicePolicies.add(microServicePolicy);
+ microServicePolicy.getUsedByLoops().add(this);
+ }
+
+ public void addLog(LoopLog log) {
+ log.setLoop(this);
+ this.loopLogs.add(log);
+ }
+
+ public Service getModelService() {
+ return modelService;
+ }
+
+ void setModelService(Service modelService) {
+ this.modelService = modelService;
+ }
+
+ public Map<String, ExternalComponent> getComponents() {
+ refreshDcaeComponents();
+ return components;
+ }
+
+ public ExternalComponent getComponent(String componentName) {
+ refreshDcaeComponents();
+ return this.components.get(componentName);
+ }
+
+ public void addComponent(ExternalComponent component) {
+ this.components.put(component.getComponentName(), component);
+ }
+
+ public LoopTemplate getLoopTemplate() {
+ return loopTemplate;
+ }
+
+ public void setLoopTemplate(LoopTemplate loopTemplate) {
+ this.loopTemplate = loopTemplate;
+ }
+
+ private void refreshDcaeComponents() {
+ if (!this.loopTemplate.getUniqueBlueprint()) {
+ this.components.remove("DCAE");
+ for (MicroServicePolicy policy : this.microServicePolicies) {
+ if (!this.components.containsKey("DCAE_" + policy.getName())) {
+ this.addComponent(new DcaeComponent(policy.getName()));
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the operationalPolicy object with the opPolicyName.
+ *
+ * @param opPolicyName The operationalPolicy name
+ * @return The OperationalPolicy object found in loop object
+ */
+ public OperationalPolicy getOperationalPolicy(String opPolicyName) {
+ for (OperationalPolicy operationalPolicy : this.getOperationalPolicies()) {
+ if (operationalPolicy.getName().equals(opPolicyName)) {
+ return operationalPolicy;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the microServicePolicy object with the msPolicyName.
+ *
+ * @param msPolicyName The microServicePolicy name
+ * @return The MicroServicePolicy object found in loop object
+ */
+ public MicroServicePolicy getMicroServicePolicy(String msPolicyName) {
+ for (MicroServicePolicy microServicePolicy : this.getMicroServicePolicies()) {
+ if (microServicePolicy.getName().equals(msPolicyName)) {
+ return microServicePolicy;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Generate the loop name.
+ *
+ * @param serviceName The service name
+ * @param serviceVersion The service version
+ * @param resourceName The resource name
+ * @param blueprintFileName The blueprint file name
+ * @return The generated loop name
+ */
+ public static String generateLoopName(String serviceName, String serviceVersion, String resourceName,
+ String blueprintFileName) {
+ StringBuilder buffer = new StringBuilder("LOOP_").append(serviceName).append("_v").append(serviceVersion)
+ .append("_").append(resourceName).append("_").append(blueprintFileName.replaceAll(".yaml", ""));
+ return buffer.toString().replace('.', '_').replaceAll(" ", "");
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Loop other = (Loop) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ }
+ else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/LoopController.java b/src/main/java/org/onap/clamp/loop/LoopController.java
new file mode 100644
index 000000000..603726f56
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/LoopController.java
@@ -0,0 +1,204 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.clamp.loop;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.reflect.TypeToken;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.List;
+import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.microservice.MicroServicePolicyService;
+import org.onap.clamp.policy.operational.OperationalPolicy;
+import org.onap.clamp.policy.operational.OperationalPolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+@Controller
+public class LoopController {
+
+ private final LoopService loopService;
+
+ private final ToscaConverterWithDictionarySupport toscaConverter;
+
+ private final OperationalPolicyService operationalPolicyService;
+
+ private final MicroServicePolicyService microServicePolicyService;
+
+ private static final Type OPERATIONAL_POLICY_TYPE = new TypeToken<List<OperationalPolicy>>() {
+ }.getType();
+
+ private static final Type MICROSERVICE_POLICY_TYPE = new TypeToken<List<MicroServicePolicy>>() {
+ }.getType();
+
+
+ /**
+ * Constructor.
+ *
+ * @param loopService loopService
+ * @param operationalPolicyService operationalPolicyService
+ * @param microServicePolicyService microServicePolicyService
+ * @param toscaConverter toscaConverter
+ */
+ @Autowired
+ public LoopController(LoopService loopService, OperationalPolicyService operationalPolicyService,
+ MicroServicePolicyService microServicePolicyService,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ this.loopService = loopService;
+ this.toscaConverter = toscaConverter;
+ this.operationalPolicyService = operationalPolicyService;
+ this.microServicePolicyService = microServicePolicyService;
+ }
+
+ public Loop createLoop(String loopName, String templateName) {
+ return loopService.createLoopFromTemplate(loopName, templateName);
+ }
+
+ public List<String> getLoopNames() {
+ return loopService.getClosedLoopNames();
+ }
+
+ public Loop getLoop(String loopName) {
+ return loopService.getLoop(loopName);
+ }
+
+ /**
+ * Update the Operational Policy properties.
+ *
+ * @param loopName The loop name
+ * @param operationalPoliciesJson The new Operational Policy properties
+ * @return The updated loop
+ */
+ public Loop updateOperationalPolicies(String loopName, JsonArray operationalPoliciesJson) {
+ List<OperationalPolicy> operationalPolicies = JsonUtils.GSON_JPA_MODEL.fromJson(operationalPoliciesJson,
+ OPERATIONAL_POLICY_TYPE);
+ return loopService.updateAndSaveOperationalPolicies(loopName, operationalPolicies);
+ }
+
+ /**
+ * Update the whole array of MicroService policies properties.
+ *
+ * @param loopName The loop name
+ * @param microServicePoliciesJson The array of all MicroService policies
+ * properties
+ * @return The updated loop
+ */
+ public Loop updateMicroservicePolicies(String loopName, JsonArray microServicePoliciesJson) {
+ List<MicroServicePolicy> microservicePolicies = JsonUtils.GSON_JPA_MODEL.fromJson(microServicePoliciesJson,
+ MICROSERVICE_POLICY_TYPE);
+ return loopService.updateAndSaveMicroservicePolicies(loopName, microservicePolicies);
+ }
+
+ /**
+ * Update the global properties.
+ *
+ * @param loopName The loop name
+ * @param globalProperties The updated global properties
+ * @return The updated loop
+ */
+ public Loop updateGlobalPropertiesJson(String loopName, JsonObject globalProperties) {
+ return loopService.updateAndSaveGlobalPropertiesJson(loopName, globalProperties);
+ }
+
+ /**
+ * This method add an operational policy to a loop instance.
+ *
+ * @param loopName The loop name
+ * @param policyType The policy model type
+ * @param policyVersion The policy model version
+ * @return The loop modified
+ */
+ public Loop addOperationalPolicy(String loopName, String policyType, String policyVersion) throws IOException {
+ return loopService.addOperationalPolicy(loopName, policyType, policyVersion);
+ }
+
+ /**
+ * This method removes an operational policy from a loop instance.
+ *
+ * @param loopName The loop name
+ * @param policyType The policy model type
+ * @param policyVersion The policy model version
+ * @return The loop modified
+ */
+ public Loop removeOperationalPolicy(String loopName, String policyType, String policyVersion) {
+ return loopService.removeOperationalPolicy(loopName, policyType, policyVersion);
+ }
+
+ /**
+ * This method deletes the loop.
+ *
+ * @param loopName The loop Name
+ */
+ public void deleteLoop(String loopName) {
+ loopService.deleteLoop(loopName);
+ }
+
+ /**
+ * Update one MicroService policy properties.
+ *
+ * @param loopName The loop name
+ * @param newMicroservicePolicy The new MicroService policy properties
+ * @return The updated MicroService policy
+ */
+ public MicroServicePolicy updateMicroservicePolicy(String loopName, MicroServicePolicy newMicroservicePolicy) {
+ return loopService.updateMicroservicePolicy(loopName, newMicroservicePolicy);
+ }
+
+ /**
+ * Refresh the Operational Policy Json representation of the loop.
+ *
+ * @param loop The loop
+ * @param operationalPolicyName The operational policy name that needs a refresh
+ * @return The loop object
+ */
+ public Loop refreshOperationalPolicyJsonRepresentation(Loop loop, String operationalPolicyName) {
+ for (OperationalPolicy operationalPolicy : loop.getOperationalPolicies()) {
+ if (operationalPolicy.getName().equals(operationalPolicyName)) {
+ this.operationalPolicyService
+ .refreshOperationalPolicyJsonRepresentation(operationalPolicy, toscaConverter);
+ }
+ }
+ return loop;
+ }
+
+ /**
+ * Refresh the Config Policy Json representation of the loop.
+ *
+ * @param loop The loop
+ * @param microServicePolicyName The microservice policy name that needs a refresh
+ * @return The loop object
+ */
+ public Loop refreshMicroServicePolicyJsonRepresentation(Loop loop, String microServicePolicyName) {
+ for (MicroServicePolicy microServicePolicy : loop.getMicroServicePolicies()) {
+ if (microServicePolicy.getName().equals(microServicePolicyName)) {
+ this.microServicePolicyService
+ .refreshMicroServicePolicyJsonRepresentation(microServicePolicy, toscaConverter, loop);
+ }
+ }
+ return loop;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/LoopService.java b/src/main/java/org/onap/clamp/loop/LoopService.java
new file mode 100644
index 000000000..5f0822816
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/LoopService.java
@@ -0,0 +1,190 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.clamp.loop;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.EntityNotFoundException;
+import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.clamp.loop.template.LoopTemplatesService;
+import org.onap.clamp.loop.template.PolicyModel;
+import org.onap.clamp.loop.template.PolicyModelsService;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.microservice.MicroServicePolicyService;
+import org.onap.clamp.policy.operational.OperationalPolicy;
+import org.onap.clamp.policy.operational.OperationalPolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class LoopService {
+
+ @Autowired
+ private LoopsRepository loopsRepository;
+
+ @Autowired
+ private MicroServicePolicyService microservicePolicyService;
+
+ @Autowired
+ private OperationalPolicyService operationalPolicyService;
+
+ @Autowired
+ private PolicyModelsService policyModelsService;
+
+ @Autowired
+ private LoopTemplatesService loopTemplateService;
+
+ @Autowired
+ private ToscaConverterWithDictionarySupport toscaConverter;
+
+ Loop saveOrUpdateLoop(Loop loop) {
+ return loopsRepository.save(loop);
+ }
+
+ List<String> getClosedLoopNames() {
+ return loopsRepository.getAllLoopNames();
+ }
+
+ public Loop getLoop(String loopName) {
+ return loopsRepository.findById(loopName).orElse(null);
+ }
+
+ public void deleteLoop(String loopName) {
+ loopsRepository.deleteById(loopName);
+ }
+
+ /**
+ * Creates a Loop Instance from Loop Template Name.
+ *
+ * @param loopName Name of the Loop to be created
+ * @param templateName Loop Template to used for Loop
+ * @return Loop Instance
+ */
+ public Loop createLoopFromTemplate(String loopName, String templateName) {
+ return loopsRepository
+ .save(new Loop(loopName, loopTemplateService.getLoopTemplate(templateName), toscaConverter));
+ }
+
+ /**
+ * This method is used to refresh the DCAE deployment status fields.
+ *
+ * @param loop The loop instance to be modified
+ * @param deploymentId The deployment ID as returned by DCAE
+ * @param deploymentUrl The Deployment URL as returned by DCAE
+ */
+ public void updateDcaeDeploymentFields(Loop loop, String deploymentId, String deploymentUrl) {
+ loop.setDcaeDeploymentId(deploymentId);
+ loop.setDcaeDeploymentStatusUrl(deploymentUrl);
+ loopsRepository.saveAndFlush(loop);
+ }
+
+ public void updateLoopState(Loop loop, String newState) {
+ loop.setLastComputedState(LoopState.valueOf(newState));
+ loopsRepository.save(loop);
+ }
+
+ /**
+ * This method add an operational policy to a loop instance.
+ * This creates an operational policy from the policy model info and not the loop element model
+ *
+ * @param loopName The loop name
+ * @param policyType The policy model type
+ * @param policyVersion The policy model version
+ * @return The loop modified
+ */
+ Loop addOperationalPolicy(String loopName, String policyType, String policyVersion) throws IOException {
+ Loop loop = getLoop(loopName);
+ PolicyModel policyModel = policyModelsService.getPolicyModel(policyType, policyVersion);
+ Set<OperationalPolicy> opPolicySet = loop.getOperationalPolicies();
+ for (OperationalPolicy opPolicy : opPolicySet) {
+ if (opPolicy.getPolicyModel().equals(policyModel)) {
+ throw new IllegalArgumentException(
+ "This type of Operational Policy is already added to the loop. Please choose another one.");
+ }
+ }
+ if (policyModel == null) {
+ return null;
+ }
+ loop.addOperationalPolicy(
+ new OperationalPolicy(loop, loop.getModelService(), policyModel, toscaConverter));
+ return loopsRepository.saveAndFlush(loop);
+ }
+
+ /**
+ * This method remove an operational policy to a loop instance.
+ *
+ * @param loopName The loop name
+ * @param policyType The policy model type
+ * @param policyVersion The policy model version
+ * @return The loop modified
+ */
+ Loop removeOperationalPolicy(String loopName, String policyType, String policyVersion) {
+ Loop loop = getLoop(loopName);
+ PolicyModel policyModel = policyModelsService.getPolicyModel(policyType, policyVersion);
+ if (policyModel == null) {
+ return null;
+ }
+ for (OperationalPolicy opPolicy : loop.getOperationalPolicies()) {
+ if (opPolicy.getPolicyModel().getPolicyModelType().equals(policyType)
+ && opPolicy.getPolicyModel().getVersion().equals(policyVersion)) {
+ loop.removeOperationalPolicy(opPolicy);
+ break;
+ }
+ }
+ return loopsRepository.saveAndFlush(loop);
+ }
+
+ Loop updateAndSaveOperationalPolicies(String loopName, List<OperationalPolicy> newOperationalPolicies) {
+ Loop loop = findClosedLoopByName(loopName);
+ Set<OperationalPolicy> newPolicies = operationalPolicyService.updatePolicies(loop, newOperationalPolicies);
+ loop.setOperationalPolicies(newPolicies);
+ return loopsRepository.save(loop);
+ }
+
+ Loop updateAndSaveMicroservicePolicies(String loopName, List<MicroServicePolicy> newMicroservicePolicies) {
+ Loop loop = findClosedLoopByName(loopName);
+ Set<MicroServicePolicy> newPolicies = microservicePolicyService.updatePolicies(loop, newMicroservicePolicies);
+ loop.setMicroServicePolicies(newPolicies);
+ return loopsRepository.save(loop);
+ }
+
+ Loop updateAndSaveGlobalPropertiesJson(String loopName, JsonObject newGlobalPropertiesJson) {
+ Loop loop = findClosedLoopByName(loopName);
+ loop.setGlobalPropertiesJson(newGlobalPropertiesJson);
+ return loopsRepository.save(loop);
+ }
+
+ MicroServicePolicy updateMicroservicePolicy(String loopName, MicroServicePolicy newMicroservicePolicy) {
+ Loop loop = findClosedLoopByName(loopName);
+ return microservicePolicyService.getAndUpdateMicroServicePolicy(loop, newMicroservicePolicy);
+ }
+
+ private Loop findClosedLoopByName(String loopName) {
+ return loopsRepository.findById(loopName)
+ .orElseThrow(() -> new EntityNotFoundException("Couldn't find closed loop named: " + loopName));
+ }
+}
+
diff --git a/src/main/java/org/onap/clamp/loop/LoopState.java b/src/main/java/org/onap/clamp/loop/LoopState.java
new file mode 100644
index 000000000..4707730ce
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/LoopState.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop;
+
+public enum LoopState {
+ DESIGN, SUBMITTED, DEPLOYED, RUNNING, STOPPED, IN_ERROR, WAITING;
+}
diff --git a/src/main/java/org/onap/clamp/loop/LoopsRepository.java b/src/main/java/org/onap/clamp/loop/LoopsRepository.java
new file mode 100644
index 000000000..aaa49116f
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/LoopsRepository.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface LoopsRepository extends JpaRepository<Loop, String> {
+
+ @Query("SELECT loop.name FROM Loop as loop")
+ List<String> getAllLoopNames();
+}
diff --git a/src/main/java/org/onap/clamp/loop/cds/CdsDataInstaller.java b/src/main/java/org/onap/clamp/loop/cds/CdsDataInstaller.java
new file mode 100644
index 000000000..d18cae1d6
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/cds/CdsDataInstaller.java
@@ -0,0 +1,173 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * 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.clamp.loop.cds;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import org.onap.clamp.clds.client.CdsServices;
+import org.onap.clamp.clds.model.cds.CdsBpWorkFlowListResponse;
+import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.clamp.loop.service.Service;
+import org.onap.clamp.loop.service.ServicesRepository;
+import org.onap.sdc.tosca.parser.enums.SdcTypes;
+import org.onap.sdc.toscaparser.api.NodeTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * This class installs the cds data in the service model properties.
+ * This can be refreshed later on by clicking on the button refresh, when recomputing the json schema.
+ */
+@Component
+public class CdsDataInstaller {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(CdsDataInstaller.class);
+
+ @Autowired
+ CdsServices cdsServices;
+
+ @Autowired
+ ServicesRepository serviceRepository;
+
+ public static final String CONTROLLER_PROPERTIES = "controllerProperties";
+ public static final String SDNC_MODEL_NAME = "sdnc_model_name";
+ public static final String SDNC_MODEL_VERSION = "sdnc_model_version";
+
+ /**
+ * This method installs the service model properties for CDS in the service object given in input.
+ *
+ * @param csar The csar from sdc
+ * @param service the service object already provisioned with csar data
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public Service installCdsServiceProperties(CsarHandler csar, Service service) {
+ // Iterate on all types defined in the tosca lib
+ for (SdcTypes type : SdcTypes.values()) {
+ JsonObject resourcesPropByType = service.getResourceByType(type.getValue());
+ // For each type, get the metadata of each nodetemplate
+ for (NodeTemplate nodeTemplate : csar.getSdcCsarHelper().getServiceNodeTemplateBySdcType(type)) {
+ // get cds artifact information and save in resources Prop
+ if (SdcTypes.PNF == type || SdcTypes.VF == type) {
+ JsonObject controllerProperties = createCdsArtifactProperties(
+ String.valueOf(nodeTemplate.getPropertyValue(SDNC_MODEL_NAME)),
+ String.valueOf(nodeTemplate.getPropertyValue(SDNC_MODEL_VERSION)));
+ if (controllerProperties != null) {
+ resourcesPropByType.getAsJsonObject(nodeTemplate.getName())
+ .add(CONTROLLER_PROPERTIES, controllerProperties);
+ logger.info("Successfully installed the CDS data in Service");
+ }
+ else {
+ logger.warn("Skipping CDS data installation in Service, as sdnc_model_name and "
+ + "sdnc_model_version are not provided in the CSAR");
+ }
+ }
+ }
+ }
+ serviceRepository.save(service);
+
+ return service;
+ }
+
+ /**
+ * This method updates the service model properties for CDS in the service object given in input.
+ *
+ * @param service the service object already provisioned with csar data
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public Service updateCdsServiceProperties(Service service) {
+ // Iterate on all types defined in the tosca lib
+ for (SdcTypes type : SdcTypes.values()) {
+ JsonObject resourcesPropByType = service.getResourceByType(type.getValue());
+ for (String resourceName : resourcesPropByType.keySet()) {
+ // get cds artifact information and save in resources Prop
+ if ((SdcTypes.PNF == type || SdcTypes.VF == type) && resourcesPropByType.getAsJsonObject(resourceName)
+ .getAsJsonObject(CONTROLLER_PROPERTIES) != null) {
+ JsonObject controllerProperties =
+ createCdsArtifactProperties(resourcesPropByType.getAsJsonObject(resourceName)
+ .getAsJsonObject(CONTROLLER_PROPERTIES).get(SDNC_MODEL_NAME)
+ .getAsString(),
+ resourcesPropByType.getAsJsonObject(resourceName)
+ .getAsJsonObject(CONTROLLER_PROPERTIES).get(SDNC_MODEL_VERSION)
+ .getAsString());
+ if (controllerProperties != null) {
+ resourcesPropByType.getAsJsonObject(resourceName)
+ .add(CONTROLLER_PROPERTIES, controllerProperties);
+ }
+ }
+ }
+ }
+ serviceRepository.save(service);
+ logger.info("Successfully updated the CDS data in Service");
+ return service;
+ }
+
+ /**
+ * Retrieve CDS artifacts information from node template and save in resource object.
+ *
+ * @param sdncModelName sdnc model name
+ * @param sdncModelVersion sdnc model version
+ * @return Returns CDS artifacts information
+ */
+ private JsonObject createCdsArtifactProperties(String sdncModelName, String sdncModelVersion) {
+ if (sdncModelName != null && !"null".equals(sdncModelName)
+ && sdncModelVersion != null && !"null".equals(sdncModelVersion)) {
+ JsonObject controllerProperties = new JsonObject();
+ controllerProperties.addProperty(SDNC_MODEL_NAME, sdncModelName);
+ controllerProperties.addProperty(SDNC_MODEL_VERSION, sdncModelVersion);
+
+ CdsBpWorkFlowListResponse response =
+ queryCdsToGetWorkFlowList(sdncModelName, sdncModelVersion);
+ if (response == null) {
+ return controllerProperties;
+ }
+
+ JsonObject workFlowProps = new JsonObject();
+ for (String workFlow : response.getWorkflows()) {
+ logger.info("Found CDS workflow " + workFlow + " for model name " + sdncModelName + " and version "
+ + sdncModelVersion);
+ JsonObject inputs = queryCdsToGetWorkFlowInputProperties(response.getBlueprintName(),
+ response.getVersion(), workFlow);
+ workFlowProps.add(workFlow, inputs);
+ }
+
+ controllerProperties.add("workflows", workFlowProps);
+ return controllerProperties;
+ }
+ return null;
+ }
+
+
+ private CdsBpWorkFlowListResponse queryCdsToGetWorkFlowList(String artifactName, String artifactVersion) {
+ return cdsServices.getBlueprintWorkflowList(artifactName, artifactVersion);
+ }
+
+ private JsonObject queryCdsToGetWorkFlowInputProperties(String artifactName, String artifactVersion,
+ String workFlow) {
+ return cdsServices.getWorkflowInputProperties(artifactName, artifactVersion, workFlow);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/common/AuditEntity.java b/src/main/java/org/onap/clamp/loop/common/AuditEntity.java
new file mode 100644
index 000000000..7ce12ec6b
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/common/AuditEntity.java
@@ -0,0 +1,148 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.loop.common;
+
+import com.google.gson.annotations.Expose;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+/**
+ * This class is the parent of the hibernate entities requiring to be audited.
+ */
+@MappedSuperclass
+@EntityListeners(AuditingEntityListener.class)
+public class AuditEntity {
+
+ @Expose
+ @CreatedDate
+ @Column(name = "created_timestamp", nullable = false, updatable = false)
+ private Instant createdDate;
+
+ @Expose
+ @LastModifiedDate
+ @Column(name = "updated_timestamp", nullable = false)
+ private Instant updatedDate;
+
+ @Expose
+ @LastModifiedBy
+ @Column(name = "updated_by")
+ private String updatedBy;
+
+ @Expose
+ @CreatedBy
+ @Column(name = "created_by")
+ private String createdBy;
+
+ public Instant getCreatedDate() {
+ return createdDate;
+ }
+
+ /**
+ * createdDate setter.
+ *
+ * @param createdDate The created Date object
+ */
+ public void setCreatedDate(Instant createdDate) {
+ if (createdDate != null) {
+ this.createdDate = createdDate.truncatedTo(ChronoUnit.SECONDS);
+ }
+ else {
+ this.createdDate = null;
+ }
+ }
+
+ /**
+ * updatedDate getter.
+ *
+ * @return the updatedDate
+ */
+ public Instant getUpdatedDate() {
+ return updatedDate;
+ }
+
+ /**
+ * updatedDate setter.
+ *
+ * @param updatedDate updatedDate to set
+ */
+ public void setUpdatedDate(Instant updatedDate) {
+ if (updatedDate != null) {
+ this.updatedDate = updatedDate.truncatedTo(ChronoUnit.SECONDS);
+ }
+ else {
+ this.updatedDate = null;
+ }
+ }
+
+ /**
+ * updatedBy getter.
+ *
+ * @return the updatedBy
+ */
+ public String getUpdatedBy() {
+ return updatedBy;
+ }
+
+ /**
+ * updatedBy setter.
+ *
+ * @param updatedBy the updatedBy
+ */
+ public void setUpdatedBy(String updatedBy) {
+ this.updatedBy = updatedBy;
+ }
+
+ /**
+ * createdBy getter.
+ *
+ * @return the createdBy
+ */
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ /**
+ * createdBy setter.
+ *
+ * @param createdBy the createdBy to set
+ */
+ public void setCreatedBy(String createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ /**
+ * Empty constructor.
+ */
+ public AuditEntity() {
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/components/external/DcaeComponent.java b/src/main/java/org/onap/clamp/loop/components/external/DcaeComponent.java
new file mode 100644
index 000000000..8b8547195
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/components/external/DcaeComponent.java
@@ -0,0 +1,253 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.components.external;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.persistence.Transient;
+import org.apache.camel.Exchange;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.onap.clamp.clds.model.dcae.DcaeInventoryResponse;
+import org.onap.clamp.clds.model.dcae.DcaeOperationStatusResponse;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+
+public class DcaeComponent extends ExternalComponent {
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(DcaeComponent.class);
+
+ private static final String DCAE_DEPLOYMENT_PREFIX = "CLAMP_";
+ private static final String DEPLOYMENT_PARAMETER = "dcaeDeployParameters";
+ private static final String DCAE_SERVICETYPE_ID = "serviceTypeId";
+ private static final String DCAE_INPUTS = "inputs";
+ public static final String UNIQUE_BLUEPRINT_PARAMETERS = "uniqueBlueprintParameters";
+
+ private String name;
+
+ public static final ExternalComponentState BLUEPRINT_DEPLOYED = new ExternalComponentState("BLUEPRINT_DEPLOYED",
+ "The DCAE blueprint has been found in the DCAE inventory but not yet instancianted for this loop");
+ public static final ExternalComponentState PROCESSING_MICROSERVICE_INSTALLATION = new ExternalComponentState(
+ "PROCESSING_MICROSERVICE_INSTALLATION", "Clamp has requested DCAE to install the microservices "
+ + "defined in the DCAE blueprint and it's currently processing the request");
+ public static final ExternalComponentState MICROSERVICE_INSTALLATION_FAILED = new ExternalComponentState(
+ "MICROSERVICE_INSTALLATION_FAILED",
+ "Clamp has requested DCAE to install the microservices defined in the DCAE blueprint and it failed");
+ public static final ExternalComponentState MICROSERVICE_INSTALLED_SUCCESSFULLY = new ExternalComponentState(
+ "MICROSERVICE_INSTALLED_SUCCESSFULLY",
+ "Clamp has requested DCAE to install the DCAE blueprint and it has been installed successfully");
+ public static final ExternalComponentState PROCESSING_MICROSERVICE_UNINSTALLATION = new ExternalComponentState(
+ "PROCESSING_MICROSERVICE_UNINSTALLATION", "Clamp has requested DCAE to uninstall the microservices "
+ + "defined in the DCAE blueprint and it's currently processing the request");
+ public static final ExternalComponentState MICROSERVICE_UNINSTALLATION_FAILED = new ExternalComponentState(
+ "MICROSERVICE_UNINSTALLATION_FAILED",
+ "Clamp has requested DCAE to uninstall the microservices defined in the DCAE blueprint and it failed");
+ public static final ExternalComponentState MICROSERVICE_UNINSTALLED_SUCCESSFULLY = new ExternalComponentState(
+ "MICROSERVICE_UNINSTALLED_SUCCESSFULLY",
+ "Clamp has requested DCAE to uninstall the DCAE blueprint and it has been uninstalled successfully");
+ public static final ExternalComponentState IN_ERROR = new ExternalComponentState("IN_ERROR",
+ "There was an error during the request done to DCAE, look at the logs or try again");
+
+ public DcaeComponent() {
+ super(BLUEPRINT_DEPLOYED);
+ this.name = "DCAE";
+ }
+
+ public DcaeComponent(String name) {
+ super(BLUEPRINT_DEPLOYED);
+ this.name = "DCAE_" + name;
+ }
+
+ @Override
+ public String getComponentName() {
+ return name;
+ }
+
+
+ /**
+ * Convert the json response to a DcaeOperationStatusResponse.
+ *
+ * @param responseBody The DCAE response Json paylaod
+ * @return The dcae object provisioned
+ */
+ public static DcaeOperationStatusResponse convertDcaeResponse(String responseBody) {
+ if (responseBody != null && !responseBody.isEmpty()) {
+ return JsonUtils.GSON_JPA_MODEL.fromJson(responseBody, DcaeOperationStatusResponse.class);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Generate the deployment id, it's random.
+ *
+ * @return The deployment id
+ */
+ public static String generateDeploymentId() {
+ return DCAE_DEPLOYMENT_PREFIX + UUID.randomUUID();
+ }
+
+ /**
+ * This method prepare the url returned by DCAE to check the status if fine. It
+ * extracts it from the dcaeResponse.
+ *
+ * @param dcaeResponse The dcae response object
+ * @return the Right Url modified if needed
+ */
+ public static String getStatusUrl(DcaeOperationStatusResponse dcaeResponse) {
+ return dcaeResponse.getLinks().getStatus().replaceAll("http:", "http4:").replaceAll("https:", "https4:");
+ }
+
+ /**
+ * Return the deploy payload for DCAE.
+ *
+ * @param loop The loop object
+ * @return The payload used to send deploy closed loop request
+ */
+ public static String getDeployPayload(Loop loop) {
+ JsonObject globalProp = loop.getGlobalPropertiesJson();
+ JsonObject deploymentProp = globalProp.getAsJsonObject(DEPLOYMENT_PARAMETER).getAsJsonObject(
+ UNIQUE_BLUEPRINT_PARAMETERS);
+
+ String serviceTypeId = loop.getLoopTemplate().getDcaeBlueprintId();
+
+ JsonObject rootObject = new JsonObject();
+ rootObject.addProperty(DCAE_SERVICETYPE_ID, serviceTypeId);
+ if (deploymentProp != null) {
+ rootObject.add(DCAE_INPUTS, deploymentProp);
+ }
+ logger.info("DCAE Deploy payload for unique blueprint: " + rootObject.toString());
+ return rootObject.toString();
+ }
+
+ /**
+ * Return the deploy payload for DCAE.
+ *
+ * @param loop The loop object
+ * @param microServicePolicy The micro service policy
+ * @return The payload used to send deploy closed loop request
+ */
+ public static String getDeployPayload(Loop loop, MicroServicePolicy microServicePolicy) {
+ JsonObject globalProp = loop.getGlobalPropertiesJson();
+ JsonObject deploymentProp =
+ globalProp.getAsJsonObject(DEPLOYMENT_PARAMETER).getAsJsonObject(microServicePolicy.getName());
+
+ String serviceTypeId = microServicePolicy.getDcaeBlueprintId();
+
+ JsonObject rootObject = new JsonObject();
+ rootObject.addProperty(DCAE_SERVICETYPE_ID, serviceTypeId);
+ if (deploymentProp != null) {
+ rootObject.add(DCAE_INPUTS, deploymentProp);
+ }
+ logger.info("DCAE Deploy payload for multiple blueprints: " + rootObject.toString());
+ return rootObject.toString();
+ }
+
+ /**
+ * Return the uninstallation payload for DCAE.
+ *
+ * @param loop The loop object
+ * @return The payload in string (json)
+ */
+ public static String getUndeployPayload(Loop loop) {
+ JsonObject rootObject = new JsonObject();
+ rootObject.addProperty(DCAE_SERVICETYPE_ID, loop.getLoopTemplate().getDcaeBlueprintId());
+ logger.info("DCAE Undeploy payload for unique blueprint: " + rootObject.toString());
+ return rootObject.toString();
+ }
+
+ /**
+ * Return the uninstallation payload for DCAE.
+ *
+ * @param policy The microServicePolicy object
+ * @return The payload in string (json)
+ */
+ public static String getUndeployPayload(MicroServicePolicy policy) {
+ JsonObject rootObject = new JsonObject();
+ rootObject.addProperty(DCAE_SERVICETYPE_ID, policy.getDcaeBlueprintId());
+ logger.info("DCAE Undeploy payload for multiple blueprints: " + rootObject.toString());
+ return rootObject.toString();
+ }
+
+ @Override
+ public ExternalComponentState computeState(Exchange camelExchange) {
+
+ DcaeOperationStatusResponse dcaeResponse = (DcaeOperationStatusResponse) camelExchange.getIn().getExchange()
+ .getProperty("dcaeResponse");
+
+ if (dcaeResponse == null) {
+ setState(BLUEPRINT_DEPLOYED);
+ } else if (dcaeResponse.getOperationType().equals("install") && dcaeResponse.getStatus().equals("succeeded")) {
+ setState(MICROSERVICE_INSTALLED_SUCCESSFULLY);
+ } else if (dcaeResponse.getOperationType().equals("install") && dcaeResponse.getStatus().equals("processing")) {
+ setState(PROCESSING_MICROSERVICE_INSTALLATION);
+ } else if (dcaeResponse.getOperationType().equals("install") && dcaeResponse.getStatus().equals("failed")) {
+ setState(MICROSERVICE_INSTALLATION_FAILED);
+ } else if (dcaeResponse.getOperationType().equals("uninstall")
+ && dcaeResponse.getStatus().equals("succeeded")) {
+ setState(MICROSERVICE_UNINSTALLED_SUCCESSFULLY);
+ } else if (dcaeResponse.getOperationType().equals("uninstall")
+ && dcaeResponse.getStatus().equals("processing")) {
+ setState(PROCESSING_MICROSERVICE_UNINSTALLATION);
+ } else if (dcaeResponse.getOperationType().equals("uninstall") && dcaeResponse.getStatus().equals("failed")) {
+ setState(MICROSERVICE_UNINSTALLATION_FAILED);
+ } else {
+ setState(IN_ERROR);
+ }
+ return this.getState();
+ }
+
+ /**
+ * Convert the json response to a DcaeInventoryResponse.
+ *
+ * @param responseBody The DCAE response Json paylaod
+ * @return list of DcaeInventoryResponse
+ * @throws ParseException In case of issues with the Json parsing
+ */
+ public static List<DcaeInventoryResponse> convertToDcaeInventoryResponse(String responseBody)
+ throws ParseException {
+ JSONParser parser = new JSONParser();
+ JSONObject jsonObj = (JSONObject) parser.parse(responseBody);
+ JSONArray itemsArray = (JSONArray) jsonObj.get("items");
+ Iterator it = itemsArray.iterator();
+ List<DcaeInventoryResponse> inventoryResponseList = new LinkedList<>();
+ while (it.hasNext()) {
+ JSONObject item = (JSONObject) it.next();
+ DcaeInventoryResponse response = JsonUtils.GSON.fromJson(item.toString(), DcaeInventoryResponse.class);
+ inventoryResponseList.add(response);
+ }
+ return inventoryResponseList;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/components/external/ExternalComponent.java b/src/main/java/org/onap/clamp/loop/components/external/ExternalComponent.java
new file mode 100644
index 000000000..2be707fe4
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/components/external/ExternalComponent.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.components.external;
+
+import com.google.gson.annotations.Expose;
+
+import org.apache.camel.Exchange;
+
+/**
+ * Should be abstract but Gson can't instantiate it if it's an abstract.
+ */
+public class ExternalComponent {
+ @Expose
+ private ExternalComponentState componentState;
+
+ public void setState(ExternalComponentState newState) {
+ this.componentState = newState;
+ }
+
+ public ExternalComponentState getState() {
+ return this.componentState;
+ }
+
+ public String getComponentName() {
+ return null;
+ }
+
+ public ExternalComponentState computeState(Exchange camelExchange) {
+ return new ExternalComponentState("INIT", "no desc", 0);
+ }
+
+ public ExternalComponent(ExternalComponentState initialState) {
+ setState(initialState);
+ }
+
+ public ExternalComponent() {
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/components/external/ExternalComponentState.java b/src/main/java/org/onap/clamp/loop/components/external/ExternalComponentState.java
new file mode 100644
index 000000000..a57234af0
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/components/external/ExternalComponentState.java
@@ -0,0 +1,128 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.components.external;
+
+import com.google.gson.annotations.Expose;
+
+/**
+ * This is a transient state reflecting the deployment status of a component. It
+ * can be Policy, DCAE, or whatever... This is object is generic. Clamp is now
+ * stateless, so it triggers the different components at runtime, the status per
+ * component is stored here. The state level is used to re-compute the global
+ * state when multiple sub states are required for that computation (generally
+ * provided sequentially to the method computeState from the camel routes.
+ *
+ */
+public class ExternalComponentState implements Comparable<ExternalComponentState> {
+ @Expose
+ private String stateName;
+ @Expose
+ private String description;
+ private int stateLevel;
+
+ /**
+ * Constructor taking stateName, description and its level.
+ *
+ * @param stateName The stateName in string
+ * @param description The description in string
+ * @param level The level, higher value has higher priority and can't be
+ * down-graded
+ */
+ public ExternalComponentState(String stateName, String description, int level) {
+ this.stateName = stateName;
+ this.description = description;
+ this.stateLevel = level;
+ }
+
+ public ExternalComponentState(String stateName, String description) {
+ this(stateName, description, 0);
+ }
+
+ public ExternalComponentState() {
+ }
+
+ public String getStateName() {
+ return stateName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String toString() {
+ return stateName;
+ }
+
+ public int getLevel() {
+ return stateLevel;
+ }
+
+ public void setLevel(int priority) {
+ this.stateLevel = priority;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((stateName == null) ? 0 : stateName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ExternalComponentState other = (ExternalComponentState) obj;
+ if (stateName == null) {
+ if (other.stateName != null) {
+ return false;
+ }
+ } else if (!stateName.equals(other.stateName)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This method compares this object by using the level of them.
+ *
+ * @param stateToCompare The state to compare to the current object
+ * @return If the one given in input has a higher level than the current object
+ * it returns -1, 1 otherwise and 0 if equals.
+ */
+ @Override
+ public int compareTo(ExternalComponentState stateToCompare) {
+ return Integer.compare(this.getLevel(), stateToCompare.getLevel());
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/components/external/PolicyComponent.java b/src/main/java/org/onap/clamp/loop/components/external/PolicyComponent.java
new file mode 100644
index 000000000..4ea5b7118
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/components/external/PolicyComponent.java
@@ -0,0 +1,195 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.components.external;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.persistence.Transient;
+import org.apache.camel.Exchange;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.operational.OperationalPolicy;
+
+public class PolicyComponent extends ExternalComponent {
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyComponent.class);
+
+ public static final ExternalComponentState IN_ERROR = new ExternalComponentState("IN_ERROR",
+ "There was an error during the sending to policy, the policy engine may be corrupted or inconsistent", 100);
+ public static final ExternalComponentState NOT_SENT = new ExternalComponentState("NOT_SENT",
+ "The policies defined have NOT yet been created on the policy engine", 90);
+ public static final ExternalComponentState SENT = new ExternalComponentState("SENT",
+ "The policies defined have been created but NOT deployed on the policy engine", 50);
+ public static final ExternalComponentState SENT_AND_DEPLOYED = new ExternalComponentState("SENT_AND_DEPLOYED",
+ "The policies defined have been created and deployed on the policy engine", 10);
+ public static final ExternalComponentState UNKNOWN = new ExternalComponentState("UNKNOWN",
+ "The current status is not clear. Need to refresh the status to get the current status.", 0);
+
+ /**
+ * Default constructor.
+ */
+ public PolicyComponent() {
+ /*
+ * We assume it's good by default as we will receive the state for each policy
+ * on by one, each time we increase the level we can't decrease it anymore.
+ * That's why it starts with the lowest one SENT_AND_DEPLOYED.
+ */
+ super(UNKNOWN);
+ }
+
+ @Override
+ public String getComponentName() {
+ return "POLICY";
+ }
+
+ /**
+ * Generates the Json that must be sent to policy to add all policies to Active
+ * PDP group.
+ * @param loop the loop object
+ * @param action POST (to add policy to group) or DELETE (to delete policy from group)
+ * @return The json, payload to send
+ */
+ public static String createPoliciesPayloadPdpGroup(Loop loop, String action) {
+ Map<String, Map<String, List<JsonObject>>> pdpGroupMap = new HashMap<>();
+ for (OperationalPolicy opPolicy : loop.getOperationalPolicies()) {
+ updatePdpGroupMap(opPolicy.getPdpGroup(), opPolicy.getPdpSubgroup(),
+ opPolicy.getName(),
+ "1.0.0", pdpGroupMap);
+ }
+
+ for (MicroServicePolicy msPolicy : loop.getMicroServicePolicies()) {
+ updatePdpGroupMap(msPolicy.getPdpGroup(), msPolicy.getPdpSubgroup(),
+ msPolicy.getName(),
+ "1.0.0", pdpGroupMap);
+ }
+
+ String payload = new GsonBuilder().setPrettyPrinting().create()
+ .toJson(generateActivatePdpGroupPayload(pdpGroupMap, action));
+ logger.info("PdpGroup policy payload: " + payload);
+ return payload;
+ }
+
+ private static void updatePdpGroupMap(String pdpGroup,
+ String pdpSubGroup,
+ String policyName,
+ String policyVersion,
+ Map<String, Map<String,
+ List<JsonObject>>> pdpGroupMap) {
+ JsonObject policyJson = new JsonObject();
+ policyJson.addProperty("name", policyName);
+ policyJson.addProperty("version", policyVersion);
+ Map<String, List<JsonObject>> pdpSubGroupMap;
+ List<JsonObject> policyList;
+ if (pdpGroupMap.get(pdpGroup) == null) {
+ pdpSubGroupMap = new HashMap<>();
+ policyList = new LinkedList<>();
+ }
+ else {
+ pdpSubGroupMap = pdpGroupMap.get(pdpGroup);
+ if (pdpSubGroupMap.get(pdpSubGroup) == null) {
+ policyList = new LinkedList<>();
+ }
+ else {
+ policyList = (List<JsonObject>) pdpSubGroupMap.get(pdpSubGroup);
+ }
+ }
+ policyList.add(policyJson);
+ pdpSubGroupMap.put(pdpSubGroup, policyList);
+ pdpGroupMap.put(pdpGroup, pdpSubGroupMap);
+ }
+
+ private static JsonObject generateActivatePdpGroupPayload(
+ Map<String, Map<String, List<JsonObject>>> pdpGroupMap, String action) {
+ JsonArray payloadArray = new JsonArray();
+ for (Entry<String, Map<String, List<JsonObject>>> pdpGroupInfo : pdpGroupMap.entrySet()) {
+ JsonObject pdpGroupNode = new JsonObject();
+ JsonArray subPdpArray = new JsonArray();
+ pdpGroupNode.addProperty("name", pdpGroupInfo.getKey());
+ pdpGroupNode.add("deploymentSubgroups", subPdpArray);
+
+ for (Entry<String, List<JsonObject>> pdpSubGroupInfo : pdpGroupInfo.getValue().entrySet()) {
+ JsonObject pdpSubGroupNode = new JsonObject();
+ subPdpArray.add(pdpSubGroupNode);
+ pdpSubGroupNode.addProperty("pdpType", pdpSubGroupInfo.getKey());
+ pdpSubGroupNode.addProperty("action", action);
+
+ JsonArray policyArray = new JsonArray();
+ pdpSubGroupNode.add("policies", policyArray);
+
+ for (JsonObject policy : pdpSubGroupInfo.getValue()) {
+ policyArray.add(policy);
+ }
+ }
+ payloadArray.add(pdpGroupNode);
+ }
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.add("groups", payloadArray);
+ return jsonObject;
+ }
+
+ private static ExternalComponentState findNewState(boolean found, boolean deployed) {
+
+ ExternalComponentState newState = NOT_SENT;
+ if (found && deployed) {
+ newState = SENT_AND_DEPLOYED;
+ }
+ else if (found) {
+ newState = SENT;
+ }
+ else if (deployed) {
+ newState = IN_ERROR;
+ }
+ return newState;
+ }
+
+ private static ExternalComponentState mergeStates(ExternalComponentState oldState,
+ ExternalComponentState newState) {
+ return (oldState.compareTo(newState) < 0) ? newState : oldState;
+ }
+
+ /**
+ * This is a method that expect the results of the queries getPolicy and
+ * getPolicyDeployed for a unique policy (op, config, etc ...). It
+ * re-computes the global policy state for each policy results given. Therefore
+ * this method is called multiple times from the camel route and must be reset
+ * for a new global policy state retrieval. The state to compute the global
+ * policy state is stored in this class.
+ */
+ @Override
+ public ExternalComponentState computeState(Exchange camelExchange) {
+ this.setState(mergeStates(this.getState(),
+ findNewState((boolean) camelExchange.getIn().getExchange().getProperty("policyFound"),
+ (boolean) camelExchange.getIn().getExchange().getProperty("policyDeployed"))));
+ return this.getState();
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/deploy/DcaeDeployParameters.java b/src/main/java/org/onap/clamp/loop/deploy/DcaeDeployParameters.java
new file mode 100644
index 000000000..65506a479
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/deploy/DcaeDeployParameters.java
@@ -0,0 +1,119 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.deploy;
+
+import com.google.gson.JsonObject;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.loop.components.external.DcaeComponent;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * To decode the bluprint input parameters.
+ */
+public class DcaeDeployParameters {
+
+ private static LinkedHashMap<String, JsonObject> init(Loop loop) {
+ LinkedHashMap<String, JsonObject> deploymentParamMap = new LinkedHashMap<>();
+ Set<MicroServicePolicy> microServiceList = loop.getMicroServicePolicies();
+
+ for (MicroServicePolicy microService : microServiceList) {
+ deploymentParamMap.put(microService.getName(),
+ generateDcaeDeployParameter(microService));
+ }
+ return deploymentParamMap;
+ }
+
+ private static JsonObject generateDcaeDeployParameter(MicroServicePolicy microService) {
+ return generateDcaeDeployParameter(microService.getLoopElementModel().getBlueprint(),
+ microService.getName());
+ }
+
+ private static JsonObject generateDcaeDeployParameter(String blueprint, String policyId) {
+ JsonObject deployJsonBody = new JsonObject();
+ Yaml yaml = new Yaml();
+ Map<String, Object> inputsNodes = ((Map<String, Object>) ((Map<String, Object>) yaml
+ .load(blueprint)).get("inputs"));
+ inputsNodes.entrySet().stream().filter(e -> !e.getKey().contains("policy_id")).forEach(elem -> {
+ Object defaultValue = ((Map<String, Object>) elem.getValue()).get("default");
+ if (defaultValue != null) {
+ addPropertyToNode(deployJsonBody, elem.getKey(), defaultValue);
+ }
+ else {
+ deployJsonBody.addProperty(elem.getKey(), "");
+ }
+ });
+ deployJsonBody.addProperty("policy_id", policyId);
+ return deployJsonBody;
+ }
+
+ private static void addPropertyToNode(JsonObject node, String key, Object value) {
+ if (value instanceof String) {
+ node.addProperty(key, (String) value);
+ }
+ else if (value instanceof Number) {
+ node.addProperty(key, (Number) value);
+ }
+ else if (value instanceof Boolean) {
+ node.addProperty(key, (Boolean) value);
+ }
+ else if (value instanceof Character) {
+ node.addProperty(key, (Character) value);
+ }
+ else {
+ node.addProperty(key, JsonUtils.GSON.toJson(value));
+ }
+ }
+
+ /**
+ * Convert the object in Json.
+ *
+ * @return The deploymentParameters in Json
+ */
+ public static JsonObject getDcaeDeploymentParametersInJson(Loop loop) {
+ JsonObject globalProperties = new JsonObject();
+ JsonObject deployParamJson = new JsonObject();
+ if (loop.getLoopTemplate().getUniqueBlueprint()) {
+ // Normally the unique blueprint could contain multiple microservices but then we can't guess
+ // the policy id params that will be used, so here we expect only one by default.
+ deployParamJson.add(DcaeComponent.UNIQUE_BLUEPRINT_PARAMETERS,
+ generateDcaeDeployParameter(loop.getLoopTemplate().getBlueprint(),
+ ((MicroServicePolicy) loop.getMicroServicePolicies().toArray()[0]).getName()));
+
+ }
+ else {
+ LinkedHashMap<String, JsonObject> deploymentParamMap = init(loop);
+ for (Map.Entry<String, JsonObject> mapElement : deploymentParamMap.entrySet()) {
+ deployParamJson.add(mapElement.getKey(), mapElement.getValue());
+ }
+ }
+ globalProperties.add("dcaeDeployParameters", deployParamJson);
+ return globalProperties;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/log/LogType.java b/src/main/java/org/onap/clamp/loop/log/LogType.java
new file mode 100644
index 000000000..13d9dccf8
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/log/LogType.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.log;
+
+public enum LogType {
+ INFO, WARNING, ERROR;
+}
diff --git a/src/main/java/org/onap/clamp/loop/log/LoopLog.java b/src/main/java/org/onap/clamp/loop/log/LoopLog.java
new file mode 100644
index 000000000..e49598879
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/log/LoopLog.java
@@ -0,0 +1,196 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.log;
+
+import com.google.gson.annotations.Expose;
+
+import java.io.Serializable;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.onap.clamp.loop.Loop;
+
+/**
+ * This class holds the logs created by the Clamp Backend. The Instant is always
+ * rounded to the nearest second as the nano seconds can't be stored in the
+ * database. The logs can be therefore exposed to the UI or the client doing
+ * some GET Loop on the backend.
+ *
+ */
+@Entity
+@Table(name = "loop_logs")
+public class LoopLog implements Serializable, Comparable<LoopLog> {
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 1988276670074437631L;
+
+ @Expose
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @Expose
+ @Column(name = "log_type", nullable = false)
+ @Enumerated(EnumType.STRING)
+ private LogType logType;
+
+ @Expose
+ @Column(name = "log_component", nullable = false)
+ private String logComponent;
+
+ @Expose
+ @Column(name = "message", columnDefinition = "MEDIUMTEXT", nullable = false)
+ private String message;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "loop_id", nullable = false)
+ private Loop loop;
+
+ @Expose
+ @Column(name = "log_instant", nullable = false)
+ private Instant logInstant = Instant.now().truncatedTo(ChronoUnit.SECONDS);
+
+ public LoopLog() {
+ }
+
+ /**
+ * Constructor For LoopLog taking message and logtype, logComponent and loop
+ * reference.
+ *
+ * @param message The message as string
+ * @param logType Type like INFO, WARN, DEBUG
+ * @param logComponent A String with DCAE, POLICY, CLAMP ,etc...
+ * @param loop The loop object that this log is about
+ */
+ public LoopLog(String message, LogType logType, String logComponent, Loop loop) {
+ this.message = message;
+ this.logType = logType;
+ this.loop = loop;
+ this.logComponent = logComponent;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public LogType getLogType() {
+ return logType;
+ }
+
+ public void setLogType(LogType logType) {
+ this.logType = logType;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Loop getLoop() {
+ return loop;
+ }
+
+ public void setLoop(Loop loop) {
+ this.loop = loop;
+ }
+
+ public Instant getLogInstant() {
+ return logInstant;
+ }
+
+ public void setLogInstant(Instant logInstant) {
+ this.logInstant = logInstant.truncatedTo(ChronoUnit.SECONDS);
+ }
+
+ public String getLogComponent() {
+ return logComponent;
+ }
+
+ public void setLogComponent(String logComponent) {
+ this.logComponent = logComponent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LoopLog other = (LoopLog) obj;
+ if (id == null) {
+ if (other.id != null) {
+ return false;
+ }
+ } else if (!id.equals(other.id)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int compareTo(LoopLog arg0) {
+ // Reverse it, so that by default we have the latest
+ if (getId() == null) {
+ return 1;
+ }
+ if (arg0.getId() == null) {
+ return -1;
+ }
+ return arg0.getId().compareTo(this.getId());
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/log/LoopLogRepository.java b/src/main/java/org/onap/clamp/loop/log/LoopLogRepository.java
new file mode 100644
index 000000000..0b3c34ec0
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/log/LoopLogRepository.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.log;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface LoopLogRepository extends JpaRepository<LoopLog, Long> {
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/log/LoopLogService.java b/src/main/java/org/onap/clamp/loop/log/LoopLogService.java
new file mode 100644
index 000000000..d02d0b278
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/log/LoopLogService.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.clamp.loop.log;
+
+import org.onap.clamp.loop.Loop;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class LoopLogService {
+
+ private final LoopLogRepository repository;
+
+ @Autowired
+ public LoopLogService(LoopLogRepository repository) {
+ this.repository = repository;
+ }
+
+ public void addLog(String message, String logType, Loop loop) {
+ this.addLogForComponent(message, logType, "CLAMP", loop);
+ }
+
+ public void addLogForComponent(String message, String logType, String component, Loop loop) {
+ loop.addLog(repository.save(new LoopLog(message, LogType.valueOf(logType), component, loop)));
+ }
+
+ public boolean isExisting(Long logId) {
+ return repository.existsById(logId);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java b/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java
new file mode 100644
index 000000000..c43f2cb6d
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java
@@ -0,0 +1,129 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * 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.clamp.loop.service;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import java.util.Map.Entry;
+import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.sdc.tosca.parser.api.IEntityDetails;
+import org.onap.sdc.tosca.parser.elements.queries.EntityQuery;
+import org.onap.sdc.tosca.parser.elements.queries.TopologyTemplateQuery;
+import org.onap.sdc.tosca.parser.enums.EntityTemplateType;
+import org.onap.sdc.tosca.parser.enums.SdcTypes;
+import org.onap.sdc.toscaparser.api.NodeTemplate;
+import org.onap.sdc.toscaparser.api.Property;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+@Qualifier("csarInstaller")
+public class CsarServiceInstaller {
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarServiceInstaller.class);
+
+ @Autowired
+ ServicesRepository serviceRepository;
+
+ /**
+ * Install the Service from the csar.
+ *
+ * @param csar The Csar Handler
+ * @return The service object
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public Service installTheService(CsarHandler csar) {
+ logger.info("Start to install the Service from csar");
+ JsonObject serviceDetails = JsonUtils.GSON.fromJson(
+ JsonUtils.GSON.toJson(csar.getSdcCsarHelper().getServiceMetadataAllProperties()), JsonObject.class);
+
+ // Add properties details for each type, VfModule, VF, VFC, ....
+ JsonObject resourcesProp = createServicePropertiesByType(csar);
+ resourcesProp.add("VFModule", createVfModuleProperties(csar));
+
+ Service modelService = new Service(serviceDetails, resourcesProp,
+ csar.getSdcNotification().getServiceVersion());
+
+ serviceRepository.save(modelService);
+ logger.info("Successfully installed the Service");
+ return modelService;
+ }
+
+ private JsonObject createServicePropertiesByType(CsarHandler csar) {
+ JsonObject resourcesProp = new JsonObject();
+ // Iterate on all types defined in the tosca lib
+ for (SdcTypes type : SdcTypes.values()) {
+ JsonObject resourcesPropByType = new JsonObject();
+ // For each type, get the metadata of each nodetemplate
+ for (NodeTemplate nodeTemplate : csar.getSdcCsarHelper().getServiceNodeTemplateBySdcType(type)) {
+ resourcesPropByType.add(nodeTemplate.getName(),
+ JsonUtils.GSON.toJsonTree(nodeTemplate.getMetaData().getAllProperties()));
+ }
+ resourcesProp.add(type.getValue(), resourcesPropByType);
+ }
+ return resourcesProp;
+ }
+
+ private static JsonObject createVfModuleProperties(CsarHandler csar) {
+ JsonObject vfModuleProps = new JsonObject();
+ // Loop on all Groups defined in the service (VFModule entries type:
+ // org.openecomp.groups.VfModule)
+ for (IEntityDetails entity : csar.getSdcCsarHelper().getEntity(
+ EntityQuery.newBuilder(EntityTemplateType.GROUP).build(),
+ TopologyTemplateQuery.newBuilder(SdcTypes.SERVICE).build(), false)) {
+ // Get all metadata info
+ JsonObject allVfProps = (JsonObject) JsonUtils.GSON.toJsonTree(entity.getMetadata().getAllProperties());
+ vfModuleProps.add(entity.getMetadata().getAllProperties().get("vfModuleModelName"), allVfProps);
+ // now append the properties section so that we can also have isBase,
+ // volume_group, etc ... fields under the VFmodule name
+ for (Entry<String, Property> additionalProp : entity.getProperties().entrySet()) {
+ allVfProps.add(additionalProp.getValue().getName(),
+ JsonUtils.GSON.toJsonTree(additionalProp.getValue().getValue()));
+ }
+ }
+ return vfModuleProps;
+ }
+
+ /**
+ * Verify whether Service in Csar is deployed.
+ *
+ * @param csar The Csar Handler
+ * @return The flag indicating whether Service is deployed
+ * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
+ */
+ public boolean isServiceAlreadyDeployed(CsarHandler csar) throws SdcArtifactInstallerException {
+ boolean alreadyInstalled = true;
+ JsonObject serviceDetails = JsonUtils.GSON.fromJson(
+ JsonUtils.GSON.toJson(csar.getSdcCsarHelper().getServiceMetadataAllProperties()), JsonObject.class);
+ alreadyInstalled = serviceRepository.existsById(serviceDetails.get("UUID").getAsString());
+
+ return alreadyInstalled;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/service/Service.java b/src/main/java/org/onap/clamp/loop/service/Service.java
new file mode 100644
index 000000000..338032a16
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/service/Service.java
@@ -0,0 +1,168 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.service;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
+
+@Entity
+@Table(name = "services")
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class Service implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = 1331119060272760758L;
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(Service.class);
+
+ @Id
+ @Column(name = "service_uuid", unique = true)
+ private String serviceUuid;
+
+ @Column(nullable = false, name = "name")
+ private String name;
+
+ @Column(name = "version")
+ private String version;
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "service_details")
+ private JsonObject serviceDetails;
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "resource_details")
+ private JsonObject resourceDetails;
+
+ /**
+ * Default constructor for serialization.
+ */
+ public Service() {
+ }
+
+ /**
+ * Constructor with string.
+ */
+ public Service(String serviceDetails, String resourceDetails) {
+ JsonObject serviceDetailsJson = JsonUtils.GSON.fromJson(serviceDetails, JsonObject.class);
+ this.name = serviceDetailsJson.get("name").getAsString();
+ this.serviceUuid = serviceDetailsJson.get("UUID").getAsString();
+ this.serviceDetails = serviceDetailsJson;
+ this.resourceDetails = JsonUtils.GSON.fromJson(resourceDetails, JsonObject.class);
+ }
+
+ /**
+ * Constructor with Json Object.
+ */
+ public Service(JsonObject serviceDetails, JsonObject resourceDetails, String version) {
+ this.name = serviceDetails.get("name").getAsString();
+ this.serviceUuid = serviceDetails.get("UUID").getAsString();
+ this.serviceDetails = serviceDetails;
+ this.resourceDetails = resourceDetails;
+ this.version = version;
+ }
+
+ public String getServiceUuid() {
+ return serviceUuid;
+ }
+
+ public JsonObject getServiceDetails() {
+ return serviceDetails;
+ }
+
+ public JsonObject getResourceDetails() {
+ return resourceDetails;
+ }
+
+ public JsonObject getResourceByType(String type) {
+ return (JsonObject) resourceDetails.get(type);
+ }
+
+ /**
+ * Name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Version getter.
+ *
+ * @return the version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((serviceUuid == null) ? 0 : serviceUuid.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Service other = (Service) obj;
+ if (serviceUuid == null) {
+ if (other.serviceUuid != null) {
+ return false;
+ }
+ }
+ else if (!serviceUuid.equals(other.serviceUuid)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/service/ServicesRepository.java b/src/main/java/org/onap/clamp/loop/service/ServicesRepository.java
new file mode 100644
index 000000000..fe5ba8ed0
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/service/ServicesRepository.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.loop.service;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ServicesRepository extends JpaRepository<Service, String> {
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/LoopElementModel.java b/src/main/java/org/onap/clamp/loop/template/LoopElementModel.java
new file mode 100644
index 000000000..70cdbe233
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/LoopElementModel.java
@@ -0,0 +1,298 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import org.hibernate.annotations.SortNatural;
+import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.loop.common.AuditEntity;
+import org.onap.clamp.policy.Policy;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.operational.OperationalPolicy;
+
+/**
+ * This class represents a micro service/operational/... model for a loop template.
+ * So it's an element in the flow (a box shown in the loop).
+ */
+
+@Entity
+@Table(name = "loop_element_models")
+public class LoopElementModel extends AuditEntity implements Serializable {
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701376645L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "dcae_blueprint_id")
+ private String dcaeBlueprintId;
+
+ /**
+ * Here we store the blueprint coming from DCAE, it can be null if this is not a micro service model.
+ */
+ @Column(columnDefinition = "MEDIUMTEXT", name = "blueprint_yaml")
+ private String blueprint;
+
+ public static final String MICRO_SERVICE_TYPE = "MICRO_SERVICE_TYPE";
+ public static final String OPERATIONAL_POLICY_TYPE = "OPERATIONAL_POLICY_TYPE";
+ /**
+ * The type of element.
+ */
+ @Expose
+ @Column(nullable = false, name = "loop_element_type")
+ private String loopElementType;
+
+ /**
+ * This variable is used to display the micro-service name in the SVG.
+ */
+ @Expose
+ @Column(name = "short_name")
+ private String shortName;
+
+ /**
+ * This variable is used to store the type mentioned in the micro-service
+ * blueprint.
+ */
+ @Expose
+ @ManyToMany(
+ fetch = FetchType.EAGER,
+ cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
+ @JoinTable(
+ name = "loopelementmodels_to_policymodels",
+ joinColumns = @JoinColumn(name = "loop_element_name", referencedColumnName = "name"),
+ inverseJoinColumns = {
+ @JoinColumn(name = "policy_model_type", referencedColumnName = "policy_model_type"),
+ @JoinColumn(name = "policy_model_version", referencedColumnName = "version")})
+ @SortNatural
+ private SortedSet<PolicyModel> policyModels = new TreeSet<>();
+
+ @OneToMany(fetch = FetchType.LAZY, mappedBy = "loopElementModel", orphanRemoval = true)
+ private Set<LoopTemplateLoopElementModel> usedByLoopTemplates = new HashSet<>();
+
+ /**
+ * policyModels getter.
+ *
+ * @return the policyModel
+ */
+ public SortedSet<PolicyModel> getPolicyModels() {
+ return policyModels;
+ }
+
+ /**
+ * Method to add a new policyModel to the list.
+ *
+ * @param policyModel The policy model
+ */
+ public void addPolicyModel(PolicyModel policyModel) {
+ policyModels.add(policyModel);
+ policyModel.getUsedByElementModels().add(this);
+ }
+
+ /**
+ * name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * blueprint getter.
+ *
+ * @return the blueprint
+ */
+ public String getBlueprint() {
+ return blueprint;
+ }
+
+ /**
+ * blueprint setter.
+ *
+ * @param blueprint the blueprint to set
+ */
+ public void setBlueprint(String blueprint) {
+ this.blueprint = blueprint;
+ }
+
+ /**
+ * dcaeBlueprintId getter.
+ *
+ * @return the dcaeBlueprintId
+ */
+ public String getDcaeBlueprintId() {
+ return dcaeBlueprintId;
+ }
+
+ /**
+ * dcaeBlueprintId setter.
+ *
+ * @param dcaeBlueprintId the dcaeBlueprintId to set
+ */
+ public void setDcaeBlueprintId(String dcaeBlueprintId) {
+ this.dcaeBlueprintId = dcaeBlueprintId;
+ }
+
+ /**
+ * loopElementType getter.
+ *
+ * @return the loopElementType
+ */
+ public String getLoopElementType() {
+ return loopElementType;
+ }
+
+ /**
+ * loopElementType setter.
+ *
+ * @param loopElementType the loopElementType to set
+ */
+ public void setLoopElementType(String loopElementType) {
+ this.loopElementType = loopElementType;
+ }
+
+ /**
+ * shortName getter.
+ *
+ * @return the shortName
+ */
+ public String getShortName() {
+ return shortName;
+ }
+
+ /**
+ * @param shortName the shortName to set.
+ */
+ public void setShortName(String shortName) {
+ this.shortName = shortName;
+ }
+
+ /**
+ * usedByLoopTemplates getter.
+ *
+ * @return the usedByLoopTemplates
+ */
+ public Set<LoopTemplateLoopElementModel> getUsedByLoopTemplates() {
+ return usedByLoopTemplates;
+ }
+
+ /**
+ * Default constructor for serialization.
+ */
+ public LoopElementModel() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The name id
+ * @param loopElementType The type of loop element
+ * @param blueprint The blueprint defined for dcae that contains the
+ * policy type to use
+ */
+ public LoopElementModel(String name, String loopElementType, String blueprint) {
+ this.name = name;
+ this.loopElementType = loopElementType;
+ this.blueprint = blueprint;
+ }
+
+ /**
+ * Create a policy instance from the current loop element model.
+ *
+ * @return A Policy object.
+ */
+ public Policy createPolicyInstance(Loop loop, ToscaConverterWithDictionarySupport toscaConverter) {
+ if (LoopElementModel.MICRO_SERVICE_TYPE.equals(this.getLoopElementType())) {
+ return new MicroServicePolicy(loop, loop.getModelService(), this, toscaConverter);
+ }
+ else if (LoopElementModel.OPERATIONAL_POLICY_TYPE.equals(this.getLoopElementType())) {
+ return new OperationalPolicy(loop, loop.getModelService(), this, toscaConverter);
+ }
+ else {
+ return null;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LoopElementModel other = (LoopElementModel) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ }
+ else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/LoopElementModelsRepository.java b/src/main/java/org/onap/clamp/loop/template/LoopElementModelsRepository.java
new file mode 100644
index 000000000..27b82189c
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/LoopElementModelsRepository.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.template;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface LoopElementModelsRepository extends JpaRepository<LoopElementModel, String> {
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplate.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplate.java
new file mode 100644
index 000000000..6f896f3d4
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplate.java
@@ -0,0 +1,341 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Convert;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import org.hibernate.annotations.SortNatural;
+import org.onap.clamp.loop.common.AuditEntity;
+import org.onap.clamp.loop.service.Service;
+
+@Entity
+@Table(name = "loop_templates")
+public class LoopTemplate extends AuditEntity implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701388642L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "dcae_blueprint_id")
+ private String dcaeBlueprintId;
+
+ /**
+ * This field is used when we have a blueprint defining all microservices. The
+ * other option would be to have independent blueprint for each microservices.
+ * In that case they are stored in each MicroServiceModel
+ */
+ @Column(columnDefinition = "MEDIUMTEXT", name = "blueprint_yaml")
+ private String blueprint;
+
+ @Expose
+ @OneToMany(
+ cascade = CascadeType.ALL,
+ fetch = FetchType.EAGER,
+ mappedBy = "loopTemplate",
+ orphanRemoval = true)
+ @SortNatural
+ private SortedSet<LoopTemplateLoopElementModel> loopElementModelsUsed = new TreeSet<>();
+
+ @Expose
+ @ManyToOne(
+ fetch = FetchType.EAGER,
+ cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
+ @JoinColumn(name = "service_uuid")
+ private Service modelService;
+
+ @Expose
+ @Column(name = "maximum_instances_allowed")
+ private Integer maximumInstancesAllowed;
+
+ @Expose
+ @Column(name = "unique_blueprint", columnDefinition = "boolean default false")
+ private boolean uniqueBlueprint;
+
+ /**
+ * Type of Loop allowed to be created.
+ */
+ @Expose
+ @Column(name = "allowed_loop_type")
+ @Convert(converter = LoopTypeConvertor.class)
+ private LoopType allowedLoopType = LoopType.CLOSED;
+
+ /**
+ * name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * blueprint getter.
+ *
+ * @return the blueprint
+ */
+ public String getBlueprint() {
+ return blueprint;
+ }
+
+ /**
+ * dcaeBlueprintId getter.
+ *
+ * @return the dcaeBlueprintId
+ */
+ public String getDcaeBlueprintId() {
+ return dcaeBlueprintId;
+ }
+
+ /**
+ * dcaeBlueprintId setter.
+ *
+ * @param dcaeBlueprintId the dcaeBlueprintId to set
+ */
+ public void setDcaeBlueprintId(String dcaeBlueprintId) {
+ this.dcaeBlueprintId = dcaeBlueprintId;
+ }
+
+ /**
+ * blueprint setter.
+ *
+ * @param blueprint the blueprint to set
+ */
+ public void setBlueprint(String blueprint) {
+ this.blueprint = blueprint;
+ if (blueprint == null) {
+ this.uniqueBlueprint = false;
+ } else {
+ this.uniqueBlueprint = true;
+ }
+ }
+
+ /**
+ * loopElementModelsUsed getter.
+ *
+ * @return the loopElementModelsUsed
+ */
+ public SortedSet<LoopTemplateLoopElementModel> getLoopElementModelsUsed() {
+ return loopElementModelsUsed;
+ }
+
+ /**
+ * maximumInstancesAllowed getter.
+ *
+ * @return the maximumInstancesAllowed
+ */
+ public Integer getMaximumInstancesAllowed() {
+ return maximumInstancesAllowed;
+ }
+
+ /**
+ * maximumInstancesAllowed setter.
+ *
+ * @param maximumInstancesAllowed the maximumInstancesAllowed to set
+ */
+ public void setMaximumInstancesAllowed(Integer maximumInstancesAllowed) {
+ this.maximumInstancesAllowed = maximumInstancesAllowed;
+ }
+
+ /**
+ * allowedLoopType getter.
+ *
+ * @return the allowedLoopType Type of Loop allowed to be created
+ */
+ public LoopType getAllowedLoopType() {
+ return allowedLoopType;
+ }
+
+ /**
+ * allowedLoopType setter.
+ *
+ * @param allowedLoopType the allowedLoopType to set
+ */
+ public void setAllowedLoopType(LoopType allowedLoopType) {
+ this.allowedLoopType = allowedLoopType;
+ }
+
+ /**
+ * Add list of loopElements to the current template, each loopElementModel is
+ * added at the end of the list so the flowOrder is computed automatically.
+ *
+ * @param loopElementModels The loopElementModel set to add
+ */
+ public void addLoopElementModels(Set<LoopElementModel> loopElementModels) {
+ for (LoopElementModel loopElementModel : loopElementModels) {
+ addLoopElementModel(loopElementModel);
+ }
+ }
+
+ /**
+ * Add a loopElement to the current template, the loopElementModel is added at
+ * the end of the list so the flowOrder is computed automatically.
+ *
+ * @param loopElementModel The loopElementModel to add
+ */
+ public void addLoopElementModel(LoopElementModel loopElementModel) {
+ this.addLoopElementModel(loopElementModel,this.loopElementModelsUsed.size());
+ }
+
+ /**
+ * Add a loopElement model to the current template, the flow order must be
+ * specified manually.
+ *
+ * @param loopElementModel The loopElementModel to add
+ * @param listPosition The position in the flow
+ */
+ public void addLoopElementModel(LoopElementModel loopElementModel, Integer listPosition) {
+ LoopTemplateLoopElementModel jointEntry =
+ new LoopTemplateLoopElementModel(this, loopElementModel, listPosition);
+ this.loopElementModelsUsed.add(jointEntry);
+ loopElementModel.getUsedByLoopTemplates().add(jointEntry);
+ }
+
+ /**
+ * modelService getter.
+ *
+ * @return the modelService
+ */
+ public Service getModelService() {
+ return modelService;
+ }
+
+ /**
+ * modelService setter.
+ *
+ * @param modelService the modelService to set
+ */
+ public void setModelService(Service modelService) {
+ this.modelService = modelService;
+ }
+
+ /**
+ * uniqueBlueprint getter.
+ *
+ * @return the uniqueBlueprint
+ */
+ public boolean getUniqueBlueprint() {
+ return uniqueBlueprint;
+ }
+
+ /**
+ * Default constructor for serialization.
+ */
+ public LoopTemplate() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The loop template name id
+ * @param blueprint The blueprint containing all microservices (legacy
+ * case)
+ * @param maxInstancesAllowed The maximum number of instances that can be
+ * created from that template
+ * @param service The service associated to that loop template
+ */
+ public LoopTemplate(String name, String blueprint, Integer maxInstancesAllowed, Service service) {
+ this.name = name;
+ this.setBlueprint(blueprint);
+
+ this.maximumInstancesAllowed = maxInstancesAllowed;
+ this.modelService = service;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LoopTemplate other = (LoopTemplate) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Generate the loop template name.
+ *
+ * @param serviceName The service name
+ * @param serviceVersion The service version
+ * @param resourceName The resource name
+ * @param blueprintFileName The blueprint file name
+ * @return The generated loop template name
+ */
+ public static String generateLoopTemplateName(String serviceName, String serviceVersion,
+ String resourceName, String blueprintFileName) {
+ StringBuilder buffer = new StringBuilder("LOOP_TEMPLATE_").append(serviceName).append("_v")
+ .append(serviceVersion).append("_").append(resourceName).append("_")
+ .append(blueprintFileName.replaceAll(".yaml", ""));
+ return buffer.toString().replace('.', '_').replaceAll(" ", "");
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModel.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModel.java
new file mode 100644
index 000000000..aca16bc04
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModel.java
@@ -0,0 +1,194 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+
+import java.io.Serializable;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapsId;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "looptemplates_to_loopelementmodels")
+public class LoopTemplateLoopElementModel implements Serializable, Comparable<LoopTemplateLoopElementModel> {
+
+ /**
+ * Serial ID.
+ */
+ private static final long serialVersionUID = 5924989899078094245L;
+
+ @EmbeddedId
+ private LoopTemplateLoopElementModelId loopTemplateLoopElementModelId;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @MapsId("loopTemplateName")
+ @JoinColumn(name = "loop_template_name")
+ private LoopTemplate loopTemplate;
+
+ @Expose
+ @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
+ @MapsId("loopElementModelName")
+ @JoinColumn(name = "loop_element_model_name")
+ private LoopElementModel loopElementModel;
+
+ @Expose
+ @Column(nullable = false, name = "flow_order")
+ private Integer flowOrder;
+
+ /**
+ * Default constructor for serialization.
+ */
+ public LoopTemplateLoopElementModel() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param loopTemplate The loop template object
+ * @param loopElementModel The loopElementModel object
+ * @param flowOrder The position of the micro service in the flow
+ */
+ public LoopTemplateLoopElementModel(LoopTemplate loopTemplate, LoopElementModel loopElementModel,
+ Integer flowOrder) {
+ this.loopTemplate = loopTemplate;
+ this.loopElementModel = loopElementModel;
+ this.flowOrder = flowOrder;
+ this.loopTemplateLoopElementModelId = new LoopTemplateLoopElementModelId(loopTemplate.getName(),
+ loopElementModel.getName());
+ }
+
+ /**
+ * loopTemplate getter.
+ *
+ * @return the loopTemplate
+ */
+ public LoopTemplate getLoopTemplate() {
+ return loopTemplate;
+ }
+
+ /**
+ * loopTemplate setter.
+ *
+ * @param loopTemplate the loopTemplate to set
+ */
+ public void setLoopTemplate(LoopTemplate loopTemplate) {
+ this.loopTemplate = loopTemplate;
+ }
+
+ /**
+ * loopElementModel getter.
+ *
+ * @return the loopElementModel
+ */
+ public LoopElementModel getLoopElementModel() {
+ return loopElementModel;
+ }
+
+ /**
+ * loopElementModel setter.
+ *
+ * @param loopElementModel the loopElementModel to set
+ */
+ public void setLoopElementModel(LoopElementModel loopElementModel) {
+ this.loopElementModel = loopElementModel;
+ }
+
+ /**
+ * flowOrder getter.
+ *
+ * @return the flowOrder
+ */
+ public Integer getFlowOrder() {
+ return flowOrder;
+ }
+
+ /**
+ * flowOrder setter.
+ *
+ * @param flowOrder the flowOrder to set
+ */
+ public void setFlowOrder(Integer flowOrder) {
+ this.flowOrder = flowOrder;
+ }
+
+ @Override
+ public int compareTo(LoopTemplateLoopElementModel arg0) {
+ // Reverse it, so that by default we have the latest
+ if (getFlowOrder() == null) {
+ return 1;
+ }
+ if (arg0.getFlowOrder() == null) {
+ return -1;
+ }
+ return arg0.getFlowOrder().compareTo(this.getFlowOrder());
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((loopTemplate == null) ? 0 : loopTemplate.hashCode());
+ result = prime * result + ((loopElementModel == null) ? 0 : loopElementModel.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LoopTemplateLoopElementModel other = (LoopTemplateLoopElementModel) obj;
+ if (loopTemplate == null) {
+ if (other.loopTemplate != null) {
+ return false;
+ }
+ } else if (!loopTemplate.equals(other.loopTemplate)) {
+ return false;
+ }
+ if (loopElementModel == null) {
+ if (other.loopElementModel != null) {
+ return false;
+ }
+ } else if (!loopElementModel.equals(other.loopElementModel)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModelId.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModelId.java
new file mode 100644
index 000000000..cac5f088a
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModelId.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class LoopTemplateLoopElementModelId implements Serializable {
+
+ /**
+ * Serial ID.
+ */
+ private static final long serialVersionUID = 4089888115504914773L;
+
+ @Expose
+ @Column(name = "loop_template_name")
+ private String loopTemplateName;
+
+ @Expose
+ @Column(name = "loop_element_model_name")
+ private String loopElementModelName;
+
+ /**
+ * Default constructor for serialization.
+ */
+ public LoopTemplateLoopElementModelId() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param loopTemplateName The loop template name id
+ * @param microServiceModelName THe micro Service name id
+ */
+ public LoopTemplateLoopElementModelId(String loopTemplateName, String microServiceModelName) {
+ this.loopTemplateName = loopTemplateName;
+ this.loopElementModelName = microServiceModelName;
+ }
+
+ /**
+ * loopTemplateName getter.
+ *
+ * @return the loopTemplateName
+ */
+ public String getLoopTemplateName() {
+ return loopTemplateName;
+ }
+
+ /**
+ * loopTemplateName setter.
+ *
+ * @param loopTemplateName the loopTemplateName to set
+ */
+ public void setLoopTemplateName(String loopTemplateName) {
+ this.loopTemplateName = loopTemplateName;
+ }
+
+ /**
+ * microServiceModelName getter.
+ *
+ * @return the microServiceModelName
+ */
+ public String getLoopElementModelName() {
+ return loopElementModelName;
+ }
+
+ /**
+ * loopElementModelName setter.
+ *
+ * @param loopElementModelName the loopElementModelName to set
+ */
+ public void setLoopElementModelName(String loopElementModelName) {
+ this.loopElementModelName = loopElementModelName;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplatesRepository.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplatesRepository.java
new file mode 100644
index 000000000..07f304de7
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplatesRepository.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.template;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface LoopTemplatesRepository extends JpaRepository<LoopTemplate, String> {
+
+ @Query("SELECT looptemplate.name FROM LoopTemplate as looptemplate")
+ List<String> getAllLoopTemplateNames();
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplatesService.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplatesService.java
new file mode 100644
index 000000000..29382137e
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplatesService.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.loop.template;
+
+import java.util.List;
+import org.onap.clamp.clds.sdc.controller.installer.ChainGenerator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class LoopTemplatesService {
+
+ private final LoopTemplatesRepository loopTemplatesRepository;
+
+ @Autowired
+ ChainGenerator chainGenerator;
+
+ /**
+ * Constructor.
+ */
+ @Autowired
+ public LoopTemplatesService(LoopTemplatesRepository loopTemplatesRepository) {
+ this.loopTemplatesRepository = loopTemplatesRepository;
+
+ }
+
+ public LoopTemplate saveOrUpdateLoopTemplate(LoopTemplate loopTemplate) {
+ return loopTemplatesRepository.save(loopTemplate);
+ }
+
+ public List<String> getLoopTemplateNames() {
+ return loopTemplatesRepository.getAllLoopTemplateNames();
+ }
+
+ public List<LoopTemplate> getAllLoopTemplates() {
+ return loopTemplatesRepository.findAll();
+ }
+
+ public LoopTemplate getLoopTemplate(String name) {
+ return loopTemplatesRepository.findById(name).orElse(null);
+ }
+
+ public void deleteLoopTemplate(String name) {
+ loopTemplatesRepository.deleteById(name);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/LoopType.java b/src/main/java/org/onap/clamp/loop/template/LoopType.java
new file mode 100644
index 000000000..ccbc62a83
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/LoopType.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.loop.template;
+
+/**
+ * Enums for AllowedLoopType in LoopTemplate enity.
+ *
+ */
+public enum LoopType {
+ OPEN("OPEN"), CLOSED("CLOSED"), HYBRID("HYBRID");
+
+ private String value;
+
+ private LoopType(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTypeConvertor.java b/src/main/java/org/onap/clamp/loop/template/LoopTypeConvertor.java
new file mode 100644
index 000000000..0b05613cb
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/LoopTypeConvertor.java
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.loop.template;
+
+import java.util.stream.Stream;
+import javax.persistence.AttributeConverter;
+
+/**
+ * Attribute Converter to allow using LoopType Enum values in DB and Java classes.
+ *
+ */
+public class LoopTypeConvertor implements AttributeConverter<LoopType, String> {
+
+ @Override
+ public String convertToDatabaseColumn(LoopType loopType) {
+ if (loopType == null) {
+ return null;
+ }
+ return loopType.getValue();
+ }
+
+ @Override
+ public LoopType convertToEntityAttribute(String value) {
+ if (value == null) {
+ return null;
+ }
+
+ return Stream.of(LoopType.values()).filter(c -> c.getValue().equals(value)).findFirst()
+ .orElseThrow(IllegalArgumentException::new);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/PolicyModel.java b/src/main/java/org/onap/clamp/loop/template/PolicyModel.java
new file mode 100644
index 000000000..3f45d0551
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/PolicyModel.java
@@ -0,0 +1,282 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.template;
+
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.clamp.loop.common.AuditEntity;
+import org.onap.clamp.util.SemanticVersioning;
+
+/**
+ * This class represents the policy model tosca revision that we can have to a
+ * specific microservice.
+ */
+@Entity
+@Table(name = "policy_models")
+@IdClass(PolicyModelId.class)
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class PolicyModel extends AuditEntity implements Serializable, Comparable<PolicyModel> {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522705701376645L;
+
+ /**
+ * This variable is used to store the type mentioned in the micro-service
+ * blueprint.
+ */
+ @Id
+ @Expose
+ @Column(nullable = false, name = "policy_model_type")
+ private String policyModelType;
+
+ /**
+ * Semantic versioning on policy side.
+ */
+ @Id
+ @Expose
+ @Column(name = "version", nullable = false)
+ private String version;
+
+ @Column(columnDefinition = "MEDIUMTEXT", name = "policy_tosca")
+ private String policyModelTosca;
+
+ @Expose
+ @Column(name = "policy_acronym")
+ private String policyAcronym;
+
+ @ManyToMany(mappedBy = "policyModels", fetch = FetchType.EAGER)
+ private Set<LoopElementModel> usedByElementModels = new HashSet<>();
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "policy_pdp_group")
+ private JsonObject policyPdpGroup;
+
+ /**
+ * usedByElementModels getter.
+ *
+ * @return the usedByElementModels
+ */
+ public Set<LoopElementModel> getUsedByElementModels() {
+ return usedByElementModels;
+ }
+
+ /**
+ * policyPdpGroup getter.
+ *
+ * @return the policyPdpGroup
+ */
+ public JsonObject getPolicyPdpGroup() {
+ return policyPdpGroup;
+ }
+
+ /**
+ * policyPdpGroup setter.
+ *
+ * @param policyPdpGroup the policyPdpGroup to set
+ */
+ public void setPolicyPdpGroup(JsonObject policyPdpGroup) {
+ this.policyPdpGroup = policyPdpGroup;
+ }
+
+ /**
+ * policyModelTosca getter.
+ *
+ * @return the policyModelTosca
+ */
+ public String getPolicyModelTosca() {
+ return policyModelTosca;
+ }
+
+ /**
+ * policyModelTosca setter.
+ *
+ * @param policyModelTosca the policyModelTosca to set
+ */
+ public void setPolicyModelTosca(String policyModelTosca) {
+ this.policyModelTosca = policyModelTosca;
+ }
+
+ /**
+ * policyModelType getter.
+ *
+ * @return the modelType
+ */
+ public String getPolicyModelType() {
+ return policyModelType;
+ }
+
+ /**
+ * policyModelType setter.
+ *
+ * @param modelType the modelType to set
+ */
+ public void setPolicyModelType(String modelType) {
+ this.policyModelType = modelType;
+ }
+
+ /**
+ * version getter.
+ *
+ * @return the version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * version setter.
+ *
+ * @param version the version to set
+ */
+ public void setVersion(String version) {
+ // Try to convert it before
+ this.version = version;
+ }
+
+ /**
+ * policyAcronym getter.
+ *
+ * @return the policyAcronym value
+ */
+ public String getPolicyAcronym() {
+ return policyAcronym;
+ }
+
+ /**
+ * policyAcronym setter.
+ *
+ * @param policyAcronym The policyAcronym to set
+ */
+ public void setPolicyAcronym(String policyAcronym) {
+ this.policyAcronym = policyAcronym;
+ }
+
+ /**
+ * Default constructor for serialization.
+ */
+ public PolicyModel() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param policyType The policyType (referenced in the blueprint
+ * @param policyModelTosca The policy tosca model in yaml
+ * @param version the version like 1.0.0
+ * @param policyAcronym Subtype for policy if it exists (could be used by UI)
+ */
+ public PolicyModel(String policyType, String policyModelTosca, String version,
+ String policyAcronym) {
+ this.policyModelType = policyType;
+ this.policyModelTosca = policyModelTosca;
+ this.version = version;
+ this.policyAcronym = policyAcronym;
+ if (this.policyAcronym == null) {
+ this.policyAcronym = createDefaultPolicyAcronym(policyType);
+ }
+ }
+
+ /**
+ * Constructor with acronym generated by default from policyType.
+ *
+ * @param policyType The policyType (referenced in the blueprint
+ * @param policyModelTosca The policy tosca model in yaml
+ * @param version the version like 1.0.0
+ */
+ public PolicyModel(String policyType, String policyModelTosca, String version) {
+ this(policyType, policyModelTosca, version, null);
+ }
+
+ public static String createDefaultPolicyAcronym(String policyType) {
+ String[] policyNameArray = policyType.split("\\.");
+ return policyNameArray[policyNameArray.length - 1];
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((policyModelType == null) ? 0 : policyModelType.hashCode());
+ result = prime * result + ((version == null) ? 0 : version.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PolicyModel other = (PolicyModel) obj;
+ if (policyModelType == null) {
+ if (other.policyModelType != null) {
+ return false;
+ }
+ } else if (!policyModelType.equals(other.policyModelType)) {
+ return false;
+ }
+ if (version == null) {
+ if (other.version != null) {
+ return false;
+ }
+ } else if (!version.equals(other.version)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int compareTo(PolicyModel arg0) {
+
+ if (this.getPolicyModelType().equals(arg0.getPolicyModelType())) {
+ // Reverse it, so that by default we have the latest in they are same model type
+ return SemanticVersioning.compare(arg0.getVersion(), this.version);
+ } else {
+ return this.getPolicyModelType().compareTo(arg0.getPolicyModelType());
+ }
+
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/PolicyModelId.java b/src/main/java/org/onap/clamp/loop/template/PolicyModelId.java
new file mode 100644
index 000000000..c4dd1933b
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/PolicyModelId.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+
+import java.io.Serializable;
+
+public class PolicyModelId implements Serializable {
+
+ /**
+ * Serial Id.
+ */
+ private static final long serialVersionUID = -2846526482064334745L;
+
+ @Expose
+ private String policyModelType;
+
+ @Expose
+ private String version;
+
+ /**
+ * Default constructor for serialization.
+ */
+ public PolicyModelId() {
+
+ }
+
+ /**
+ * Constructor.
+ */
+ public PolicyModelId(String policyModelType, String version) {
+ this.policyModelType = policyModelType;
+ this.version = version;
+ }
+
+ /**
+ * policyModelType getter.
+ *
+ * @return the policyModelType
+ */
+ public String getPolicyModelType() {
+ return policyModelType;
+ }
+
+ /**
+ * policyModelType setter.
+ *
+ * @param policyModelType the policyModelType to set
+ */
+ public void setPolicyModelType(String policyModelType) {
+ this.policyModelType = policyModelType;
+ }
+
+ /**
+ * version getter.
+ *
+ * @return the version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * version setter.
+ *
+ * @param version the version to set
+ */
+ public void setVersion(String version) {
+ this.version = version;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/PolicyModelsRepository.java b/src/main/java/org/onap/clamp/loop/template/PolicyModelsRepository.java
new file mode 100644
index 000000000..a76e386b5
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/PolicyModelsRepository.java
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.loop.template;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface PolicyModelsRepository extends JpaRepository<PolicyModel, PolicyModelId> {
+ @Query("SELECT policymodel.policyModelType FROM PolicyModel as policymodel")
+ List<String> getAllPolicyModelType();
+
+ List<PolicyModel> findByPolicyModelType(String policyModelType);
+}
diff --git a/src/main/java/org/onap/clamp/loop/template/PolicyModelsService.java b/src/main/java/org/onap/clamp/loop/template/PolicyModelsService.java
new file mode 100644
index 000000000..17cf5c1c8
--- /dev/null
+++ b/src/main/java/org/onap/clamp/loop/template/PolicyModelsService.java
@@ -0,0 +1,173 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.loop.template;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.onap.clamp.clds.tosca.ToscaSchemaConstants;
+import org.onap.clamp.clds.tosca.ToscaYamlToJsonConvertor;
+import org.onap.clamp.policy.pdpgroup.PdpGroup;
+import org.onap.clamp.util.SemanticVersioning;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class PolicyModelsService {
+ private final PolicyModelsRepository policyModelsRepository;
+ private ToscaYamlToJsonConvertor toscaYamlToJsonConvertor;
+
+ @Autowired
+ public PolicyModelsService(PolicyModelsRepository policyModelrepo,
+ ToscaYamlToJsonConvertor convertor) {
+ policyModelsRepository = policyModelrepo;
+ toscaYamlToJsonConvertor = convertor;
+ }
+
+ /**
+ * Save or Update Policy Model.
+ *
+ * @param policyModel The policyModel
+ * @return The Policy Model
+ */
+ public PolicyModel saveOrUpdatePolicyModel(PolicyModel policyModel) {
+ return policyModelsRepository.saveAndFlush(policyModel);
+ }
+
+ /**
+ * Verify whether Policy Model exist by ID.
+ *
+ * @param policyModelId The policyModel Id
+ * @return The flag indicates whether Policy Model exist
+ */
+ public boolean existsById(PolicyModelId policyModelId) {
+ return policyModelsRepository.existsById(policyModelId);
+ }
+
+ /**
+ * Creates or updates the Tosca Policy Model.
+ *
+ * @param policyModelTosca The Policymodel object
+ * @return The Policy Model created
+ */
+ public PolicyModel createNewPolicyModelFromTosca(String policyModelTosca) {
+ JsonObject jsonObject = toscaYamlToJsonConvertor.validateAndConvertToJson(policyModelTosca);
+ String policyModelTypeFromTosca = toscaYamlToJsonConvertor.getValueFromMetadata(jsonObject,
+ ToscaSchemaConstants.METADATA_POLICY_MODEL_TYPE);
+ Iterable<PolicyModel> models = getAllPolicyModelsByType(policyModelTypeFromTosca);
+ Collections.sort((List<PolicyModel>) models);
+ PolicyModel newPolicyModel = new PolicyModel(policyModelTypeFromTosca, policyModelTosca,
+ SemanticVersioning.incrementMajorVersion(((ArrayList) models).isEmpty() ? null
+ : ((ArrayList<PolicyModel>) models).get(0).getVersion()),
+ toscaYamlToJsonConvertor.getValueFromMetadata(jsonObject,
+ ToscaSchemaConstants.METADATA_ACRONYM));
+ return saveOrUpdatePolicyModel(newPolicyModel);
+ }
+
+ /**
+ * Update an existing Tosca Policy Model.
+ *
+ * @param policyModelType The policy Model type in Tosca yaml
+ * @param policyModelVersion The policy Version to update
+ * @param policyModelTosca The Policy Model tosca
+ * @return The Policy Model updated
+ */
+ public PolicyModel updatePolicyModelTosca(String policyModelType, String policyModelVersion,
+ String policyModelTosca) {
+ JsonObject jsonObject = toscaYamlToJsonConvertor.validateAndConvertToJson(policyModelTosca);
+ PolicyModel thePolicyModel = getPolicyModel(policyModelType, policyModelVersion);
+ thePolicyModel.setPolicyAcronym(toscaYamlToJsonConvertor.getValueFromMetadata(jsonObject,
+ ToscaSchemaConstants.METADATA_ACRONYM));
+ thePolicyModel.setPolicyModelTosca(policyModelTosca);
+ return saveOrUpdatePolicyModel(thePolicyModel);
+ }
+
+ public List<String> getAllPolicyModelTypes() {
+ return policyModelsRepository.getAllPolicyModelType();
+ }
+
+ public Iterable<PolicyModel> getAllPolicyModels() {
+ return policyModelsRepository.findAll();
+ }
+
+ public PolicyModel getPolicyModel(String type, String version) {
+ return policyModelsRepository.findById(new PolicyModelId(type, version)).orElse(null);
+ }
+
+ public Iterable<PolicyModel> getAllPolicyModelsByType(String type) {
+ return policyModelsRepository.findByPolicyModelType(type);
+ }
+
+ /**
+ * Retrieves the Tosca model Yaml string.
+ *
+ * @param type The Policy Model Type
+ * @param version The policy model version
+ * @return The Tosca model Yaml string
+ */
+ public String getPolicyModelTosca(String type, String version) {
+ return policyModelsRepository.findById(new PolicyModelId(type, version))
+ .orElse(new PolicyModel()).getPolicyModelTosca();
+ }
+
+ /**
+ * This method creates an PolicyModel in Db if it does not exist.
+ *
+ * @param policyModel The policyModel to save
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public PolicyModel savePolicyModelInNewTransaction(PolicyModel policyModel) {
+ return policyModelsRepository.saveAndFlush(policyModel);
+ }
+
+ /**
+ * Update the Pdp Group info in Policy Model DB.
+ *
+ * @param pdpGroupList The list of Pdp Group info received from Policy Engine
+ */
+ public void updatePdpGroupInfo(List<PdpGroup> pdpGroupList) {
+ List<PolicyModel> policyModelList = policyModelsRepository.findAll();
+ for (PolicyModel policyModel : policyModelList) {
+ JsonArray supportedPdpGroups = new JsonArray();
+ for (PdpGroup pdpGroup : pdpGroupList) {
+ JsonObject supportedPdpGroup = pdpGroup.getSupportedSubgroups(
+ policyModel.getPolicyModelType(), policyModel.getVersion());
+ if (supportedPdpGroup != null) {
+ supportedPdpGroups.add(supportedPdpGroup);
+ }
+ }
+
+ if (supportedPdpGroups.size() > 0) {
+ JsonObject supportedPdpJson = new JsonObject();
+ supportedPdpJson.add("supportedPdpGroups", supportedPdpGroups);
+ policyModel.setPolicyPdpGroup(supportedPdpJson);
+ policyModelsRepository.saveAndFlush(policyModel);
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/onap/clamp/policy/Policy.java b/src/main/java/org/onap/clamp/policy/Policy.java
new file mode 100644
index 000000000..d84f2c8a0
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/Policy.java
@@ -0,0 +1,287 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.clamp.policy;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+import javax.persistence.Column;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.json.JSONObject;
+import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.clamp.loop.common.AuditEntity;
+import org.onap.clamp.loop.service.Service;
+import org.onap.clamp.loop.template.LoopElementModel;
+import org.onap.clamp.loop.template.PolicyModel;
+import org.yaml.snakeyaml.Yaml;
+
+@MappedSuperclass
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public abstract class Policy extends AuditEntity {
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(Policy.class);
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "json_representation", nullable = false)
+ private JsonObject jsonRepresentation;
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "configurations_json")
+ private JsonObject configurationsJson;
+
+ /**
+ * This attribute can be null when the user add a policy on the loop instance, not the template.
+ * When null, It therefore indicates that this policy is not by default in the loop template.
+ */
+ @Expose
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "loop_element_model_id")
+ private LoopElementModel loopElementModel;
+
+ @Expose
+ @Column(name = "pdp_group")
+ private String pdpGroup;
+
+ @Expose
+ @Column(name = "pdp_sub_group")
+ private String pdpSubgroup;
+
+ @Expose
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumns({@JoinColumn(name = "policy_model_type", referencedColumnName = "policy_model_type"),
+ @JoinColumn(name = "policy_model_version", referencedColumnName = "version")})
+ private PolicyModel policyModel;
+
+ private JsonObject createJsonFromPolicyTosca() {
+ Map<String, Object> map =
+ new Yaml().load(this.getPolicyModel() != null ? this.getPolicyModel().getPolicyModelTosca() : "");
+ JSONObject jsonObject = new JSONObject(map);
+ return new Gson().fromJson(jsonObject.toString(), JsonObject.class);
+ }
+
+ /**
+ * This method create the policy payload that must be sent to PEF.
+ *
+ * @return A String containing the payload
+ * @throws UnsupportedEncodingException In case of failure
+ */
+ public String createPolicyPayload() throws UnsupportedEncodingException {
+ JsonObject toscaJson = createJsonFromPolicyTosca();
+
+ JsonObject policyPayloadResult = new JsonObject();
+
+ policyPayloadResult.add("tosca_definitions_version", toscaJson.get("tosca_definitions_version"));
+
+ JsonObject topologyTemplateNode = new JsonObject();
+ policyPayloadResult.add("topology_template", topologyTemplateNode);
+
+ JsonArray policiesArray = new JsonArray();
+ topologyTemplateNode.add("policies", policiesArray);
+
+ JsonObject thisPolicy = new JsonObject();
+ policiesArray.add(thisPolicy);
+
+ JsonObject policyDetails = new JsonObject();
+ thisPolicy.add(this.getName(), policyDetails);
+ policyDetails.addProperty("type", this.getPolicyModel().getPolicyModelType());
+ policyDetails.addProperty("type_version", this.getPolicyModel().getVersion());
+ policyDetails.addProperty("version", this.getPolicyModel().getVersion());
+
+ JsonObject policyMetadata = new JsonObject();
+ policyDetails.add("metadata", policyMetadata);
+ policyMetadata.addProperty("policy-id", this.getName());
+
+ policyDetails.add("properties", this.getConfigurationsJson());
+
+ String policyPayload = new GsonBuilder().setPrettyPrinting().create().toJson(policyPayloadResult);
+ logger.info("Policy payload: " + policyPayload);
+ return policyPayload;
+ }
+
+
+ /**
+ * Name getter.
+ *
+ * @return the name
+ */
+ public abstract String getName();
+
+ /**
+ * Name setter.
+ */
+ public abstract void setName(String name);
+
+ /**
+ * jsonRepresentation getter.
+ *
+ * @return the jsonRepresentation
+ */
+ public JsonObject getJsonRepresentation() {
+ return jsonRepresentation;
+ }
+
+ /**
+ * jsonRepresentation setter.
+ *
+ * @param jsonRepresentation The jsonRepresentation to set
+ */
+ public void setJsonRepresentation(JsonObject jsonRepresentation) {
+ this.jsonRepresentation = jsonRepresentation;
+ }
+
+ /**
+ * Regenerate the Policy Json Representation.
+ *
+ * @param toscaConverter The tosca converter required to regenerate the json schema
+ * @param serviceModel The service model associated
+ */
+ public abstract void updateJsonRepresentation(ToscaConverterWithDictionarySupport toscaConverter,
+ Service serviceModel);
+
+ /**
+ * policyModel getter.
+ *
+ * @return the policyModel
+ */
+ public PolicyModel getPolicyModel() {
+ return policyModel;
+ }
+
+ /**
+ * policyModel setter.
+ *
+ * @param policyModel The new policyModel
+ */
+ public void setPolicyModel(PolicyModel policyModel) {
+ this.policyModel = policyModel;
+ }
+
+ /**
+ * configurationsJson getter.
+ *
+ * @return The configurationsJson
+ */
+ public JsonObject getConfigurationsJson() {
+ return configurationsJson;
+ }
+
+ /**
+ * configurationsJson setter.
+ *
+ * @param configurationsJson the configurationsJson to set
+ */
+ public void setConfigurationsJson(JsonObject configurationsJson) {
+ this.configurationsJson = configurationsJson;
+ }
+
+ /**
+ * loopElementModel getter.
+ *
+ * @return the loopElementModel
+ */
+ public LoopElementModel getLoopElementModel() {
+ return loopElementModel;
+ }
+
+ /**
+ * loopElementModel setter.
+ *
+ * @param loopElementModel the loopElementModel to set
+ */
+ public void setLoopElementModel(LoopElementModel loopElementModel) {
+ this.loopElementModel = loopElementModel;
+ }
+
+ /**
+ * pdpGroup getter.
+ *
+ * @return the pdpGroup
+ */
+ public String getPdpGroup() {
+ return pdpGroup;
+ }
+
+ /**
+ * pdpGroup setter.
+ *
+ * @param pdpGroup the pdpGroup to set
+ */
+ public void setPdpGroup(String pdpGroup) {
+ this.pdpGroup = pdpGroup;
+ }
+
+ /**
+ * pdpSubgroup getter.
+ *
+ * @return the pdpSubgroup
+ */
+ public String getPdpSubgroup() {
+ return pdpSubgroup;
+ }
+
+ /**
+ * pdpSubgroup setter.
+ *
+ * @param pdpSubgroup the pdpSubgroup to set
+ */
+ public void setPdpSubgroup(String pdpSubgroup) {
+ this.pdpSubgroup = pdpSubgroup;
+ }
+
+ /**
+ * Generate the policy name.
+ *
+ * @param policyType The policy type
+ * @param serviceName The service name
+ * @param serviceVersion The service version
+ * @param resourceName The resource name
+ * @param blueprintFilename The blueprint file name
+ * @return The generated policy name
+ */
+ public static String generatePolicyName(String policyType, String serviceName, String serviceVersion,
+ String resourceName, String blueprintFilename) {
+ StringBuilder buffer = new StringBuilder(policyType).append("_").append(serviceName).append("_v")
+ .append(serviceVersion).append("_").append(resourceName).append("_")
+ .append(blueprintFilename.replaceAll(".yaml", ""));
+ return buffer.toString().replace('.', '_').replaceAll(" ", "");
+ }
+}
diff --git a/src/main/java/org/onap/clamp/policy/PolicyService.java b/src/main/java/org/onap/clamp/policy/PolicyService.java
new file mode 100644
index 000000000..ae15f86da
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/PolicyService.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.clamp.policy;
+
+import java.util.List;
+import java.util.Set;
+
+import org.onap.clamp.loop.Loop;
+
+public interface PolicyService<T extends Policy> {
+
+ Set<T> updatePolicies(Loop loop, List<T> newPolicies);
+
+ boolean isExisting(String policyName);
+}
diff --git a/src/main/java/org/onap/clamp/policy/downloader/PolicyEngineController.java b/src/main/java/org/onap/clamp/policy/downloader/PolicyEngineController.java
new file mode 100644
index 000000000..0c3f677a1
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/downloader/PolicyEngineController.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.policy.downloader;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.time.Instant;
+
+import org.json.simple.parser.ParseException;
+import org.onap.clamp.clds.client.PolicyEngineServices;
+import org.onap.clamp.loop.template.PolicyModelsRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.Scheduled;
+
+/**
+ * This class implements a periodic job that is done in the background to
+ * synchronize policy models available on the policy engine and the clamp
+ * database table PolicyModel.
+ */
+@Configuration
+@Profile("clamp-policy-controller")
+public class PolicyEngineController {
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyEngineController.class);
+ protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
+ public static final String POLICY_RETRY_INTERVAL = "policy.retry.interval";
+ public static final String POLICY_RETRY_LIMIT = "policy.retry.limit";
+
+ private final PolicyEngineServices policyEngineServices;
+
+ private Instant lastInstantExecuted;
+
+ @Autowired
+ public PolicyEngineController(PolicyEngineServices policyEngineService,
+ PolicyModelsRepository policyModelsRepository) {
+ this.policyEngineServices = policyEngineService;
+ }
+
+ @Scheduled(fixedRate = 300000)
+ public synchronized void synchronizeAllPolicies() {
+ policyEngineServices.synchronizeAllPolicies();
+ lastInstantExecuted = Instant.now();
+ }
+
+ public Instant getLastInstantExecuted() {
+ return lastInstantExecuted;
+ }
+
+ @Scheduled(fixedRate = 300000)
+ public synchronized void downloadPdpGroups() throws ParseException {
+ policyEngineServices.downloadPdpGroups();
+ }
+}
diff --git a/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicy.java b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicy.java
new file mode 100644
index 000000000..77627a31a
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicy.java
@@ -0,0 +1,276 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.policy.microservice;
+
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.loop.service.Service;
+import org.onap.clamp.loop.template.LoopElementModel;
+import org.onap.clamp.loop.template.PolicyModel;
+import org.onap.clamp.policy.Policy;
+
+@Entity
+@Table(name = "micro_service_policies")
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class MicroServicePolicy extends Policy implements Serializable {
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 6271238288583332616L;
+
+ @Expose
+ @Id
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "context")
+ private String context;
+
+ @Expose
+ @Column(name = "device_type_scope")
+ private String deviceTypeScope;
+
+ @Expose
+ @Column(name = "shared", nullable = false)
+ private Boolean shared;
+
+ @ManyToMany(mappedBy = "microServicePolicies", fetch = FetchType.EAGER)
+ private Set<Loop> usedByLoops = new HashSet<>();
+
+ @Expose
+ @Column(name = "dcae_deployment_id")
+ private String dcaeDeploymentId;
+
+ @Expose
+ @Column(name = "dcae_deployment_status_url")
+ private String dcaeDeploymentStatusUrl;
+
+ @Expose
+ @Column(name = "dcae_blueprint_id")
+ private String dcaeBlueprintId;
+
+ /**
+ * Constructor for serialization.
+ */
+ public MicroServicePolicy() {
+ }
+
+ /**
+ * The constructor that does not make use of ToscaYamlToJsonConvertor but take
+ * the jsonRepresentation instead.
+ *
+ * @param name The name of the MicroService
+ * @param policyModel The policy model type of the MicroService
+ * @param shared The flag indicate whether the MicroService is
+ * shared
+ * @param jsonRepresentation The UI representation in json format
+ * @param loopElementModel The loop element model from which this instance should be created
+ * @param pdpGroup The Pdp Group info
+ * @param pdpSubgroup The Pdp Subgroup info
+ */
+ public MicroServicePolicy(String name, PolicyModel policyModel, Boolean shared,
+ JsonObject jsonRepresentation, LoopElementModel loopElementModel, String pdpGroup,
+ String pdpSubgroup) {
+ this.name = name;
+ this.setPolicyModel(policyModel);
+ this.shared = shared;
+ this.setJsonRepresentation(jsonRepresentation);
+ this.setLoopElementModel(loopElementModel);
+ this.setPdpGroup(pdpGroup);
+ this.setPdpSubgroup(pdpSubgroup);
+ }
+
+ /**
+ * Constructor with tosca converter.
+ *
+ * @param loop The loop instance
+ * @param service The service model object
+ * @param loopElementModel The loop element model from which this microservice instance is created
+ * @param toscaConverter The tosca converter that will used to convert the tosca policy model
+ */
+ public MicroServicePolicy(Loop loop, Service service, LoopElementModel loopElementModel,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ this(Policy.generatePolicyName("MICROSERVICE", service.getName(), service.getVersion(),
+ loopElementModel.getPolicyModels().first().getPolicyAcronym() + '_'
+ + loopElementModel.getPolicyModels().first().getVersion(),
+ RandomStringUtils.randomAlphanumeric(3)),
+ loopElementModel.getPolicyModels().first(), false, new JsonObject(), loopElementModel, null, null);
+ this.updateJsonRepresentation(toscaConverter, service);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void updateJsonRepresentation(ToscaConverterWithDictionarySupport toscaConverter, Service serviceModel) {
+ this.setJsonRepresentation(
+ toscaConverter.convertToscaToJsonSchemaObject(this.getPolicyModel().getPolicyModelTosca(),
+ this.getPolicyModel().getPolicyModelType(), serviceModel));
+ }
+
+ public Boolean getShared() {
+ return shared;
+ }
+
+ void setShared(Boolean shared) {
+ this.shared = shared;
+ }
+
+ public Set<Loop> getUsedByLoops() {
+ return usedByLoops;
+ }
+
+ void setUsedByLoops(Set<Loop> usedBy) {
+ this.usedByLoops = usedBy;
+ }
+
+ public String getContext() {
+ return context;
+ }
+
+ public void setContext(String context) {
+ this.context = context;
+ }
+
+ public String getDeviceTypeScope() {
+ return deviceTypeScope;
+ }
+
+ public void setDeviceTypeScope(String deviceTypeScope) {
+ this.deviceTypeScope = deviceTypeScope;
+ }
+
+ /**
+ * dcaeDeploymentId getter.
+ *
+ * @return the dcaeDeploymentId
+ */
+ public String getDcaeDeploymentId() {
+ return dcaeDeploymentId;
+ }
+
+ /**
+ * dcaeDeploymentId setter.
+ *
+ * @param dcaeDeploymentId the dcaeDeploymentId to set
+ */
+ public void setDcaeDeploymentId(String dcaeDeploymentId) {
+ this.dcaeDeploymentId = dcaeDeploymentId;
+ }
+
+ /**
+ * dcaeDeploymentStatusUrl getter.
+ *
+ * @return the dcaeDeploymentStatusUrl
+ */
+ public String getDcaeDeploymentStatusUrl() {
+ return dcaeDeploymentStatusUrl;
+ }
+
+ /**
+ * dcaeDeploymentStatusUrl setter.
+ *
+ * @param dcaeDeploymentStatusUrl the dcaeDeploymentStatusUrl to set
+ */
+ public void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) {
+ this.dcaeDeploymentStatusUrl = dcaeDeploymentStatusUrl;
+ }
+
+ /**
+ * dcaeBlueprintId getter.
+ *
+ * @return the dcaeBlueprintId
+ */
+ public String getDcaeBlueprintId() {
+ return dcaeBlueprintId;
+ }
+
+ /**
+ * dcaeBlueprintId setter.
+ *
+ * @param dcaeBlueprintId the dcaeBlueprintId to set
+ */
+ void setDcaeBlueprintId(String dcaeBlueprintId) {
+ this.dcaeBlueprintId = dcaeBlueprintId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ MicroServicePolicy other = (MicroServicePolicy) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ }
+ else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyRepository.java b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyRepository.java
new file mode 100644
index 000000000..38b310ce8
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyRepository.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.policy.microservice;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface MicroServicePolicyRepository extends JpaRepository<MicroServicePolicy, String> {
+
+}
diff --git a/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyService.java b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyService.java
new file mode 100644
index 000000000..060e79a63
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyService.java
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.clamp.policy.microservice;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.policy.PolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MicroServicePolicyService implements PolicyService<MicroServicePolicy> {
+
+ private final MicroServicePolicyRepository microServiceRepository;
+
+ @Autowired
+ public MicroServicePolicyService(MicroServicePolicyRepository microServiceRepository) {
+ this.microServiceRepository = microServiceRepository;
+ }
+
+ @Override
+ public Set<MicroServicePolicy> updatePolicies(Loop loop, List<MicroServicePolicy> newMicroservicePolicies) {
+ return newMicroservicePolicies.stream().map(policy -> getAndUpdateMicroServicePolicy(loop, policy))
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public boolean isExisting(String policyName) {
+ return microServiceRepository.existsById(policyName);
+ }
+
+ /**
+ * Get and update the MicroService policy properties.
+ *
+ * @param loop The loop
+ * @param policy The new MicroService policy
+ * @return The updated MicroService policy
+ */
+ public MicroServicePolicy getAndUpdateMicroServicePolicy(Loop loop, MicroServicePolicy policy) {
+ return microServiceRepository.save(
+ microServiceRepository
+ .findById(policy.getName()).map(p -> updateMicroservicePolicyProperties(p, policy, loop))
+ .orElse(new MicroServicePolicy(policy.getName(), policy.getPolicyModel(),
+ policy.getShared(), policy.getJsonRepresentation(), null, policy.getPdpGroup(),
+ policy.getPdpSubgroup())));
+ }
+
+ private MicroServicePolicy updateMicroservicePolicyProperties(MicroServicePolicy oldPolicy,
+ MicroServicePolicy newPolicy, Loop loop) {
+ oldPolicy.setConfigurationsJson(newPolicy.getConfigurationsJson());
+ if (!oldPolicy.getUsedByLoops().contains(loop)) {
+ oldPolicy.getUsedByLoops().add(loop);
+ }
+ oldPolicy.setPdpGroup(newPolicy.getPdpGroup());
+ oldPolicy.setPdpSubgroup(newPolicy.getPdpSubgroup());
+ return oldPolicy;
+ }
+
+ /**
+ * Update the MicroService policy deployment related parameters.
+ *
+ * @param microServicePolicy The micro service policy
+ * @param deploymentId The deployment ID as returned by DCAE
+ * @param deploymentUrl The Deployment URL as returned by DCAE
+ */
+ public void updateDcaeDeploymentFields(MicroServicePolicy microServicePolicy, String deploymentId,
+ String deploymentUrl) {
+ microServicePolicy.setDcaeDeploymentId(deploymentId);
+ microServicePolicy.setDcaeDeploymentStatusUrl(deploymentUrl);
+ microServiceRepository.saveAndFlush(microServicePolicy);
+ }
+
+
+ /**
+ * Api to refresh the MicroService Policy UI window.
+ *
+ * @param microServicePolicy The micro Service policy object
+ * @param toscaConverter The tosca converter required to convert the tosca model to json schema
+ * @param loop As a microservice object can belong to multiple loops, we need it here
+ */
+ public void refreshMicroServicePolicyJsonRepresentation(MicroServicePolicy microServicePolicy,
+ ToscaConverterWithDictionarySupport toscaConverter,
+ Loop loop) {
+ microServicePolicy.updateJsonRepresentation(toscaConverter, loop.getModelService());
+ this.microServiceRepository.saveAndFlush(microServicePolicy);
+
+ }
+}
diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java
new file mode 100644
index 000000000..4b052427f
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java
@@ -0,0 +1,218 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * 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.clamp.policy.operational;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.loop.service.Service;
+import org.onap.clamp.loop.template.LoopElementModel;
+import org.onap.clamp.loop.template.PolicyModel;
+import org.onap.clamp.policy.Policy;
+
+@Entity
+@Table(name = "operational_policies")
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class OperationalPolicy extends Policy implements Serializable {
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 6117076450841538255L;
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicy.class);
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "loop_id", nullable = false)
+ private Loop loop;
+
+ /**
+ * Constructor for serialization.
+ */
+ public OperationalPolicy() {
+ }
+
+ /**
+ * The constructor.
+ *
+ * @param name The name of the operational policy
+ * @param configurationsJson The operational policy property in the format of
+ * json
+ * @param jsonRepresentation The jsonObject defining the json schema
+ * @param policyModel The policy model associated if any, can be null
+ * @param loopElementModel The loop element from which this instance is supposed to be created
+ * @param pdpGroup The Pdp Group info
+ * @param pdpSubgroup The Pdp Subgroup info
+ */
+ public OperationalPolicy(String name, JsonObject configurationsJson,
+ JsonObject jsonRepresentation, PolicyModel policyModel,
+ LoopElementModel loopElementModel, String pdpGroup, String pdpSubgroup) {
+ this.name = name;
+ this.setPolicyModel(policyModel);
+ this.setConfigurationsJson(configurationsJson);
+ this.setPdpGroup(pdpGroup);
+ this.setPdpSubgroup(pdpSubgroup);
+ this.setLoopElementModel(loopElementModel);
+ this.setJsonRepresentation(jsonRepresentation);
+
+ }
+
+ /**
+ * Create an operational policy from a loop element model.
+ *
+ * @param loop The parent loop
+ * @param service The loop service
+ * @param loopElementModel The loop element model
+ * @param toscaConverter The tosca converter that must be used to create the Json representation
+ */
+ public OperationalPolicy(Loop loop, Service service, LoopElementModel loopElementModel,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ this(Policy.generatePolicyName("OPERATIONAL", service.getName(), service.getVersion(),
+ loopElementModel.getPolicyModels().first().getPolicyAcronym() + '_'
+ + loopElementModel.getPolicyModels().first().getVersion(),
+ RandomStringUtils.randomAlphanumeric(3)), new JsonObject(),
+ new JsonObject(), loopElementModel.getPolicyModels().first(), loopElementModel, null, null);
+ this.setLoop(loop);
+ this.updateJsonRepresentation(toscaConverter, service);
+ }
+
+ /**
+ * Create an operational policy from a policy model.
+ *
+ * @param loop The parent loop
+ * @param service The loop service
+ * @param policyModel The policy model
+ * @param toscaConverter The tosca converter that must be used to create the Json representation
+ */
+ public OperationalPolicy(Loop loop, Service service, PolicyModel policyModel,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ this(Policy.generatePolicyName("OPERATIONAL", service.getName(), service.getVersion(),
+ policyModel.getPolicyAcronym() + '_' + policyModel.getVersion(),
+ RandomStringUtils.randomAlphanumeric(3)),
+ new JsonObject(),
+ new JsonObject(), policyModel, null, null, null);
+ this.setLoop(loop);
+ this.updateJsonRepresentation(toscaConverter, service);
+ }
+
+ public void setLoop(Loop loopName) {
+ this.loop = loopName;
+ }
+
+ public Loop getLoop() {
+ return loop;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void updateJsonRepresentation(ToscaConverterWithDictionarySupport toscaConverter, Service serviceModel) {
+ {
+ this.setJsonRepresentation(new JsonObject());
+ if (this.getPolicyModel() == null) {
+ return;
+ }
+
+ // Generic Case
+ this.setJsonRepresentation(toscaConverter.convertToscaToJsonSchemaObject(
+ this.getPolicyModel().getPolicyModelTosca(),
+ this.getPolicyModel().getPolicyModelType(), serviceModel));
+
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ OperationalPolicy other = (OperationalPolicy) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else {
+ if (!name.equals(other.name)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public String createPolicyPayload() throws UnsupportedEncodingException {
+ return super.createPolicyPayload();
+
+ }
+}
diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepository.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepository.java
new file mode 100644
index 000000000..c0a6e12cd
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepository.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.policy.operational;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface OperationalPolicyRepository extends JpaRepository<OperationalPolicy, String> {
+ void deleteByName(String policyName);
+}
diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java
new file mode 100644
index 000000000..0381f0a2a
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java
@@ -0,0 +1,352 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * 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.clamp.policy.operational;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.clds.util.ResourceFileUtils;
+import org.onap.clamp.loop.service.Service;
+
+public class OperationalPolicyRepresentationBuilder {
+
+ private static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(OperationalPolicyRepresentationBuilder.class);
+
+ public static final String PROPERTIES = "properties";
+ public static final String ITEMS = "items";
+ public static final String ANY_OF = "anyOf";
+ public static final String TITLE = "title";
+ public static final String RECIPE = "recipe";
+ public static final String DEFAULT = "default";
+ public static final String STRING = "string";
+ public static final String TYPE = "type";
+ public static final String TYPE_LIST = "list";
+ public static final String TYPE_OBJECT = "object";
+ public static final String TYPE_ARRAY = "array";
+
+ private OperationalPolicyRepresentationBuilder() {
+ throw new IllegalStateException("This is Utility class, not supposed to be initiated.");
+ }
+
+ /**
+ * This method generates the operational policy json representation that will be
+ * used by ui for rendering. It uses the model (VF and VFModule) defined in the
+ * loop object to do so, so it's dynamic. It also uses the operational policy
+ * schema template defined in the resource folder.
+ *
+ * @param modelJson The loop model json
+ * @return The json representation
+ */
+ public static JsonObject generateOperationalPolicySchema(Service modelJson) {
+
+ JsonObject jsonSchema = null;
+ try {
+ jsonSchema = JsonUtils.GSON.fromJson(
+ ResourceFileUtils
+ .getResourceAsString("clds/json-schema/operational_policies/operational_policy.json"),
+ JsonObject.class);
+ jsonSchema.get(PROPERTIES).getAsJsonObject()
+ .get("operational_policy").getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("policies")
+ .getAsJsonObject().get(ITEMS).getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("target")
+ .getAsJsonObject().get(ANY_OF).getAsJsonArray().addAll(createAnyOfArray(modelJson, true));
+
+ // update CDS recipe and payload information to schema
+ JsonArray actors = jsonSchema.get(PROPERTIES).getAsJsonObject()
+ .get("operational_policy").getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("policies")
+ .getAsJsonObject().get(ITEMS).getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("actor")
+ .getAsJsonObject().get(ANY_OF).getAsJsonArray();
+
+ for (JsonElement actor : actors) {
+ if ("CDS".equalsIgnoreCase(actor.getAsJsonObject().get(TITLE).getAsString())) {
+ actor.getAsJsonObject().get(PROPERTIES).getAsJsonObject().get(RECIPE).getAsJsonObject()
+ .get(ANY_OF).getAsJsonArray()
+ .addAll(createAnyOfArrayForCdsRecipe(modelJson));
+ }
+ }
+ return jsonSchema;
+ } catch (IOException e) {
+ logger.error("Unable to generate the json schema because of an exception", e);
+ return new JsonObject();
+ }
+ }
+
+ private static JsonObject createSchemaProperty(String title, String type, String defaultValue, String readOnlyFlag,
+ String[] enumArray) {
+ JsonObject property = new JsonObject();
+ property.addProperty(TITLE, title);
+ property.addProperty(TYPE, type);
+ property.addProperty(DEFAULT, defaultValue);
+ property.addProperty("readOnly", readOnlyFlag);
+
+ if (enumArray != null) {
+ JsonArray jsonArray = new JsonArray();
+ property.add("enum", jsonArray);
+ for (String val : enumArray) {
+ jsonArray.add(val);
+ }
+ }
+ return property;
+ }
+
+ private static JsonArray createVnfSchema(Service modelService, boolean generateType) {
+ JsonArray vnfSchemaArray = new JsonArray();
+ JsonObject modelVnfs = modelService.getResourceByType("VF");
+
+ for (Entry<String, JsonElement> entry : modelVnfs.entrySet()) {
+ JsonObject vnfOneOfSchema = new JsonObject();
+ vnfOneOfSchema.addProperty(TITLE, "VNF" + "-" + entry.getKey());
+ JsonObject properties = new JsonObject();
+ if (generateType) {
+ properties.add(TYPE, createSchemaProperty("Type", STRING, "VNF", "True", null));
+ }
+ properties.add("resourceID", createSchemaProperty("Resource ID", STRING,
+ modelVnfs.get(entry.getKey()).getAsJsonObject().get("invariantUUID").getAsString(), "True", null));
+
+ vnfOneOfSchema.add(PROPERTIES, properties);
+ vnfSchemaArray.add(vnfOneOfSchema);
+ }
+ return vnfSchemaArray;
+ }
+
+ private static JsonArray createBlankEntry() {
+ JsonArray result = new JsonArray();
+ JsonObject blankObject = new JsonObject();
+ blankObject.addProperty("title", "User defined");
+ blankObject.add("properties", new JsonObject());
+ result.add(blankObject);
+ return result;
+ }
+
+ private static JsonArray createVfModuleSchema(Service modelService, boolean generateType) {
+ JsonArray vfModuleOneOfSchemaArray = new JsonArray();
+ JsonObject modelVfModules = modelService.getResourceByType("VFModule");
+
+ for (Entry<String, JsonElement> entry : modelVfModules.entrySet()) {
+ JsonObject vfModuleOneOfSchema = new JsonObject();
+ vfModuleOneOfSchema.addProperty(TITLE, "VFMODULE" + "-" + entry.getKey());
+ JsonObject properties = new JsonObject();
+ if (generateType) {
+ properties.add(TYPE, createSchemaProperty("Type", STRING, "VFMODULE", "True", null));
+ }
+ properties.add("resourceID",
+ createSchemaProperty("Resource ID", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelName").getAsString(),
+ "True", null));
+ properties.add("modelInvariantId",
+ createSchemaProperty("Model Invariant Id (ModelInvariantUUID)", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelInvariantUUID")
+ .getAsString(),
+ "True", null));
+ properties.add("modelVersionId",
+ createSchemaProperty("Model Version Id (ModelUUID)", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelUUID").getAsString(),
+ "True", null));
+ properties.add("modelName",
+ createSchemaProperty("Model Name", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelName").getAsString(),
+ "True", null));
+ properties.add("modelVersion", createSchemaProperty("Model Version", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelVersion").getAsString(),
+ "True", null));
+ properties
+ .add("modelCustomizationId",
+ createSchemaProperty("Customization ID", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject()
+ .get("vfModuleModelCustomizationUUID").getAsString(), "True",
+ null));
+
+ vfModuleOneOfSchema.add(PROPERTIES, properties);
+ vfModuleOneOfSchemaArray.add(vfModuleOneOfSchema);
+ }
+ return vfModuleOneOfSchemaArray;
+ }
+
+ /**
+ * Create an anyOf array of possible structure we may have for Target.
+ *
+ * @param modelJson The service object
+ * @return A JsonArray with everything inside
+ */
+ public static JsonArray createAnyOfArray(Service modelJson, boolean generateType) {
+ JsonArray targetOneOfStructure = new JsonArray();
+ // First entry must be user defined
+ targetOneOfStructure.addAll(createBlankEntry());
+ targetOneOfStructure.addAll(createVnfSchema(modelJson, generateType));
+ targetOneOfStructure.addAll(createVfModuleSchema(modelJson, generateType));
+ return targetOneOfStructure;
+ }
+
+ private static JsonArray createAnyOfArrayForCdsRecipe(Service modelJson) {
+ JsonArray anyOfStructure = new JsonArray();
+ anyOfStructure.addAll(createAnyOfCdsRecipe(modelJson.getResourceDetails().getAsJsonObject("VF")));
+ anyOfStructure.addAll(createAnyOfCdsRecipe(modelJson.getResourceDetails().getAsJsonObject("PNF")));
+ return anyOfStructure;
+ }
+
+ private static JsonArray createAnyOfCdsRecipe(JsonObject jsonObject) {
+ JsonArray schemaArray = new JsonArray();
+ for (Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+ JsonObject controllerProperties = entry.getValue().getAsJsonObject()
+ .getAsJsonObject("controllerProperties");
+
+ if (controllerProperties != null && controllerProperties.getAsJsonObject("workflows") != null) {
+ JsonObject workflows = controllerProperties.getAsJsonObject("workflows");
+ for (Entry<String, JsonElement> workflowsEntry : workflows.entrySet()) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty(TITLE, workflowsEntry.getKey());
+ obj.addProperty(TYPE, "object");
+ obj.add(PROPERTIES, createPayloadProperty(workflowsEntry.getValue().getAsJsonObject(),
+ controllerProperties, workflowsEntry.getKey()));
+ schemaArray.add(obj);
+ }
+
+ }
+ }
+ return schemaArray;
+ }
+
+ private static JsonObject createPayloadProperty(JsonObject workFlow,
+ JsonObject controllerProperties, String workFlowName) {
+ JsonObject payload = new JsonObject();
+ payload.addProperty(TITLE, "Payload");
+ payload.addProperty(TYPE, "object");
+ payload.add(PROPERTIES, createInputPropertiesForPayload(workFlow, controllerProperties,
+ workFlowName));
+ JsonObject properties = new JsonObject();
+ properties.add(RECIPE, createRecipeForCdsWorkflow(workFlowName));
+ properties.add("payload", payload);
+ return properties;
+ }
+
+ private static JsonObject createRecipeForCdsWorkflow(String workflow) {
+ JsonObject recipe = new JsonObject();
+ recipe.addProperty(TITLE, RECIPE);
+ recipe.addProperty(TYPE, STRING);
+ recipe.addProperty(DEFAULT, workflow);
+ JsonObject options = new JsonObject();
+ options.addProperty("hidden", true);
+ recipe.add("options", options);
+ return recipe;
+ }
+
+ /**
+ * Returns the properties of payload based on the cds work flows.
+ *
+ * @param workFlow cds work flows to update payload
+ * @param controllerProperties cds properties to get blueprint name and
+ * version
+ * @param workFlowName work flow name
+ * @return returns the properties of payload
+ */
+ public static JsonObject createInputPropertiesForPayload(JsonObject workFlow,
+ JsonObject controllerProperties,
+ String workFlowName) {
+ String artifactName = controllerProperties.get("sdnc_model_name").getAsString();
+ String artifactVersion = controllerProperties.get("sdnc_model_version").getAsString();
+ JsonObject inputs = workFlow.getAsJsonObject("inputs");
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.add("artifact_name", createSchemaProperty(
+ "artifact name", STRING, artifactName, "True", null));
+ jsonObject.add("artifact_version", createSchemaProperty(
+ "artifact version", STRING, artifactVersion, "True", null));
+ jsonObject.add("mode", createCdsInputProperty(
+ "mode", STRING, "async" ,null));
+ jsonObject.add("data", createDataProperty(inputs, workFlowName));
+ return jsonObject;
+ }
+
+ private static JsonObject createDataProperty(JsonObject inputs, String workflowName) {
+ JsonObject data = new JsonObject();
+ data.addProperty(TITLE, "data");
+ JsonObject dataObj = new JsonObject();
+ addDataFields(inputs, dataObj, workflowName);
+ data.add(PROPERTIES, dataObj);
+ return data;
+ }
+
+ private static void addDataFields(JsonObject inputs,
+ JsonObject dataObj,
+ String workFlowName) {
+ Set<Map.Entry<String, JsonElement>> entrySet = inputs.entrySet();
+ for (Map.Entry<String, JsonElement> entry : entrySet) {
+ String key = entry.getKey();
+ JsonObject inputProperty = inputs.getAsJsonObject(key);
+ if (key.equalsIgnoreCase(workFlowName + "-properties")) {
+ addDataFields(entry.getValue().getAsJsonObject().get("properties").getAsJsonObject(),
+ dataObj, workFlowName);
+ } else {
+ dataObj.add(entry.getKey(),
+ createCdsInputProperty(key, inputProperty.get(TYPE).getAsString(),null,
+ entry.getValue().getAsJsonObject()));
+ }
+ }
+ }
+
+ private static JsonObject createCdsInputProperty(String title,
+ String type,
+ String defaultValue,
+ JsonObject cdsProperty) {
+ JsonObject property = new JsonObject();
+ property.addProperty(TITLE, title);
+
+ if (TYPE_LIST.equalsIgnoreCase(type)) {
+ property.addProperty(TYPE, TYPE_ARRAY);
+ if (cdsProperty != null && cdsProperty.get(PROPERTIES) != null) {
+ JsonObject listProperties = new JsonObject();
+ listProperties.add(PROPERTIES, getProperties(cdsProperty.get(PROPERTIES).getAsJsonObject()));
+ property.add(ITEMS, listProperties);
+ }
+ } else if (TYPE_OBJECT.equalsIgnoreCase(type)) {
+ property.addProperty(TYPE, TYPE_OBJECT);
+ property.add(PROPERTIES, getProperties(cdsProperty.get(PROPERTIES).getAsJsonObject()));
+ } else {
+ property.addProperty(TYPE, type);
+ }
+
+ if (defaultValue != null) {
+ property.addProperty(DEFAULT, defaultValue);
+ }
+ return property;
+ }
+
+ private static JsonObject getProperties(JsonObject inputProperties) {
+ if (inputProperties == null) {
+ return null;
+ }
+ JsonObject dataObject = new JsonObject();
+ addDataFields(inputProperties, dataObject, null);
+ return dataObject;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java
new file mode 100644
index 000000000..d5442e145
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.clamp.policy.operational;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.loop.template.PolicyModelsRepository;
+import org.onap.clamp.policy.PolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OperationalPolicyService implements PolicyService<OperationalPolicy> {
+
+ private final OperationalPolicyRepository operationalPolicyRepository;
+
+ private final PolicyModelsRepository policyModelsRepository;
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicyService.class);
+
+ @Autowired
+ public OperationalPolicyService(OperationalPolicyRepository repository,
+ PolicyModelsRepository policyModelsRepository) {
+ this.operationalPolicyRepository = repository;
+ this.policyModelsRepository = policyModelsRepository;
+ }
+
+ @Override
+ public Set<OperationalPolicy> updatePolicies(Loop loop, List<OperationalPolicy> operationalPolicies) {
+ return operationalPolicies
+ .parallelStream()
+ .map(policy ->
+ operationalPolicyRepository
+ .findById(policy.getName())
+ .map(p -> setConfiguration(p, policy))
+ .orElse(initializeMissingFields(loop, policy)))
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public boolean isExisting(String policyName) {
+ return operationalPolicyRepository.existsById(policyName);
+ }
+
+ private OperationalPolicy initializeMissingFields(Loop loop, OperationalPolicy policy) {
+ policy.setLoop(loop);
+ return policy;
+ }
+
+ private OperationalPolicy setConfiguration(OperationalPolicy policy, OperationalPolicy newPolicy) {
+ policy.setConfigurationsJson(newPolicy.getConfigurationsJson());
+ policy.setPdpGroup(newPolicy.getPdpGroup());
+ policy.setPdpSubgroup(newPolicy.getPdpSubgroup());
+ return policy;
+ }
+
+ /**
+ * Api to refresh the Operational Policy UI window.
+ *
+ * @param operationalPolicy The operational policy object
+ * @param toscaConverter the tosca converter required to convert the tosca model to json schema
+ */
+ public void refreshOperationalPolicyJsonRepresentation(OperationalPolicy operationalPolicy,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ operationalPolicy.updateJsonRepresentation(toscaConverter, operationalPolicy.getLoop().getModelService());
+ this.operationalPolicyRepository.saveAndFlush(operationalPolicy);
+ }
+}
diff --git a/src/main/java/org/onap/clamp/policy/pdpgroup/PdpGroup.java b/src/main/java/org/onap/clamp/policy/pdpgroup/PdpGroup.java
new file mode 100644
index 000000000..a3cf4e053
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/pdpgroup/PdpGroup.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.policy.pdpgroup;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+
+import java.util.List;
+
+/**
+ * This class maps the get Pdp Group response to a nice pojo.
+ */
+public class PdpGroup {
+
+ @Expose
+ private String name;
+
+ @Expose
+ private String pdpGroupState;
+
+ @Expose
+ private List<PdpSubgroup> pdpSubgroups;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPdpGroupState() {
+ return pdpGroupState;
+ }
+
+ public void setPdpGroupState(String pdpGroupState) {
+ this.pdpGroupState = pdpGroupState;
+ }
+
+ public List<PdpSubgroup> getPdpSubgroups() {
+ return pdpSubgroups;
+ }
+
+ public void setPdpSubgroups(List<PdpSubgroup> pdpSubgroups) {
+ this.pdpSubgroups = pdpSubgroups;
+ }
+
+ /**
+ * Get supported subGroups based on the defined policy type and version.
+ * @param policyType The policy type
+ * @param version The version
+ * @return The supported subGroup list in Json format
+ */
+ public JsonObject getSupportedSubgroups(String policyType, String version) {
+ if (!pdpGroupState.equalsIgnoreCase("ACTIVE")) {
+ return null;
+ }
+ JsonArray supportedSubgroups = new JsonArray();
+ for (PdpSubgroup subGroup : pdpSubgroups) {
+ if (subGroup.getSupportedPolicyTypes().contains(new PolicyModelKey(policyType, version))) {
+ supportedSubgroups.add(subGroup.getPdpType());
+ }
+ }
+ if (supportedSubgroups.size() > 0) {
+ JsonObject supportedPdpGroup = new JsonObject();
+ supportedPdpGroup.add(this.name, supportedSubgroups);
+ return supportedPdpGroup;
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/policy/pdpgroup/PdpSubgroup.java b/src/main/java/org/onap/clamp/policy/pdpgroup/PdpSubgroup.java
new file mode 100644
index 000000000..28de79abf
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/pdpgroup/PdpSubgroup.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.policy.pdpgroup;
+
+import com.google.gson.annotations.Expose;
+import java.util.List;
+
+/**
+ * This class maps the Policy get PDP Group response to a nice pojo.
+ */
+public class PdpSubgroup {
+
+ @Expose
+ private String pdpType;
+
+ @Expose
+ private List<PolicyModelKey> supportedPolicyTypes;
+
+ public String getPdpType() {
+ return pdpType;
+ }
+
+ public void setPdpType(String pdpType) {
+ this.pdpType = pdpType;
+ }
+
+ public List<PolicyModelKey> getSupportedPolicyTypes() {
+ return supportedPolicyTypes;
+ }
+
+ public void setSupportedPolicyTypes(List<PolicyModelKey> supportedPolicyTypes) {
+ this.supportedPolicyTypes = supportedPolicyTypes;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/policy/pdpgroup/PolicyModelKey.java b/src/main/java/org/onap/clamp/policy/pdpgroup/PolicyModelKey.java
new file mode 100644
index 000000000..707b3bd2f
--- /dev/null
+++ b/src/main/java/org/onap/clamp/policy/pdpgroup/PolicyModelKey.java
@@ -0,0 +1,126 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.policy.pdpgroup;
+
+import com.google.gson.annotations.Expose;
+
+import java.io.Serializable;
+
+public class PolicyModelKey implements Serializable {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 3307410842013230886L;
+
+ @Expose
+ private String name;
+
+ @Expose
+ private String version;
+
+ /**
+ * Constructor.
+ */
+ public PolicyModelKey(String name, String version) {
+ this.name = name;
+ this.version = version;
+ }
+
+ /**
+ * name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * version getter.
+ *
+ * @return the version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * version setter.
+ *
+ * @param version the version to set
+ */
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((version == null) ? 0 : version.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PolicyModelKey other = (PolicyModelKey) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ if (!name.matches(other.name)) {
+ return false;
+ }
+ }
+ if (version == null) {
+ if (other.version != null) {
+ return false;
+ }
+ } else if (!version.equals(other.version)) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/tosca/Dictionary.java b/src/main/java/org/onap/clamp/tosca/Dictionary.java
new file mode 100644
index 000000000..cf514c4bd
--- /dev/null
+++ b/src/main/java/org/onap/clamp/tosca/Dictionary.java
@@ -0,0 +1,219 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.tosca;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import org.onap.clamp.loop.common.AuditEntity;
+
+/**
+ * Represents Dictionary.
+ */
+
+@Entity
+@Table(name = "dictionary")
+public class Dictionary extends AuditEntity implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701388645L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "dictionary_second_level")
+ private int secondLevelDictionary = 0;
+
+ @Expose
+ @Column(name = "dictionary_type")
+ private String subDictionaryType;
+
+ @Expose
+ @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
+ @JoinTable(
+ name = "dictionary_to_dictionaryelements",
+ joinColumns = @JoinColumn(name = "dictionary_name", referencedColumnName = "name"),
+ inverseJoinColumns = {@JoinColumn(
+ name = "dictionary_element_short_name",
+ referencedColumnName = "short_name")})
+ private Set<DictionaryElement> dictionaryElements = new HashSet<>();
+
+ /**
+ * name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * secondLevelDictionary getter.
+ *
+ * @return the secondLevelDictionary
+ */
+ public int getSecondLevelDictionary() {
+ return secondLevelDictionary;
+ }
+
+ /**
+ * secondLevelDictionary setter.
+ *
+ * @param secondLevelDictionary the secondLevelDictionary to set
+ */
+ public void setSecondLevelDictionary(int secondLevelDictionary) {
+ this.secondLevelDictionary = secondLevelDictionary;
+ }
+
+ /**
+ * subDictionaryType getter.
+ *
+ * @return the subDictionaryType
+ */
+ public String getSubDictionaryType() {
+ return subDictionaryType;
+ }
+
+ /**
+ * subDictionaryType setter.
+ *
+ * @param subDictionaryType the subDictionaryType to set
+ */
+ public void setSubDictionaryType(String subDictionaryType) {
+ this.subDictionaryType = subDictionaryType;
+ }
+
+ /**
+ * dictionaryElements getter.
+ *
+ * @return the dictionaryElements List of dictionary element
+ */
+ public Set<DictionaryElement> getDictionaryElements() {
+ return dictionaryElements;
+ }
+
+ /**
+ * Method to add a new dictionaryElement to the list.
+ *
+ * @param dictionaryElement The dictionary element
+ */
+ public void addDictionaryElements(DictionaryElement dictionaryElement) {
+ dictionaryElements.add(dictionaryElement);
+ dictionaryElement.getUsedByDictionaries().add(this);
+ }
+
+ /**
+ * Method to set dictionaryElements.
+ *
+ * @param dictionaryElements The dictionary elements set
+ */
+ public void setDictionaryElements(Set<DictionaryElement> dictionaryElements) {
+ this.dictionaryElements = dictionaryElements;
+ }
+
+ /**
+ * Method to delete a dictionaryElement from the list.
+ *
+ * @param dictionaryElement The dictionary element
+ */
+ public void removeDictionaryElement(DictionaryElement dictionaryElement) {
+ dictionaryElements.remove(dictionaryElement);
+ dictionaryElement.getUsedByDictionaries().remove(this);
+ }
+
+ /**
+ * Default Constructor.
+ */
+ public Dictionary() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The Dictionary name
+ * @param secondLevelDictionary defines if dictionary is a secondary level
+ * @param subDictionaryType defines the type of secondary level dictionary
+ */
+ public Dictionary(String name, int secondLevelDictionary, String subDictionaryType) {
+ this.name = name;
+ this.secondLevelDictionary = secondLevelDictionary;
+ this.subDictionaryType = subDictionaryType;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Dictionary other = (Dictionary) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/src/main/java/org/onap/clamp/tosca/DictionaryElement.java b/src/main/java/org/onap/clamp/tosca/DictionaryElement.java
new file mode 100644
index 000000000..43a3106f5
--- /dev/null
+++ b/src/main/java/org/onap/clamp/tosca/DictionaryElement.java
@@ -0,0 +1,254 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.tosca;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import org.onap.clamp.loop.common.AuditEntity;
+
+/**
+ * Represents a Dictionary Item.
+ */
+@Entity
+@Table(name = "dictionary_elements")
+public class DictionaryElement extends AuditEntity implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701388644L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "short_name")
+ private String shortName;
+
+ @Expose
+ @Column(nullable = false, name = "name")
+ private String name;
+
+ @Expose
+ @Column(nullable = false, name = "description")
+ private String description;
+
+ @Expose
+ @Column(nullable = false, name = "type")
+ private String type;
+
+ @Expose
+ @Column(nullable = true, name = "subdictionary_name")
+ private String subDictionary;
+
+ @ManyToMany(mappedBy = "dictionaryElements", fetch = FetchType.EAGER)
+ private Set<Dictionary> usedByDictionaries = new HashSet<>();
+
+ /**
+ * name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * shortName getter.
+ *
+ * @return the shortName
+ */
+ public String getShortName() {
+ return shortName;
+ }
+
+ /**
+ * shortName setter.
+ *
+ * @param shortName the shortName to set
+ */
+ public void setShortName(String shortName) {
+ this.shortName = shortName;
+ }
+
+ /**
+ * description getter.
+ *
+ * @return the description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * description setter.
+ *
+ * @param description the description to set
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * type getter.
+ *
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * type setter.
+ *
+ * @param type the type to set
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * subDictionary getter.
+ *
+ * @return the subDictionary
+ */
+ public String getSubDictionary() {
+ return subDictionary;
+ }
+
+ /**
+ * subDictionary setter.
+ *
+ * @param subDictionary the subDictionary to set
+ */
+ public void setSubDictionary(String subDictionary) {
+ this.subDictionary = subDictionary;
+ }
+
+ /**
+ * usedByDictionaries getter.
+ *
+ * @return the usedByDictionaries
+ */
+ public Set<Dictionary> getUsedByDictionaries() {
+ return usedByDictionaries;
+ }
+
+ /**
+ * usedByDictionaries setter.
+ *
+ * @param usedByDictionaries the usedByDictionaries to set
+ */
+ public void setUsedByDictionaries(Set<Dictionary> usedByDictionaries) {
+ this.usedByDictionaries = usedByDictionaries;
+ }
+
+ /**
+ * Default Constructor.
+ */
+ public DictionaryElement() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The Dictionary element name
+ * @param shortName The short name
+ * @param description The description
+ * @param type The type of element
+ * @param subDictionary The sub type
+ */
+ public DictionaryElement(String name, String shortName, String description, String type,
+ String subDictionary) {
+ this.name = name;
+ this.shortName = shortName;
+ this.description = description;
+ this.type = type;
+ this.subDictionary = subDictionary;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The Dictionary element name
+ * @param shortName The short name
+ * @param description The description
+ * @param type The type of element
+ * @param subDictionary The sub type
+ */
+ public DictionaryElement(String name, String shortName, String description, String type,
+ String subDictionary, Set<Dictionary> usedByDictionaries) {
+ this.name = name;
+ this.shortName = shortName;
+ this.description = description;
+ this.type = type;
+ this.subDictionary = subDictionary;
+ this.usedByDictionaries = usedByDictionaries;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((shortName == null) ? 0 : shortName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ DictionaryElement other = (DictionaryElement) obj;
+ if (shortName == null) {
+ if (other.shortName != null) {
+ return false;
+ }
+ } else if (!shortName.equals(other.shortName)) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/tosca/DictionaryElementsRepository.java b/src/main/java/org/onap/clamp/tosca/DictionaryElementsRepository.java
new file mode 100644
index 000000000..43f6f1d40
--- /dev/null
+++ b/src/main/java/org/onap/clamp/tosca/DictionaryElementsRepository.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.tosca;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface DictionaryElementsRepository extends JpaRepository<DictionaryElement, String> {
+
+}
diff --git a/src/main/java/org/onap/clamp/tosca/DictionaryRepository.java b/src/main/java/org/onap/clamp/tosca/DictionaryRepository.java
new file mode 100644
index 000000000..ae8430d93
--- /dev/null
+++ b/src/main/java/org/onap/clamp/tosca/DictionaryRepository.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.tosca;
+
+import java.util.List;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface DictionaryRepository extends JpaRepository<Dictionary, String> {
+
+ @Query("SELECT dict.name FROM Dictionary as dict")
+ List<String> getAllDictionaryNames();
+
+ @Query("SELECT dict.name FROM Dictionary as dict where dict.secondLevelDictionary = 1")
+ List<String> getAllSecondaryLevelDictionaryNames();
+
+}
diff --git a/src/main/java/org/onap/clamp/tosca/DictionaryService.java b/src/main/java/org/onap/clamp/tosca/DictionaryService.java
new file mode 100644
index 000000000..6172641a7
--- /dev/null
+++ b/src/main/java/org/onap/clamp/tosca/DictionaryService.java
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.tosca;
+
+import com.google.common.collect.Sets;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.persistence.EntityNotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class DictionaryService {
+
+ private final DictionaryRepository dictionaryRepository;
+ private final DictionaryElementsRepository dictionaryElementsRepository;
+
+ /**
+ * Constructor.
+ */
+ @Autowired
+ public DictionaryService(DictionaryRepository dictionaryRepository,
+ DictionaryElementsRepository dictionaryElementsRepository) {
+ this.dictionaryRepository = dictionaryRepository;
+ this.dictionaryElementsRepository = dictionaryElementsRepository;
+
+ }
+
+ public Dictionary saveOrUpdateDictionary(Dictionary dictionary) {
+ return dictionaryRepository.saveAndFlush(dictionary);
+ }
+
+ /**
+ * Creates or Updates Dictionary Element.
+ *
+ * @param dictionaryName The Dictionary name
+ * @param dictionary The Dictionary object with dictionary elements
+ * @return updated Dictionary object with all dictionary elements
+ */
+ public Dictionary saveOrUpdateDictionaryElement(String dictionaryName, Dictionary dictionary) {
+ Dictionary dict = getDictionary(dictionaryName);
+
+ Set<DictionaryElement> newDictionaryElements = dictionary.getDictionaryElements();
+
+ if (newDictionaryElements != null && !newDictionaryElements.isEmpty()) {
+ Set<DictionaryElement> updatedDictionaryElements = newDictionaryElements.stream()
+ .map(dictionaryElement -> getAndUpdateDictionaryElement(dict, dictionaryElement))
+ .collect(Collectors.toSet());
+
+ dict.getDictionaryElements().forEach(dictElement -> {
+ if (!updatedDictionaryElements.contains(dictElement)) {
+ updatedDictionaryElements.add(dictElement);
+ }
+ });
+ dict.setDictionaryElements(updatedDictionaryElements);
+ }
+ return dictionaryRepository.saveAndFlush(dict);
+
+ }
+
+ private DictionaryElement getAndUpdateDictionaryElement(Dictionary dictionary,
+ DictionaryElement element) {
+ return dictionaryElementsRepository
+ .save(dictionaryElementsRepository.findById(element.getShortName())
+ .map(p -> updateDictionaryElement(p, element, dictionary))
+ .orElse(new DictionaryElement(element.getName(), element.getShortName(),
+ element.getDescription(), element.getType(), element.getSubDictionary(),
+ Sets.newHashSet(dictionary))));
+ }
+
+ public void deleteDictionary(Dictionary dictionary) {
+ dictionaryRepository.delete(dictionary);
+ }
+
+ public void deleteDictionary(String dictionaryName) {
+ dictionaryRepository.deleteById(dictionaryName);
+ }
+
+ public List<Dictionary> getAllDictionaries() {
+ return dictionaryRepository.findAll();
+ }
+
+ public List<String> getAllSecondaryLevelDictionaryNames() {
+ return dictionaryRepository.getAllSecondaryLevelDictionaryNames();
+ }
+
+ public Dictionary getDictionary(String dictionaryName) {
+ return dictionaryRepository.findById(dictionaryName).orElseThrow(
+ () -> new EntityNotFoundException("Couldn't find Dictionary named: " + dictionaryName));
+ }
+
+ /**
+ * Deletes a dictionary element from Dictionary by shortName.
+ *
+ * @param dictionaryName The dictionary name
+ * @param dictionaryElementShortName the dictionary Element Short name
+ */
+ public void deleteDictionaryElement(String dictionaryName, String dictionaryElementShortName) {
+ if (dictionaryRepository.existsById(dictionaryName)) {
+ DictionaryElement element =
+ dictionaryElementsRepository.findById(dictionaryElementShortName).orElse(null);
+ if (element != null) {
+ Dictionary dict = getDictionary(dictionaryName);
+ dict.removeDictionaryElement(element);
+ dictionaryRepository.saveAndFlush(dict);
+ }
+ }
+ }
+
+ private DictionaryElement updateDictionaryElement(DictionaryElement oldDictionaryElement,
+ DictionaryElement newDictionaryElement, Dictionary dictionary) {
+ oldDictionaryElement.setName(newDictionaryElement.getName());
+ oldDictionaryElement.setDescription(newDictionaryElement.getDescription());
+ oldDictionaryElement.setType(newDictionaryElement.getType());
+ oldDictionaryElement.setSubDictionary(newDictionaryElement.getSubDictionary());
+ oldDictionaryElement.getUsedByDictionaries().add(dictionary);
+ return oldDictionaryElement;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/util/PassDecoder.java b/src/main/java/org/onap/clamp/util/PassDecoder.java
new file mode 100644
index 000000000..b2e4ca2c5
--- /dev/null
+++ b/src/main/java/org/onap/clamp/util/PassDecoder.java
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 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.clamp.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.onap.aaf.cadi.Symm;
+import org.onap.clamp.clds.util.ResourceFileUtils;
+
+/**
+ * PassDecoder for decrypting the truststore and keystore password.
+ */
+public class PassDecoder {
+ /**
+ * Used to log PassDecoder class.
+ */
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(PassDecoder.class);
+
+ /**
+ * Decode the password.
+ *
+ * @param encryptedPass The encrypted password
+ * @param keyFileName The key file name in String
+ */
+ public static String decode(String encryptedPass, String keyFileName) {
+ if (null == keyFileName) {
+ logger.debug("Key file is not defined, thus password will not be decrypted");
+ return encryptedPass;
+ }
+ if (null == encryptedPass) {
+ logger.error("Encrypted password is not defined");
+ return null;
+ }
+ try {
+ return Symm.obtain(ResourceFileUtils.getResourceAsStream(keyFileName)).depass(encryptedPass);
+ } catch (IOException e) {
+ logger.error("Exception occurred during the key decryption", e);
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/clamp/util/SemanticVersioning.java b/src/main/java/org/onap/clamp/util/SemanticVersioning.java
new file mode 100644
index 000000000..8852e2a4f
--- /dev/null
+++ b/src/main/java/org/onap/clamp/util/SemanticVersioning.java
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clamp.util;
+
+/**
+ * This class is the base class for object that requires semantic versioning.
+ * ... This class supports also a.b.c.d... etc ... as a version.
+ */
+public class SemanticVersioning {
+ public static final int BEFORE = -1;
+ public static final int EQUAL = 0;
+ public static final int AFTER = 1;
+ public static final String DEFAULT_VERSION = "1.0.0";
+
+ /**
+ * The compare method that compare arg0 to arg1.
+ *
+ * @param arg0 A version in string for semantic versioning (a.b.c.d...)
+ * @param arg1 A version in string for semantic versioning (a.b.c.d...)
+ * @return objects (arg0, arg1) given as parameters. It returns the value: 0: if
+ * (arg0==arg1) -1: if (arg0 < arg1) 1: if (arg0 > arg1)
+ */
+ public static int compare(String arg0, String arg1) {
+
+ if (arg0 == null && arg1 == null) {
+ return EQUAL;
+ }
+ if (arg0 == null) {
+ return BEFORE;
+ }
+ if (arg1 == null) {
+ return AFTER;
+ }
+ String[] arg0Array = arg0.split("\\.");
+ String[] arg1Array = arg1.split("\\.");
+
+ int smalestStringLength = Math.min(arg0Array.length, arg1Array.length);
+
+ for (int currentVersionIndex =
+ 0; currentVersionIndex < smalestStringLength; ++currentVersionIndex) {
+ if (Integer.parseInt(arg0Array[currentVersionIndex]) < Integer
+ .parseInt(arg1Array[currentVersionIndex])) {
+ return BEFORE;
+ } else if (Integer.parseInt(arg0Array[currentVersionIndex]) > Integer
+ .parseInt(arg1Array[currentVersionIndex])) {
+ return AFTER;
+ }
+ // equals, so do not return anything, continue
+ }
+ if (arg0Array.length == arg1Array.length) {
+ return EQUAL;
+ } else {
+ return Integer.compare(arg0Array.length, arg1Array.length);
+ }
+ }
+
+ /**
+ * Method to increment a version from its current version.
+ *
+ * @param currentVersion The current Version
+ * @return the increment version string
+ */
+ public static String incrementMajorVersion(String currentVersion) {
+ if (currentVersion == null || currentVersion.isEmpty()) {
+ return DEFAULT_VERSION;
+ }
+ String[] versionArray = currentVersion.split("\\.");
+ return String.valueOf(Integer.parseInt(versionArray[0]) + 1) + ".0.0";
+ }
+}