summaryrefslogtreecommitdiffstats
path: root/dcaedt_be/src/main/java/org/onap
diff options
context:
space:
mode:
Diffstat (limited to 'dcaedt_be/src/main/java/org/onap')
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionConfig.java87
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionEngine.java140
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BaseController.java80
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BlueprintController.java239
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/CompositionController.java338
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ConfigurationController.java63
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/LifecycleController.java84
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/RuleEditorController.java453
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ServicesController.java230
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/VfcmtController.java183
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/HealthController.java77
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/HealthPoller.java97
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/ToscaLabHealthState.java29
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/swagger/SwaggerConfig.java23
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BaseBusinessLogic.java49
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/ReferenceBusinessLogic.java74
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/VfcmtBusinessLogic.java283
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ActionStatus.java48
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/BasicConfiguration.java5
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/DcaeException.java15
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrConfMgr.java306
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorConfiguration.java46
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorConfigurationLoader.java121
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorInfo.java99
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ResponseFormatManager.java103
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/filter/LoggingFilter.java247
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/ConditionTypeEnum.java22
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/OperatorTypeEnum.java32
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/RuleEditorElementType.java58
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogic.java149
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionGroupTranslator.java47
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionTranslator.java40
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/CopyActionTranslator.java47
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/DateFormatterTranslator.java49
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/FieldConditionTranslator.java43
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/IRuleElementTranslator.java50
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MapActionTranslator.java50
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MappingRulesTranslator.java69
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RegexActionTranslator.java44
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RuleTranslator.java51
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/EmptyStringTranslationSerializer.java14
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/RulesPayloadUtils.java38
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/ValidationUtils.java20
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ActionValidator.java40
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConcatActionValidator.java29
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionGroupValidator.java40
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionValidator.java40
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/DateFormatterValidator.java41
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/IRuleElementValidator.java9
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MapActionValidator.java49
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/RuleValidator.java56
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/EventListenerDefinition.java101
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesDataItemsDefinition.java9
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesDataTypeDefinition.java270
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesJsonDeserializer.java20
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesSimpleTypesEnum.java26
-rw-r--r--dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesStructureLoader.java115
57 files changed, 5187 insertions, 0 deletions
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionConfig.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionConfig.java
new file mode 100644
index 0000000..ee8f5c6
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionConfig.java
@@ -0,0 +1,87 @@
+package org.onap.sdc.dcae.composition;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.PostConstruct;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.context.annotation.PropertySources;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+@Component
+@PropertySources({
+ @PropertySource(value="classpath:application-fe.properties", ignoreResourceNotFound=true),
+ @PropertySource(value="file:${jetty.base}/config/dcae-be/application.properties", ignoreResourceNotFound=true)
+})
+
+public class CompositionConfig {
+
+ private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ @Value("${compositionConfig.flowTypes}")
+ private String flowTypes;
+ @JsonIgnore
+ private Map<String, FlowType> flowTypesMap;
+ @Value("${compositionConfig.isRuleEditorActive}")
+ private boolean isRuleEditorActive;
+
+ // get flowTypes as the parsed keySet
+ public Set<String> getFlowTypes() {
+ return flowTypesMap.keySet();
+ }
+
+ @JsonProperty("isRuleEditorActive")
+ public boolean isRuleEditorActive() {
+ return isRuleEditorActive;
+ }
+
+ public Map<String, FlowType> getFlowTypesMap() {
+ return flowTypesMap;
+ }
+
+ public static class FlowType {
+
+ private String entryPointPhaseName;
+ private String lastPhaseName;
+
+ public String getEntryPointPhaseName() {
+ return entryPointPhaseName;
+ }
+
+ public void setEntryPointPhaseName(String entryPointPhaseName) {
+ this.entryPointPhaseName = entryPointPhaseName;
+ }
+
+ public String getLastPhaseName() {
+ return lastPhaseName;
+ }
+
+ public void setLastPhaseName(String lastPhaseName) {
+ this.lastPhaseName = lastPhaseName;
+ }
+ }
+
+
+ @PostConstruct
+ public void init() {
+ try {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Reading flow type definitions from configuration");
+ Type map = new TypeToken<Map<String, FlowType>>(){}.getType();
+ flowTypesMap = new Gson().fromJson(flowTypes, map);
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error – Failed to read flow type definitions");
+ }
+ }
+} \ No newline at end of file
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionEngine.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionEngine.java
new file mode 100644
index 0000000..186f3f6
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionEngine.java
@@ -0,0 +1,140 @@
+package org.onap.sdc.dcae.composition;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Properties;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import javax.servlet.ServletContext;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.util.SystemProperties;
+import org.onap.sdc.dcae.filter.LoggingFilter;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ErrorConfiguration;
+import org.onap.sdc.dcae.errormng.ErrorConfigurationLoader;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+@Configuration
+@EnableScheduling
+@SpringBootApplication
+@ComponentScan("org.onap.sdc.dcae")
+@EnableAutoConfiguration
+@PropertySource("file:${jetty.base}/config/dcae-be/application.properties")
+public class CompositionEngine extends SpringBootServletInitializer implements CommandLineRunner{
+ private static final String SPECIFICATION_VERSION = "Specification-Version";
+ @Autowired
+ ServletContext servletContext;
+ private static final String MANIFEST_FILE_NAME = "/META-INF/MANIFEST.MF";
+ private static String dcaeVersion;
+ private OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ public static void main(String[] args) {
+ SpringApplication.run(CompositionEngine.class, args);
+ }
+
+ /**
+ * Creates and returns a new instance of a {@link SystemProperties} class.
+ *
+ * @return New instance of {@link SystemProperties}.
+ */
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(CompositionEngine.class);
+ }
+
+
+ @Bean
+ public WebMvcConfigurer corsConfigurer() {
+ return new WebMvcConfigurerAdapter() {
+ @Override
+ public void addCorsMappings(CorsRegistry registry) {
+ registry.addMapping("/**")
+ .allowedOrigins("*")
+ .allowedHeaders("*")
+ .allowedMethods("GET", "POST", "OPTIONS", "PUT")
+ .allowCredentials(false)
+ .maxAge(3600);
+
+ }
+ };
+ }
+
+ @Override
+ public void run(String... args) throws Exception {
+
+ ErrorConfigurationLoader errorConfigurationLoader = new ErrorConfigurationLoader(System.getProperty("jetty.base"));
+ ErrConfMgr instance = ErrConfMgr.INSTANCE;
+ InputStream inputStream = servletContext.getResourceAsStream(MANIFEST_FILE_NAME);
+
+ //setLogbackXmlLocation();
+
+ String version = null;
+ try {
+ Manifest mf = new Manifest(inputStream);
+ Attributes atts = mf.getMainAttributes();
+ version = atts.getValue(SPECIFICATION_VERSION);
+ if (version == null || version.isEmpty()) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "failed to read DCAE version from MANIFEST.");
+ } else {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "DCAE version from MANIFEST is {}", version);
+ dcaeVersion = version;
+ }
+
+ } catch (IOException e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "failed to read DCAE version from MANIFEST: {}", e.getMessage());
+ }
+
+ }
+
+ private void setLogbackXmlLocation() throws Exception {
+ String jettyBase = System.getProperty("config.home");
+ Properties props = System.getProperties();
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Current System Properties are: {}", props);
+ if (jettyBase == null) {
+ String msg = "Couldn't resolve config.home environmental variable";
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), msg);
+ throw new Exception(msg + ". Failed to configure logback.xml location... aborting.");
+ }
+ String logbackXmlLocation = jettyBase+"/dcae-be/logback.xml";
+ props.setProperty("logback.configurationFile", logbackXmlLocation);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Successfuly set the logback.xml location to {}", logbackXmlLocation);
+ }
+
+ @Bean
+ public FilterRegistrationBean contextLifecycleFilter() {
+ Collection<String> urlPatterns = new ArrayList<>();
+ urlPatterns.add("/*");
+
+ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new LoggingFilter());
+ filterRegistrationBean.setUrlPatterns(urlPatterns);
+
+ return filterRegistrationBean;
+ }
+
+ public static String getDcaeVersion() {
+ return dcaeVersion;
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BaseController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BaseController.java
new file mode 100644
index 0000000..8b590ca
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BaseController.java
@@ -0,0 +1,80 @@
+package org.onap.sdc.dcae.composition.controller;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.impl.BaseBusinessLogic;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Asset;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
+import org.onap.sdc.dcae.composition.util.SystemProperties;
+import org.onap.sdc.dcae.enums.AssetType;
+import org.onap.sdc.dcae.enums.LifecycleOperationType;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.DcaeException;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ErrConfMgr.ApiType;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ModelAttribute;
+
+import com.google.gson.Gson;
+
+public abstract class BaseController {
+
+ protected Gson gson = new Gson();
+
+ @Autowired
+ protected SystemProperties systemProperties;
+
+ @Autowired
+ protected BaseBusinessLogic baseBusinessLogic;
+
+ protected OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ protected OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ @ModelAttribute("requestId")
+ public String getRequestId(HttpServletRequest request) {
+ return request.getAttribute("requestId").toString();
+ }
+
+ Asset checkout(String userId, String uuid, AssetType assetType, String requestId) throws Exception {
+ return baseBusinessLogic.getSdcRestClient().changeAssetLifecycleState(userId, uuid, LifecycleOperationType.CHECKOUT.name(), null, assetType, requestId);
+ }
+
+ Asset checkin(String userId, String uuid, AssetType assetType, String requestId) throws Exception {
+ return baseBusinessLogic.getSdcRestClient().changeAssetLifecycleState(userId, uuid, LifecycleOperationType.CHECKIN.name(), "checking in " + assetType.name() + uuid, assetType, requestId);
+ }
+
+
+ boolean isNeedToCheckOut(String lifecycleState) {
+ return DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT != DcaeBeConstants.LifecycleStateEnum.findState(lifecycleState);
+ }
+
+ void checkUserIfResourceCheckedOut(String userId, Asset asset) throws DcaeException {
+ if (DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT == DcaeBeConstants.LifecycleStateEnum.findState(asset.getLifecycleState())) {
+ String lastUpdaterUserId = asset.getLastUpdaterUserId();
+ if (lastUpdaterUserId != null && !lastUpdaterUserId.equals(userId)) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "User conflicts. Operation not allowed for user {} on resource checked out by {}", userId, lastUpdaterUserId);
+ ResponseFormat responseFormat = ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.USER_CONFLICT, null, userId, asset.getName(), lastUpdaterUserId);
+ throw new DcaeException(HttpStatus.FORBIDDEN, responseFormat.getRequestError());
+ }
+ }
+ }
+
+ void checkVfcmtType(ResourceDetailed vfcmt) {
+ if (!"VFCMT".equals(vfcmt.getResourceType()) || !"Template".equals(vfcmt.getCategory())) {
+ ResponseFormat responseFormat = ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.RESOURCE_NOT_VFCMT_ERROR, null, vfcmt.getUuid());
+ throw new DcaeException(HttpStatus.BAD_REQUEST, responseFormat.getRequestError());
+ }
+ }
+
+ ResponseEntity handleException(Exception e, ApiType apiType, String... variables){
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), e.getMessage());
+ return ErrConfMgr.INSTANCE.handleException(e, apiType, variables);
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BlueprintController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BlueprintController.java
new file mode 100644
index 0000000..a12c6b8
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BlueprintController.java
@@ -0,0 +1,239 @@
+package org.onap.sdc.dcae.composition.controller;
+
+import org.apache.commons.lang.StringUtils;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.MessageResponse;
+import org.onap.sdc.dcae.catalog.asdc.ASDC;
+import org.onap.sdc.dcae.catalog.asdc.ASDCUtils;
+import org.onap.sdc.dcae.catalog.asdc.Blueprinter;
+import org.onap.sdc.dcae.composition.restmodels.sdc.*;
+import org.onap.sdc.dcae.utils.Normalizers;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
+import org.onap.sdc.dcae.enums.ArtifactType;
+import org.onap.sdc.dcae.enums.AssetType;
+import org.onap.sdc.dcae.enums.LifecycleOperationType;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ErrConfMgr.ApiType;
+import org.onap.sdc.dcae.utils.SdcRestClientUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.PostConstruct;
+import java.io.StringReader;
+import java.net.URI;
+
+@RestController
+@EnableAutoConfiguration
+@CrossOrigin
+public class BlueprintController extends BaseController{
+
+ @Autowired
+ private Blueprinter blueprinter;
+
+ @Autowired
+ private ASDC asdc;
+
+ private static final String CREATE_DESC = "creating new artifact blueprint on the service vfi";
+ private static final String UPDATE_DESC = "updating artifact blueprint on the service vfi";
+
+
+
+ @PostConstruct
+ public void init(){
+ URI sdcUri = URI.create(systemProperties.getProperties().getProperty(DcaeBeConstants.Config.URI));
+ asdc.setUri(sdcUri);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "SDC uri: {}", sdcUri);
+ }
+
+ /***
+ * VFCMT - Resource, blueprint - as an artifact as an service.
+ * @param userId
+ * @param vfcmtUuid
+ * @param serviceUuid
+ * @param serviceInstanceName
+ * @param monitoringFlowType
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = "/createBluePrint/{VFCMTUuid}/{serviceUuid}/{instanceName}/{monitoringFlowType}", method = RequestMethod.POST)
+ public ResponseEntity createBluePrint(@RequestHeader("USER_ID") String userId,
+ @PathVariable("VFCMTUuid") String vfcmtUuid,
+ @PathVariable("serviceUuid") String serviceUuid,
+ @PathVariable("instanceName") String serviceInstanceName,
+ @PathVariable("monitoringFlowType") String monitoringFlowType,
+ @ModelAttribute("requestId") String requestId) {
+ try {
+
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), vfcmt.toString());
+ checkVfcmtType(vfcmt);
+ Artifact cdumpArtifactData = findCdumpArtifactData(vfcmt);
+ if (null != cdumpArtifactData) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Found the cdump (composition.yml) on top of VFCMT {}", vfcmtUuid);
+ String cdump = baseBusinessLogic.getSdcRestClient().getResourceArtifact(vfcmtUuid, cdumpArtifactData.getArtifactUUID(), requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "---------------------------------------------------------------CDUMP: -----------------------------------------------------------------------------");
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), cdump);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "---------------------------------------------------------------------------------------------------------------------------------------------------");
+ ASDCUtils utils = new ASDCUtils(asdc, blueprinter);
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Going to use python procedure to create a blueprint....");
+ String resultBlueprintCreation;
+ try{
+ resultBlueprintCreation = utils.buildBlueprintViaToscaLab(new StringReader(cdump)).waitForResult().waitForResult();
+ }catch (Exception e){
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERATE_BLUEPRINT_ERROR, e.getMessage(), vfcmt.getName());
+ }
+ if (StringUtils.isEmpty(resultBlueprintCreation)) {
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERATE_BLUEPRINT_ERROR, "", vfcmt.getName());
+ }
+
+ // 1806 US374595 flowType in cdump
+ String flowTypeFromCdump = StringUtils.substringBetween(cdump,"\"flowType\":\"","\"");
+ if(StringUtils.isNotBlank(flowTypeFromCdump)) {
+ monitoringFlowType = flowTypeFromCdump;
+ }
+ // saving to serviceVfInstance
+ Artifact savedBluePrint = saveBluePrint(userId, serviceUuid, serviceInstanceName, resultBlueprintCreation, monitoringFlowType, vfcmt.getName(), requestId);
+ if(savedBluePrint!=null){
+ MessageResponse response = new MessageResponse();
+ response.setSuccessResponse("Blueprint build complete \n. Blueprint="+savedBluePrint.getArtifactName());
+ //1806 US374593 - certify VFCMT after BP generation
+ certifyVfcmt(vfcmt, requestId);
+ return new ResponseEntity<>(response, HttpStatus.OK);
+ }
+ else{
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SUBMIT_BLUEPRINT_ERROR);
+ }
+
+ }else{
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.MISSING_TOSCA_FILE, "", vfcmt.getName());
+ }
+ } catch (Exception e) {
+ return handleException(e, ApiType.SUBMIT_BLUEPRINT);
+ }
+ }
+
+
+ /********************* private function ********************/
+
+ /**
+ * @param userId
+ * @param serviceUuid
+ * @param resourceInstanceName
+ * @param bluePrint
+ * @param monitoringFlowType
+ * @param vfcmtName
+ * @param requestId
+ * @return
+ * @throws Exception
+ */
+ private Artifact saveBluePrint(String userId, String serviceUuid, String resourceInstanceName, String bluePrint, String monitoringFlowType, String vfcmtName, String requestId) throws Exception {
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "BLUEPRINT:\n{}", bluePrint);
+ try {
+ ServiceDetailed service = baseBusinessLogic.getSdcRestClient().getService(serviceUuid, requestId);
+ //Validations
+ checkUserIfResourceCheckedOut(userId, service);
+ ResourceInstance vfi = findVfiOnService(service, resourceInstanceName);
+ if(null == vfi){
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "VF instance {} not found on service {}", resourceInstanceName, serviceUuid);
+ return null;
+ }
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), service.toString());
+
+ String normalizedArtifactLabel = Normalizers.normalizeArtifactLabel("blueprint-" + monitoringFlowType);
+ Artifact blueprintArtifact = CollectionUtils.isEmpty(vfi.getArtifacts()) ? null : vfi.getArtifacts().stream()
+ .filter(p -> normalizedArtifactLabel.equals(Normalizers.normalizeArtifactLabel(p.getArtifactLabel())))
+ .findAny()
+ .orElse(null);
+
+ boolean isNeed2Checkout = isNeedToCheckOut(service.getLifecycleState());
+ if (isNeed2Checkout) {
+ Asset result = checkout(userId, serviceUuid, AssetType.SERVICE, requestId);
+ if (result != null) {
+ serviceUuid = result.getUuid();
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New service after checkout is: {}", serviceUuid);
+ }
+ }
+ //update mode
+ if (null != blueprintArtifact) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Found that service {} already consist of {} ----> updateMode", serviceUuid, normalizedArtifactLabel);
+ blueprintArtifact.setDescription(UPDATE_DESC);
+ blueprintArtifact.setPayloadData(Base64Utils.encodeToString(bluePrint.getBytes()));
+ blueprintArtifact = baseBusinessLogic.getSdcRestClient().updateVfInstanceArtifact(userId, serviceUuid, Normalizers.normalizeComponentInstanceName(resourceInstanceName), blueprintArtifact, requestId);
+ //create mode
+ } else {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Service {} does not consist {} ----> createMode", serviceUuid, normalizedArtifactLabel);
+ blueprintArtifact = SdcRestClientUtils.generateDeploymentArtifact(CREATE_DESC, generateBlueprintFileName(monitoringFlowType, vfcmtName), ArtifactType.DCAE_INVENTORY_BLUEPRINT.name(), normalizedArtifactLabel, bluePrint.getBytes());
+ blueprintArtifact = baseBusinessLogic.getSdcRestClient().createVfInstanceArtifact(userId, serviceUuid, Normalizers.normalizeComponentInstanceName(resourceInstanceName), blueprintArtifact, requestId);
+ }
+
+ //No need to check the service in in 1806
+// Asset blueprintAsJson = checkin(user_id, serviceUuid, AssetType.SERVICE);
+// debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "service result after check-in: {}", blueprintAsJson.toString());
+
+ return blueprintArtifact;
+
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error occurred while trying to save blueprint {}", e.toString());
+ throw e;
+ }
+ }
+
+ /**
+ *
+ * @param monitoringFlowType
+ * @param vfcmtName
+ * @return
+ */
+ private String generateBlueprintFileName(String monitoringFlowType, String vfcmtName) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(monitoringFlowType);
+ sb.append(".");
+ sb.append(Normalizers.normalizeComponentName(vfcmtName));
+ sb.append(".");
+ sb.append(DcaeBeConstants.Composition.fileNames.EVENT_PROC_BP_YAML);
+ return sb.toString();
+ }
+
+ private ResourceInstance findVfiOnService(ServiceDetailed service, String vfiName) {
+ return null == service ? null : CollectionUtils.isEmpty(service.getResources()) ? null : service.getResources().stream().filter(p -> vfiName.equals(p.getResourceInstanceName())).findAny().orElse(null);
+ }
+
+ private Artifact findCdumpArtifactData(ResourceDetailed vfcmt) {
+ return null == vfcmt ? null : CollectionUtils.isEmpty(vfcmt.getArtifacts()) ? null : vfcmt.getArtifacts().stream()
+ .filter(p -> DcaeBeConstants.Composition.fileNames.COMPOSITION_YML.equals(p.getArtifactName())).findAny().orElse(null);
+ }
+
+ private void certifyVfcmt(ResourceDetailed vfcmt, String requestId){
+ String state = vfcmt.getLifecycleState();
+ if(null == state) {
+ debugLogger.log(LogLevel.ERROR, this.getClass().getName(), "Couldn't read Vfcmt lifecycle state");
+ return;
+ }
+ DcaeBeConstants.LifecycleStateEnum lifeCycleState = DcaeBeConstants.LifecycleStateEnum.findState(state);
+ if(null == lifeCycleState) {
+ debugLogger.log(LogLevel.ERROR, this.getClass().getName(), "Undefined lifecycle state: {}", state);
+ return;
+ }
+ try{
+ switch (lifeCycleState){
+ case NOT_CERTIFIED_CHECKOUT:
+ baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(vfcmt.getLastUpdaterUserId(), vfcmt.getUuid(), LifecycleOperationType.CHECKIN.name(), "check in VFCMT after blueprint successful submission", requestId);
+ case NOT_CERTIFIED_CHECKIN:
+ baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(vfcmt.getLastUpdaterUserId(), vfcmt.getUuid(), LifecycleOperationType.CERTIFY.name(), "certify VFCMT after blueprint successful submission", requestId);
+ }
+ }
+ catch (Exception e){
+ //informative only. no message to user (TBA)
+ debugLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error occurred during vfcmt lifecycle operation: {}", e.toString());
+ }
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/CompositionController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/CompositionController.java
new file mode 100644
index 0000000..5cba14f
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/CompositionController.java
@@ -0,0 +1,338 @@
+package org.onap.sdc.dcae.composition.controller;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.MessageResponse;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Asset;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
+import org.onap.sdc.dcae.catalog.Catalog;
+import org.onap.sdc.dcae.catalog.Catalog.*;
+import org.onap.sdc.dcae.catalog.engine.*;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
+import org.onap.sdc.dcae.enums.ArtifactType;
+import org.onap.sdc.dcae.enums.LifecycleOperationType;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ErrConfMgr.ApiType;
+import org.onap.sdc.dcae.utils.SdcRestClientUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.context.request.async.DeferredResult;
+
+import javax.annotation.PostConstruct;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@RestController
+@EnableAutoConfiguration
+@CrossOrigin
+public class CompositionController extends BaseController{
+
+ @Autowired
+ private CatalogController catalogController;
+
+ @PostConstruct
+ public void init() {
+ catalogController.setDefaultCatalog(URI.create(systemProperties.getProperties().getProperty(DcaeBeConstants.Config.ASDC_CATALOG_URL)));
+ }
+
+ @RequestMapping(value = { "/utils/clone/{assetType}/{sourceId}/{targetId}" }, method = {RequestMethod.GET }, produces = { "application/json" })
+ public ResponseEntity clone(@RequestHeader("USER_ID") String userId, @PathVariable("assetType") String theAssetType, @PathVariable("sourceId") String theSourceId, @PathVariable("targetId") String theTargetId,
+ @ModelAttribute("requestId") String requestId) {
+ MessageResponse response = new MessageResponse();
+
+ try {
+ // fetch the source and assert it is a vfcmt containing clone worthy artifacts (composition + rules)
+ ResourceDetailed sourceVfcmt = baseBusinessLogic.getSdcRestClient().getResource(theSourceId, requestId);
+ checkVfcmtType(sourceVfcmt);
+ List<Artifact> artifactsToClone = CollectionUtils.isEmpty(sourceVfcmt.getArtifacts()) ? null : sourceVfcmt.getArtifacts().stream()
+ .filter(p -> DcaeBeConstants.Composition.fileNames.COMPOSITION_YML.equals(p.getArtifactName()) || p.getArtifactName().endsWith(DcaeBeConstants.Composition.fileNames.MAPPING_RULE_POSTFIX))
+ .collect(Collectors.toList());
+ if(CollectionUtils.isEmpty(artifactsToClone)) {
+ response.setSuccessResponse("Nothing to clone");
+ return new ResponseEntity<>(response ,HttpStatus.NO_CONTENT);
+ }
+
+ // fetch the target
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(theTargetId, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), vfcmt.toString());
+ checkVfcmtType(vfcmt);
+ checkUserIfResourceCheckedOut(userId, vfcmt);
+ boolean isTargetNeed2Checkout = isNeedToCheckOut(vfcmt.getLifecycleState());
+ if (isTargetNeed2Checkout) {
+ ResourceDetailed targetVfcmt = baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, theTargetId, LifecycleOperationType.CHECKOUT.name(), "checking out VFCMT before clone", requestId);
+ if(null == targetVfcmt){
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERAL_ERROR);
+ }
+ theTargetId = targetVfcmt.getUuid();
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New targetVfcmt (for artifact clone) after checkout is: {}", theTargetId);
+ }
+
+ Map<String, Artifact> currentArtifacts = CollectionUtils.isEmpty(vfcmt.getArtifacts()) ? new HashMap<>() : vfcmt.getArtifacts().stream()
+ .collect(Collectors.toMap(Artifact::getArtifactName, Function.identity()));
+
+ //TODO target VFCMT rule artifacts should be removed
+ for(Artifact artifactToClone : artifactsToClone) {
+ String payload = baseBusinessLogic.getSdcRestClient().getResourceArtifact(theSourceId, artifactToClone.getArtifactUUID(), requestId);
+ baseBusinessLogic.cloneArtifactToTarget(userId, theTargetId, payload, artifactToClone, currentArtifacts.get(artifactToClone.getArtifactName()), requestId);
+ }
+
+ baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, theTargetId, LifecycleOperationType.CHECKIN.name(), "check in VFCMT after clone", requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Cloning {} from {} has finished successfully", theSourceId, theTargetId);
+ response.setSuccessResponse("Clone VFCMT complete");
+ return new ResponseEntity<>(response, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.CLONE_VFCMT);
+ }
+ }
+
+ @RequestMapping(value = "/elements", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json")
+ public DeferredResult<CatalogResponse> items(@RequestBody(required = false) ItemsRequest theRequest) {
+
+ final ItemsRequest request = (theRequest == null) ? ItemsRequest.EMPTY_REQUEST : theRequest;
+
+ Catalog catalog = catalogController.getCatalog(request.getCatalog());
+ DeferredResult<CatalogResponse> result = new DeferredResult<CatalogResponse>(request.getTimeout());
+
+ catalog.rootsByLabel(request.getStartingLabel())
+ .setHandler(catalogController.new CatalogHandler<Folders>(request, result) {
+ public CatalogResponse handleData(Folders theFolders) {
+ JSONArray ja = new JSONArray();
+ if (theFolders != null) {
+ for (Folder folder : theFolders) {
+ ja.put(catalogController.patchData(catalog, folder.data()));
+ }
+ }
+ CatalogResponse response = new CatalogResponse(this.request);
+ try {
+ response.data().put("elements", ja);
+ } catch (JSONException e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "JSONException putting json elements to response {}", e);
+ }
+ return response;
+ }
+ });
+ return result;
+ }
+
+ @RequestMapping(value = "/{theItemId}/elements", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json")
+ public DeferredResult<CatalogResponse> items(@RequestBody(required = false) ItemsRequest theRequest, @PathVariable String theItemId) {
+
+ final ItemsRequest request = (theRequest == null) ? ItemsRequest.EMPTY_REQUEST : theRequest;
+
+ Catalog catalog = catalogController.getCatalog(request.getCatalog());
+ DeferredResult<CatalogResponse> result = new DeferredResult<CatalogResponse>(request.getTimeout());
+
+ catalog
+ // .fetchFolderByItemId(theItemId)
+ .folder(theItemId).withParts().withPartAnnotations().withItems().withItemAnnotations().withItemModels()
+ .execute().setHandler(catalogController.new CatalogHandler<Folder>(request, result) {
+ public CatalogResponse handleData(Folder theFolder) {
+ CatalogResponse response = new CatalogResponse(this.request);
+ if (theFolder == null) {
+ return response;
+ }
+
+ try {
+ Elements folders = theFolder.elements("parts", Folders.class);
+ if (folders != null) {
+ for (Object folder : folders) {
+ catalogController.patchData(catalog, ((Element) folder).data());
+ // lots of ephemere proxies created here ..
+ Elements annotations = ((Element) folder).elements("annotations",
+ Annotations.class);
+ if (annotations != null) {
+ for (Object a : annotations) {
+ catalogController.patchData(catalog, ((Annotation) a).data());
+ }
+ }
+ }
+ }
+ Elements items = theFolder.elements("items", Items.class);
+ if (items != null) {
+ for (Object i : items) {
+ catalogController.patchData(catalog, ((Element) i).data());
+ // lots of ephemere proxies created here ..
+ Elements annotations = ((Element) i).elements("annotations", Annotations.class);
+ if (annotations != null) {
+ for (Object a : annotations) {
+ catalogController.patchData(catalog, ((Annotation) a).data());
+ }
+ }
+ }
+ }
+ } catch (Exception x) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Exception processing catalog {}", x);
+ return new CatalogError(this.request, "", x);
+ }
+
+ try {
+ response.data().put("element", theFolder.data());
+ } catch (JSONException e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "JSONException putting element to response {}", e);
+ }
+ return response;
+ }
+ });
+
+ return result;
+ }
+
+ @RequestMapping(value = "/{theItemId}/model", method = { RequestMethod.POST,RequestMethod.GET }, produces = "application/json")
+ public DeferredResult model(@RequestBody(required = false) ElementRequest theRequest,
+ @PathVariable String theItemId) {
+ final ElementRequest request = (theRequest == null) ? ElementRequest.EMPTY_REQUEST : theRequest;
+
+ Catalog catalog = catalogController.getCatalog(request.getCatalog());
+ DeferredResult<CatalogResponse> result = new DeferredResult<>(request.getTimeout());
+
+ catalog
+ .item(theItemId).withModels().execute()
+ .setHandler(catalogController.new CatalogHandler<Item>(request, result) {
+ public CatalogResponse handleData(Item theItem) {
+ if (theItem == null) {
+ return new CatalogError(this.request, "No such item");
+ }
+ Templates models = null;
+ try {
+ models = (Templates) theItem.elements("models", Templates.class);
+ if (models == null || models.isEmpty()) {
+ return new CatalogError(this.request, "Item has no models");
+ }
+ if (models.size() > 1) {
+ return new CatalogError(this.request, "Item has more than one model !?");
+ }
+ catalog.template(models.get(0).id()).withInputs().withOutputs().withNodes()
+ .withNodeProperties().withNodePropertiesAssignments().withNodeRequirements()
+ .withNodeCapabilities().withNodeCapabilityProperties()
+ .withNodeCapabilityPropertyAssignments().withPolicies().withPolicyProperties()
+ .withPolicyPropertiesAssignments().execute().setHandler(
+ catalogController.new CatalogHandler<Template>(this.request, this.result) {
+ public CatalogResponse handleData(Template theTemplate) {
+ CatalogResponse response = new CatalogResponse(this.request);
+ if (theTemplate != null) {
+ try {
+ response.data().put("model", catalogController
+ .patchData(catalog, theTemplate.data()));
+ } catch (JSONException e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "JSONException putting model to response {}", e);
+ }
+ }
+ return response;
+ }
+ });
+ } catch (Exception e) {
+ handleException(e, ApiType.GET_MODEL, models.get(0).name());
+ }
+ return null;
+ }
+ });
+
+ return result;
+ }
+
+ @RequestMapping(value = "/{theItemId}/type/{theTypeName}", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json")
+ public DeferredResult<CatalogResponse> model(@RequestBody(required = false) ElementRequest theRequest, @PathVariable String theItemId, @PathVariable String theTypeName) {
+ final ElementRequest request = (theRequest == null) ? ElementRequest.EMPTY_REQUEST : theRequest;
+
+ Catalog catalog = catalogController.getCatalog(request.getCatalog());
+ DeferredResult<CatalogResponse> result = new DeferredResult<CatalogResponse>(request.getTimeout());
+
+ catalog.type(theItemId, theTypeName).withHierarchy().withCapabilities().withRequirements().execute()
+ .setHandler(catalogController.new CatalogHandler<Type>(request, result) {
+ public CatalogResponse handleData(Type theType) {
+ CatalogResponse response = new CatalogResponse(this.request);
+ if (theType != null) {
+ try {
+ response.data().put("type", catalogController.patchData(catalog, theType.data()));
+ } catch (JSONException e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Exception processing catalog {}", e);
+ }
+ }
+ return response;
+ }
+ });
+
+ return result;
+ }
+
+ @RequestMapping(value = { "/getComposition/{vfcmtUuid}" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity getComposition(@PathVariable("vfcmtUuid") String vfcmtUuid, @ModelAttribute("requestId") String requestId) {
+ MessageResponse response = new MessageResponse();
+ try {
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), vfcmt.toString());
+ checkVfcmtType(vfcmt);
+
+ Artifact compositionArtifact = CollectionUtils.isEmpty(vfcmt.getArtifacts()) ? null : vfcmt.getArtifacts().stream().filter(a -> DcaeBeConstants.Composition.fileNames.COMPOSITION_YML.equals(a.getArtifactName())).findAny().orElse(null);
+
+ if(null == compositionArtifact){
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Couldn't find {} in VFCMT artifacts", DcaeBeConstants.Composition.fileNames.COMPOSITION_YML);
+ response.setErrorResponse("No Artifacts");
+ return new ResponseEntity<>(response, HttpStatus.NO_CONTENT);
+ }
+
+ String artifact = baseBusinessLogic.getSdcRestClient().getResourceArtifact(vfcmtUuid, compositionArtifact.getArtifactUUID(), requestId);
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "ARTIFACT: {}", artifact);
+ response.setSuccessResponse(artifact);
+ return new ResponseEntity<>(response, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.GET_CDUMP);
+ }
+ }
+
+ @RequestMapping(value = "/saveComposition/{vfcmtUuid}", method = RequestMethod.POST)
+ public ResponseEntity saveComposition(@RequestHeader("USER_ID") String userId, @RequestBody String theCdump, @PathVariable("vfcmtUuid") String vfcmtUuid, @ModelAttribute("requestId") String requestId) {
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "ARTIFACT CDUMP: {}", theCdump);
+
+ try {
+
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "VFCMT: {}", vfcmt);
+
+ checkVfcmtType(vfcmt);
+ checkUserIfResourceCheckedOut(userId, vfcmt);
+ boolean isNeed2Checkout = isNeedToCheckOut(vfcmt.getLifecycleState());
+ Artifact compositionArtifact = CollectionUtils.isEmpty(vfcmt.getArtifacts()) ? null : vfcmt.getArtifacts().stream().filter(a -> DcaeBeConstants.Composition.fileNames.COMPOSITION_YML.equals(a.getArtifactName())).findAny().orElse(null);
+ String resourceUuid = vfcmtUuid; // by default the resource is the original vfcmtId unless a checkout will be done
+ if (isNeed2Checkout) {
+ vfcmt = baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, resourceUuid, LifecycleOperationType.CHECKOUT.name(), null, requestId);
+ if (vfcmt != null) {
+ resourceUuid = vfcmt.getUuid();
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New resource after checkout is: {}", resourceUuid);
+ }
+ }
+ boolean isUpdateMode = null != compositionArtifact;
+ if (isUpdateMode) {
+ compositionArtifact.setDescription("updating composition file");
+ compositionArtifact.setPayloadData(Base64Utils.encodeToString(theCdump.getBytes()));
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "VFCMT {} does consist {} ----> updateMode", resourceUuid, DcaeBeConstants.Composition.fileNames.COMPOSITION_YML);
+ baseBusinessLogic.getSdcRestClient().updateResourceArtifact(userId, resourceUuid, compositionArtifact, requestId);
+
+ } else {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "VFCMT {} does not consist {} ----> createMode", resourceUuid, DcaeBeConstants.Composition.fileNames.COMPOSITION_YML);
+ compositionArtifact = SdcRestClientUtils.generateDeploymentArtifact("creating composition file", DcaeBeConstants.Composition.fileNames.COMPOSITION_YML, ArtifactType.DCAE_TOSCA.name(), "composition", theCdump.getBytes());
+ baseBusinessLogic.getSdcRestClient().createResourceArtifact(userId, resourceUuid, compositionArtifact, requestId);
+ }
+ Asset result = checkin(userId, resourceUuid, org.onap.sdc.dcae.enums.AssetType.RESOURCE, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "vfcmt check-in result: {}", result);
+
+ return new ResponseEntity<>(result, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.SAVE_CDUMP);
+ }
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ConfigurationController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ConfigurationController.java
new file mode 100644
index 0000000..4f083ca
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ConfigurationController.java
@@ -0,0 +1,63 @@
+package org.onap.sdc.dcae.composition.controller;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.CompositionConfig;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.ves.VesStructureLoader;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+@RestController
+@EnableAutoConfiguration
+@CrossOrigin
+@RequestMapping("/conf")
+public class ConfigurationController extends BaseController{
+
+ @Autowired
+ private CompositionConfig compositionConfig;
+
+ @ApiOperation(value = "Get a list of available flow types", response = CompositionConfig.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = 200, message = "Successfully retrieved available flow types list"),
+ @ApiResponse(code = 500, message = "Flow types couldn't be fetched due to internal error")})
+ @RequestMapping(value = "/composition", method = RequestMethod.GET)
+ public ResponseEntity getCompositionConfig() {
+ try {
+ return new ResponseEntity<>(compositionConfig, HttpStatus.OK);
+ }catch (Exception e) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"Exception:{}",e);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.FLOW_TYPES_CONFIGURATION_ERROR);
+ }
+ }
+
+ @RequestMapping(value = "/ves/schemaversions", method = RequestMethod.GET)
+ public ResponseEntity getCommonEventFormatVersion() {
+ try {
+ Set<String> availableVersionsSet = VesStructureLoader.getAvailableVersionsList();
+ List<String> availableVersionsList = new ArrayList<>(availableVersionsSet.size());
+ availableVersionsList.addAll(availableVersionsSet);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Got a request to return available ves schema versions: {}", availableVersionsSet);
+ return new ResponseEntity<>(availableVersionsList, HttpStatus.OK);
+ }catch (Exception e) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"Exception:{}",e);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.VES_SCHEMA_NOT_FOUND);
+ }
+ }
+
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/LifecycleController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/LifecycleController.java
new file mode 100644
index 0000000..3007335
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/LifecycleController.java
@@ -0,0 +1,84 @@
+package org.onap.sdc.dcae.composition.controller;
+
+import org.onap.sdc.dcae.composition.restmodels.sdc.Asset;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
+import org.onap.sdc.dcae.enums.AssetType;
+import org.onap.sdc.dcae.enums.LifecycleOperationType;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.UUID;
+
+@RestController
+@EnableAutoConfiguration
+@CrossOrigin
+public class LifecycleController extends BaseController {
+
+ private static final String VFCMT = "vfcmt";
+
+ @RequestMapping(value={"/checkin/{assetType}/{uuid}"}, method={RequestMethod.PUT}, produces={"application/json"})
+ public ResponseEntity putCheckin(
+ @PathVariable("assetType") String assetType,
+ @PathVariable("uuid") UUID uuid,
+ @RequestHeader("USER_ID") String user_id,
+ @ModelAttribute("requestId") String requestId) {
+
+ try {
+ switch (assetType) {
+ case VFCMT:
+ Asset res_checkin = checkin(user_id, uuid.toString(), AssetType.RESOURCE, requestId);
+ return new ResponseEntity<>(res_checkin, HttpStatus.OK);
+
+ default:
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+ } catch (Exception e) {
+ return handleException(e, ErrConfMgr.ApiType.CHECK_IN_RESOURCE);
+ }
+ }
+
+ @RequestMapping(value={"/checkout/{assetType}/{uuid}"}, method={RequestMethod.PUT}, produces={"application/json"})
+ public ResponseEntity putCheckout(
+ @PathVariable("assetType") String assetType,
+ @PathVariable("uuid") UUID uuid,
+ @RequestHeader("USER_ID") String user_id,
+ @ModelAttribute("requestId") String requestId) {
+
+ try {
+ switch (assetType) {
+ case VFCMT:
+ Asset asset = checkout(user_id, uuid.toString(), AssetType.RESOURCE, requestId);
+ return new ResponseEntity<>(asset, HttpStatus.OK);
+
+ default:
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+ } catch (Exception e) {
+ return handleException(e, ErrConfMgr.ApiType.CHECK_OUT_RESOURCE);
+ }
+ }
+
+ @RequestMapping(value={"/certify/{assetType}/{uuid}"}, method={RequestMethod.PUT}, produces={"application/json"})
+ public ResponseEntity putCertify(
+ @PathVariable("assetType") String assetType,
+ @PathVariable("uuid") String uuid,
+ @RequestHeader("USER_ID") String user_id,
+ @ModelAttribute("requestId") String requestId) {
+
+ try {
+ switch (assetType) {
+ case VFCMT:
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(user_id, uuid, LifecycleOperationType.CERTIFY.name(), "certifying VFCMT", requestId);
+ return new ResponseEntity<>(vfcmt, HttpStatus.OK);
+
+ default:
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+ } catch (Exception e) {
+ return handleException(e, ErrConfMgr.ApiType.CHECK_OUT_RESOURCE);
+ }
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/RuleEditorController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/RuleEditorController.java
new file mode 100644
index 0000000..3f5ff1a
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/RuleEditorController.java
@@ -0,0 +1,453 @@
+package org.onap.sdc.dcae.composition.controller;
+
+import com.google.gson.JsonParseException;
+import org.apache.commons.collections.ListUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Asset;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
+import org.onap.sdc.dcae.composition.CompositionConfig;
+import org.onap.sdc.dcae.utils.Normalizers;
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
+import org.onap.sdc.dcae.enums.ArtifactType;
+import org.onap.sdc.dcae.enums.AssetType;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ErrConfMgr.ApiType;
+import org.onap.sdc.dcae.errormng.ServiceException;
+import org.onap.sdc.dcae.rule.editor.impl.RulesBusinessLogic;
+import org.onap.sdc.dcae.rule.editor.utils.RulesPayloadUtils;
+import org.onap.sdc.dcae.utils.SdcRestClientUtils;
+import org.onap.sdc.dcae.ves.VesDataItemsDefinition;
+import org.onap.sdc.dcae.ves.VesDataTypeDefinition;
+import org.onap.sdc.dcae.ves.VesSimpleTypesEnum;
+import org.onap.sdc.dcae.ves.VesStructureLoader;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@RestController
+@EnableAutoConfiguration
+@CrossOrigin
+@RequestMapping("/rule-editor")
+public class RuleEditorController extends BaseController {
+
+ private static final String EXCEPTION = "Exception {}";
+ @Autowired
+ private CompositionConfig compositionConfig;
+
+ @Autowired
+ private RulesBusinessLogic rulesBusinessLogic;
+
+ @RequestMapping(value = "/list-events-by-versions", method = RequestMethod.GET)
+ public ResponseEntity getEventsByVersion() {
+ try {
+
+ Map<String, Set<String>> eventsByVersions = VesStructureLoader.getAvailableVersionsAndEventTypes();
+
+ List<EventTypesByVersionUI> resBody = eventsByVersions.entrySet().stream().map(entry -> {
+ Set<String> events = entry.getValue().stream().filter(event -> !EventTypesByVersionUI.DEFAULT_EVENTS.contains(event)).collect(Collectors.toSet());
+ return new EventTypesByVersionUI(entry.getKey(), events);
+ }).collect(Collectors.toList());
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Got a request to return all ves event types by versions {}", eventsByVersions);
+ return new ResponseEntity<>(resBody, HttpStatus.OK);
+
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), EXCEPTION, e);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.VES_SCHEMA_NOT_FOUND);
+ }
+ }
+
+ @RequestMapping(value = { "/definition/{version:.*}/{eventType}" }, method = { RequestMethod.GET }, produces = { "application/json" })
+ public ResponseEntity getDefinition(@PathVariable("version") String version,
+ @PathVariable("eventType") String eventType) {
+
+ try {
+ List<EventTypeDefinitionUI> result = getEventTypeDefinitionUIs(version, eventType);
+
+ return new ResponseEntity<>(result, HttpStatus.OK);
+
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), EXCEPTION, e);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.VES_SCHEMA_NOT_FOUND);
+ }
+ }
+
+ /**
+ * This endpoint functions as a 'create/update' service for the rule editor UI
+ *
+ * @param json - json representing the saved rule
+ * @param vfcmtUuid - VFCMT that the rule editor ui is saved in
+ * @param dcaeCompLabel - the name of the DCAE Component which the rule is applied to
+ * @param nid - A unique id of the DCAE Component which the rule is applied to - exists also in the cdump
+ * @param configParam - the name of the DCAE Component configuration property the rule is linked to
+ * @return json representing the rule editor UI
+ * Validations:
+ * 1. That the user is able to edit the VFCMT
+ * 2. That the cdump holds a dcae component with such nid (to avoid orphan rules)
+ * 3. Check that the fetched VFCMT is actually a VFCMT and not a regular VF
+ */
+ @RequestMapping(value = "/rule/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam}", method = { RequestMethod.POST }, produces = "application/json")
+ public ResponseEntity saveRule(@RequestBody String json, @ModelAttribute("requestId") String requestId,
+ @RequestHeader("USER_ID") String userId,
+ @PathVariable("vfcmtUuid") String vfcmtUuid,
+ @PathVariable("dcaeCompLabel") String dcaeCompLabel,
+ @PathVariable("nid") String nid,
+ @PathVariable("configParam") String configParam) {
+ try {
+ Rule rule = RulesPayloadUtils.parsePayloadToRule(json);
+ if (null == rule) {
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT);
+ }
+
+ List<ServiceException> errors = rulesBusinessLogic.validateRule(rule);
+ if(!errors.isEmpty()){
+ return ErrConfMgr.INSTANCE.buildErrorArrayResponse(errors);
+ }
+
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ checkVfcmtType(vfcmt);
+
+ if (CollectionUtils.isEmpty(vfcmt.getArtifacts())) {
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SAVE_RULE_FAILED);
+ }
+
+ String artifactLabel = Normalizers.normalizeArtifactLabel(dcaeCompLabel + nid + configParam);
+
+ // check for MappingRules artifact in existing artifacts
+ Artifact artifactFound = vfcmt.getArtifacts().stream()
+ .filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel())))
+ .findAny().orElse(null);
+
+ // exception thrown if vfcmt is checked out and current user is not its owner
+ // performs vfcmt checkout if required
+ String vfcmtId = assertOwnershipOfVfcmtId(userId, vfcmt, requestId);
+ // new mappingRules artifact, validate nid exists in composition before creating new artifact
+ if (null == artifactFound) {
+ if(cdumpContainsNid(vfcmt, nid, requestId)) {
+ return saveNewRulesArtifact(rule, vfcmtId, generateMappingRulesFileName(dcaeCompLabel, nid, configParam), artifactLabel , userId, requestId);
+ }
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.NODE_NOT_FOUND, "", dcaeCompLabel);
+ }
+
+ //update artifact flow - append new rule or edit existing rule
+ return addOrEditRuleInArtifact(rule, vfcmtId, userId, artifactFound, requestId);
+
+ } catch (JsonParseException je) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error: Rule format is invalid: {}", je);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "", je.getMessage());
+ } catch (Exception e) {
+ return handleException(e, ErrConfMgr.ApiType.SAVE_RULE_ARTIFACT);
+ }
+
+ }
+
+
+ /**
+ * This endpoint functions as a 'fetch' service for the rule editor UI
+ *
+ * @param vfcmtUuid - VFCMT that the rule editor ui is saved in
+ * @param dcaeCompLabel - the name of the DCAE Component which the rule is applied to
+ * @param nid - A unique id of the DCAE Component which the rule is applied to - exists also in the cdump
+ * @param configParam - the name of the DCAE Component configuration property the rule is linked to
+ * @return json representing the rule editor UI
+ */
+ @RequestMapping(value = "/rule/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam}", method = { RequestMethod.GET }, produces = "application/json")
+ public ResponseEntity getRules(
+ @PathVariable("vfcmtUuid") String vfcmtUuid,
+ @PathVariable("dcaeCompLabel") String dcaeCompLabel,
+ @PathVariable("nid") String nid,
+ @PathVariable("configParam") String configParam,
+ @ModelAttribute("requestId") String requestId) {
+
+ try {
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ if (CollectionUtils.isEmpty(vfcmt.getArtifacts())) {
+ return new ResponseEntity<>("{}", HttpStatus.OK);
+ }
+ String artifactLabel = Normalizers.normalizeArtifactLabel(dcaeCompLabel + nid + configParam);
+
+ // check for MappingRules artifact in existing artifacts
+ Artifact artifactListed = vfcmt.getArtifacts().stream().filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel()))).findAny().orElse(null);
+ if (null == artifactListed) {
+ return new ResponseEntity<>("{}", HttpStatus.OK);
+ }
+ String ruleFile = baseBusinessLogic.getSdcRestClient().getResourceArtifact(vfcmtUuid, artifactListed.getArtifactUUID(), requestId);
+
+ // To avoid opening the file for reading we search for the eventType and SchemaVer from the artifact metadata's description
+ SchemaInfo schemainfo = RulesPayloadUtils.extractInfoFromDescription(artifactListed);
+ List<EventTypeDefinitionUI> schema = null == schemainfo? new ArrayList<>() : getEventTypeDefinitionUIs(schemainfo.getVersion(), schemainfo.getEventType());
+ return new ResponseEntity<>(RulesPayloadUtils.buildSchemaAndRulesResponse(ruleFile, schema), HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.GET_RULE_ARTIFACT);
+ }
+
+ }
+
+ /**
+ * This endpoint functions as a 'delete' service for the rule editor UI
+ *
+ * @param vfcmtUuid - VFCMT that the rule editor ui is saved in
+ * @param dcaeCompLabel - the name of the DCAE Component which the rule is applied to
+ * @param nid - A unique id of the DCAE Component which the rule is applied to - exists also in the cdump
+ * @param configParam - the name of the DCAE Component configuration property the rule is linked to
+ * @param ruleUid - the unique id of the rule to delete
+ * @return operation result
+ */
+ @RequestMapping(value = "/rule/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam}/{ruleUid}", method = { RequestMethod.DELETE }, produces = "application/json")
+ public ResponseEntity deleteRule(
+ @RequestHeader("USER_ID") String userId,
+ @PathVariable("vfcmtUuid") String vfcmtUuid,
+ @PathVariable("dcaeCompLabel") String dcaeCompLabel,
+ @PathVariable("nid") String nid,
+ @PathVariable("configParam") String configParam,
+ @PathVariable("ruleUid") String ruleUid,
+ @ModelAttribute("requestId") String requestId){
+
+ try {
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ if (null == vfcmt.getArtifacts()) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "VFCMT {} doesn't have artifacts", vfcmtUuid);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.DELETE_RULE_FAILED);
+ }
+ String artifactLabel = Normalizers.normalizeArtifactLabel(dcaeCompLabel + nid + configParam);
+
+ // check for MappingRules artifact in existing artifacts
+ Artifact mappingRuleFile = vfcmt.getArtifacts().stream()
+ .filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel())))
+ .findAny().orElse(null);
+
+ if (null == mappingRuleFile) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "{} doesn't exist for VFCMT {}", artifactLabel, vfcmtUuid);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.DELETE_RULE_FAILED);
+ }
+
+ String vfcmtId = assertOwnershipOfVfcmtId(userId, vfcmt, requestId);
+ String payload = baseBusinessLogic.getSdcRestClient().getResourceArtifact(vfcmtId, mappingRuleFile.getArtifactUUID(), requestId);
+ MappingRules rules = RulesPayloadUtils.parseMappingRulesArtifactPayload(payload);
+ Rule removedRule = rulesBusinessLogic.deleteRule(rules, ruleUid);
+ if(null == removedRule){
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Rule {} not found.", ruleUid);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.DELETE_RULE_FAILED);
+ }
+ if(rules.isEmpty()){ // if file doesn't contain any rules after last deletion -> let's delete the file
+ baseBusinessLogic.getSdcRestClient().deleteResourceArtifact(userId, vfcmtId, mappingRuleFile.getArtifactUUID(), requestId);
+ } else {
+ updateRulesArtifact(vfcmtId, userId, mappingRuleFile, rules, requestId);
+ }
+ return checkInAndReturnSaveArtifactResult(removedRule, vfcmtId, userId, requestId);
+ } catch (Exception e) {
+ return handleException(e, ApiType.SAVE_RULE_ARTIFACT);
+ }
+
+ }
+
+ /**
+ * This endpoint functions as a 'translate' service for the rule editor UI
+ *
+ * @param vfcmtUuid - VFCMT that the rule editor ui is saved in
+ * @param dcaeCompLabel - the name of the DCAE Component which the rule is applied to
+ * @param nid - A unique id of the DCAE Component which the rule is applied to - exists also in the cdump
+ * @param configParam - the name of the DCAE Component configuration property the rule is linked to
+ * @param flowType - the mapping rules flow type (SNMP,Syslog,FOI)
+ * @return translateJson representing the translated Rules
+ * Validations:
+ * 1. That the user is able to edit the VFCMT
+ * 2. That the cdump holds a dcae component with such nid (to avoid orphan rules)
+ * 3. Check that the fetched VFCMT is actually a VFCMT and not a regular VF
+ * @throws Exception
+ */
+ @RequestMapping(value = "/rule/translate/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam}", method = { RequestMethod.GET }, produces = "application/json")
+ public ResponseEntity translateRules(@PathVariable("vfcmtUuid") String vfcmtUuid, @ModelAttribute("requestId") String requestId,
+ @PathVariable("dcaeCompLabel") String dcaeCompLabel,
+ @PathVariable("nid") String nid,
+ @PathVariable("configParam") String configParam,
+ @RequestParam("flowType") String flowType) throws Exception {
+
+ try {
+
+ if (StringUtils.isBlank(flowType) || MapUtils.isEmpty(compositionConfig.getFlowTypesMap()) || null == compositionConfig.getFlowTypesMap().get(flowType)) {
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.TRANSLATE_FAILED, "", "Flow type " + flowType + " not found");
+ }
+
+ // extract entry phase name and last phase name from configuration:
+ String entryPointPhaseName = compositionConfig.getFlowTypesMap().get(flowType).getEntryPointPhaseName();
+ String lastPhaseName = compositionConfig.getFlowTypesMap().get(flowType).getLastPhaseName();
+
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ checkVfcmtType(vfcmt);
+
+ if (CollectionUtils.isEmpty(vfcmt.getArtifacts())) {
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.TRANSLATE_FAILED, "", "No rules found on VFCMT " + vfcmtUuid);
+ }
+ String artifactLabel = Normalizers.normalizeArtifactLabel(dcaeCompLabel + nid + configParam);
+
+ // check for MappingRules artifact in existing artifacts
+ Artifact rulesArtifact = vfcmt.getArtifacts().stream().filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel()))).findAny().orElse(null);
+
+ if (rulesArtifact == null) {
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.TRANSLATE_FAILED, "", artifactLabel + " doesn't exist on VFCMT " + vfcmtUuid);
+ }
+
+ String payload = baseBusinessLogic.getSdcRestClient().getResourceArtifact(vfcmtUuid, rulesArtifact.getArtifactUUID(), requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Retrieved mapping rules artifact {}, start parsing rules...", artifactLabel);
+ MappingRules rules = RulesPayloadUtils.parseMappingRulesArtifactPayload(payload);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Finished parsing rules, calling validator...");
+ List<ServiceException> errors = rulesBusinessLogic.validateRules(rules);
+ if (!errors.isEmpty()) {
+ return ErrConfMgr.INSTANCE.buildErrorArrayResponse(errors);
+ }
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Validation completed successfully, calling translator...");
+ String translateJson = rulesBusinessLogic.translateRules(rules, entryPointPhaseName, lastPhaseName, vfcmt.getName());
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Translation completed successfully");
+ return new ResponseEntity<>(translateJson, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.SAVE_RULE_ARTIFACT);
+ }
+ }
+
+
+ ///////////////////PRIVATE METHODS////////////////////////////////////////////////////////////////////////
+
+ private String assertOwnershipOfVfcmtId(String userId, ResourceDetailed vfcmt, String requestId) throws Exception {
+ checkUserIfResourceCheckedOut(userId, vfcmt);
+ String newVfcmtId = vfcmt.getUuid(); // may change after checking out a certified vfcmt
+ if (isNeedToCheckOut(vfcmt.getLifecycleState())) {
+ Asset result = checkout(userId, newVfcmtId, AssetType.RESOURCE, requestId);
+ if (result != null) {
+ newVfcmtId = result.getUuid();
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New resource after checkout is: {}", newVfcmtId);
+ }
+ }
+ return newVfcmtId;
+ }
+
+
+
+ // called after validating vfcmt.getArtifacts() is not null
+ private boolean cdumpContainsNid(ResourceDetailed vfcmt, String nid, String requestId) {
+ Artifact cdump = vfcmt.getArtifacts().stream()
+ .filter(a -> DcaeBeConstants.Composition.fileNames.COMPOSITION_YML.equalsIgnoreCase(a.getArtifactName()))
+ .findAny().orElse(null);
+ if (null == cdump || null == cdump.getArtifactUUID()) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "No {} found on vfcmt {}", DcaeBeConstants.Composition.fileNames.COMPOSITION_YML, vfcmt.getUuid());
+ return false;
+ }
+ try {
+ String artifact = baseBusinessLogic.getSdcRestClient().getResourceArtifact(vfcmt.getUuid(), cdump.getArtifactUUID(), requestId);
+ if (!artifact.contains("\"nid\":\""+nid)) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "{} doesn't contain nid {}. Cannot save mapping rule file", DcaeBeConstants.Composition.fileNames.COMPOSITION_YML, nid);
+ return false;
+ }
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), EXCEPTION, e);
+ return false;
+ }
+ return true;
+ }
+
+ private ResponseEntity<String> saveNewRulesArtifact(Rule rule, String vfcmtUuid, String artifactFileName, String artifactLabel, String userId, String requestId) throws Exception {
+ MappingRules body = new MappingRules(rule);
+ Artifact artifact = SdcRestClientUtils.generateDeploymentArtifact(body.describe(), artifactFileName, ArtifactType.OTHER.name(), artifactLabel, body.convertToPayload());
+ baseBusinessLogic.getSdcRestClient().createResourceArtifact(userId, vfcmtUuid, artifact, requestId);
+ return checkInAndReturnSaveArtifactResult(rule, vfcmtUuid, userId, requestId);
+ }
+
+ private ResponseEntity addOrEditRuleInArtifact(Rule rule, String vfcmtUuid, String userId, Artifact rulesArtifact, String requestId) throws Exception {
+ String payload = baseBusinessLogic.getSdcRestClient().getResourceArtifact(vfcmtUuid, rulesArtifact.getArtifactUUID(), requestId);
+ MappingRules rules = RulesPayloadUtils.parseMappingRulesArtifactPayload(payload);
+
+ // in case the rule id is passed but the rule doesn't exist on the mapping rule file:
+ if(!rulesBusinessLogic.addOrEditRule(rules, rule)) {
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SAVE_RULE_FAILED);
+ }
+ updateRulesArtifact(vfcmtUuid, userId, rulesArtifact, rules, requestId);
+ return checkInAndReturnSaveArtifactResult(rule, vfcmtUuid, userId, requestId);
+ }
+
+ // regardless of check in result, return save artifact success
+ private ResponseEntity<String> checkInAndReturnSaveArtifactResult(Rule rule, String vfcmtUuid, String userId, String requestId) {
+ try {
+ checkin(userId, vfcmtUuid, AssetType.RESOURCE, requestId);
+ } catch (Exception e) {
+ // swallowing the exception intentionally since it is on the check in action
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error occurred while performing check in on VFCMT {}:{}", vfcmtUuid, e);
+ }
+ return new ResponseEntity<>(rule.toJson(), HttpStatus.OK);
+ }
+
+ private void updateRulesArtifact(String vfcmtUuid, String userId, Artifact artifactInfo, MappingRules rules, String requestId) throws Exception {
+ artifactInfo.setPayloadData(Base64Utils.encodeToString(rules.convertToPayload()));
+ // POST must contain 'description' while GET returns 'artifactDescription'
+ artifactInfo.setDescription(artifactInfo.getArtifactDescription());
+ baseBusinessLogic.getSdcRestClient().updateResourceArtifact(userId, vfcmtUuid, artifactInfo, requestId);
+ }
+
+
+ /**
+ * @param eventMapStream
+ * @param parent
+ * @param path
+ * @return
+ */
+ private List<EventTypeDefinitionUI> convertToEventTypeDefinition(Stream<Entry<String, VesDataTypeDefinition>> eventMapStream, VesDataTypeDefinition parent, String path) {
+
+ return eventMapStream.map(entry -> {
+ Map<String, VesDataTypeDefinition> properties = entry.getValue().getProperties();
+ VesDataItemsDefinition items = entry.getValue().getItems();
+ String newPath = path + "." + entry.getKey();
+ List<EventTypeDefinitionUI> children = (properties == null) ? null : convertToEventTypeDefinition(properties.entrySet().stream(), entry.getValue(), newPath);
+ if(VesSimpleTypesEnum.ARRAY.getType().equals(entry.getValue().getType())) {
+ newPath += "[]";
+ if(innerTypeIsComplex(items)) {
+ children = convertComplexArrayType(items, newPath);
+ } else if(innerTypeIsArray(items)) {
+ newPath += "[]";
+ }
+ }
+
+ boolean isRequired = (parent != null) ? parent.getRequired().contains(entry.getKey()) : false;
+ return new EventTypeDefinitionUI(entry.getKey(), children, isRequired, newPath);
+ }).collect(Collectors.toList());
+ }
+
+ private boolean innerTypeIsComplex(VesDataItemsDefinition items){
+ return items != null && items.stream().anyMatch(p -> p.getProperties() != null);
+ }
+
+ private boolean innerTypeIsArray(VesDataItemsDefinition items){
+ return items != null && items.stream().anyMatch(p -> p.getItems() != null);
+ }
+
+ private List<EventTypeDefinitionUI> convertComplexArrayType(VesDataItemsDefinition items, String path){
+ return items.stream().map(item -> item.getProperties() != null ? convertToEventTypeDefinition(item.getProperties().entrySet().stream(), item, path) : new ArrayList<EventTypeDefinitionUI>())
+ .flatMap(List::stream).collect(Collectors.toList());
+ }
+
+
+ private String generateMappingRulesFileName(String dcaeCompLabel, String nid, String configParam) {
+ return dcaeCompLabel + "_" + nid + "_" + configParam + DcaeBeConstants.Composition.fileNames.MAPPING_RULE_POSTFIX;
+ }
+
+ private List<EventTypeDefinitionUI> getEventTypeDefinitionUIs(String version, String eventType) {
+ List<String> eventNamesToReturn = ListUtils.union(EventTypesByVersionUI.DEFAULT_EVENTS, Arrays.asList(eventType));
+ Map<String, VesDataTypeDefinition> eventDefs = VesStructureLoader.getEventListenerDefinitionByVersion(version);
+ Stream<Entry<String, VesDataTypeDefinition>> filteredEvents = eventDefs.entrySet().stream().filter(entry -> eventNamesToReturn.contains(entry.getKey()));
+
+ return convertToEventTypeDefinition(filteredEvents, null, "event");
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ServicesController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ServicesController.java
new file mode 100644
index 0000000..257d1a9
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ServicesController.java
@@ -0,0 +1,230 @@
+package org.onap.sdc.dcae.composition.controller;
+
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.AttachVFCMTServiceRequest;
+import org.onap.sdc.dcae.composition.restmodels.DcaeMinimizedService;
+import org.onap.sdc.dcae.composition.restmodels.MessageResponse;
+import org.onap.sdc.dcae.composition.restmodels.sdc.*;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants.LifecycleStateEnum;
+import org.onap.sdc.dcae.enums.ArtifactType;
+import org.onap.sdc.dcae.enums.LifecycleOperationType;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.DcaeException;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.onap.sdc.dcae.utils.SdcRestClientUtils;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@EnableAutoConfiguration
+@CrossOrigin
+public class ServicesController extends BaseController {
+
+ /***
+ * GET services list by VFCMT
+ * @param userId
+ * @param vfcmtUuid
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = { "/services/{vfcmtUuid}" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity services(@RequestHeader("USER_ID") String userId, @PathVariable String vfcmtUuid, @ModelAttribute("requestId") String requestId) {
+ try {
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "GET ({}) Vfcmt form SDC: {}", vfcmtUuid, vfcmt);
+ checkVfcmtType(vfcmt);
+ checkUserIfResourceCheckedOut(userId, vfcmt);
+
+ List<Service> services = baseBusinessLogic.getSdcRestClient().getServices(requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "GET services data from SDC: {}", services);
+ List<Service> uuids = filterServicesByUser(services, userId);
+ return new ResponseEntity<>(uuids, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ErrConfMgr.ApiType.GET_SERVICE);
+ }
+ }
+
+ /***
+ * GET a single service
+ * @param theServiceId
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = { "/service/{theServiceId}" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity service(@PathVariable String theServiceId, @ModelAttribute("requestId") String requestId) {
+ try {
+ ServiceDetailed service = baseBusinessLogic.getSdcRestClient().getService(theServiceId, requestId);
+ if (service != null) {
+ if(service.getResources()!=null){
+ List<ResourceInstance> vfResourcesOnly = service.getResources().stream().filter(vfi -> vfi.getResoucreType().equals("VF")).collect(Collectors.toList());
+ service.setResources(vfResourcesOnly);
+ }else{
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Service {} doesn't have any resources (e.g VFi's)", theServiceId);
+ }
+ } else {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Couldn't fetch service with uuid {} from SDC", theServiceId);
+ }
+ return new ResponseEntity<>(service, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ErrConfMgr.ApiType.GET_SERVICE);
+ }
+ }
+
+
+ /***
+ * Attach service and service instance to VFCMT
+ * @param userId
+ * @param request
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = "/{vfcmtUuid}/attachment", method = RequestMethod.POST, produces = {"application/json" })
+ public ResponseEntity attachService(
+ @PathVariable("vfcmtUuid") String vfcmtUuid,
+ @RequestHeader("USER_ID") String userId,
+ @RequestBody AttachVFCMTServiceRequest request,
+ @ModelAttribute("requestId") String requestId) {
+
+ String serviceUuid = request.getServiceUuid();
+ String vfiName = request.getInstanceName();
+ String resourceUuid = vfcmtUuid;
+ MessageResponse response = new MessageResponse();
+
+ try {
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), vfcmt.toString());
+
+ checkVfcmtType(vfcmt);
+ verifyVfiExists(serviceUuid, vfiName, requestId);
+
+ boolean isUpdateMode = false;
+ Artifact artifactObj = null;
+
+ String reference = serviceUuid + "/resources/" + vfiName;
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "*****************************************");
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Reference between service and vfi {}", reference);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "*****************************************");
+
+ if(!CollectionUtils.isEmpty(vfcmt.getArtifacts())){
+ artifactObj = vfcmt.getArtifacts().stream().filter(a -> DcaeBeConstants.Composition.fileNames.SVC_REF.equals(a.getArtifactName())).findAny().orElse(null);
+ isUpdateMode = null != artifactObj;
+ }
+
+ if (isNeedToCheckOut(vfcmt.getLifecycleState())) {
+ vfcmt = baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, vfcmtUuid, LifecycleOperationType.CHECKOUT.name(), null, requestId);
+ if (vfcmt != null) {
+ resourceUuid = vfcmt.getUuid();
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New vfcmt uuid after checkout is: {}", resourceUuid);
+ }
+ }
+
+ if(isUpdateMode){
+ updateReferenceArtifact(userId, resourceUuid, artifactObj, reference, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Artifact {} updated with content: {}", reference, DcaeBeConstants.Composition.fileNames.SVC_REF, reference);
+ }else{
+ Artifact artifact = SdcRestClientUtils.generateDeploymentArtifact("createReferenceArtifact", DcaeBeConstants.Composition.fileNames.SVC_REF, ArtifactType.DCAE_TOSCA.name(), "servicereference", reference.getBytes());
+ baseBusinessLogic.getSdcRestClient().createResourceArtifact(userId, resourceUuid, artifact, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Artifact {} created with content: {}", DcaeBeConstants.Composition.fileNames.SVC_REF, reference);
+ }
+ checkin(userId, resourceUuid, org.onap.sdc.dcae.enums.AssetType.RESOURCE, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Attachment of reference={} in VFCMT {} has finished successfully", reference, resourceUuid);
+
+ response.setSuccessResponse("Artifact updated");
+ return new ResponseEntity<>(response, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ErrConfMgr.ApiType.ATTACH_TO_SERVICE);
+ }
+ }
+
+ @RequestMapping(value = { "/{vfcmtUuid}/attachment" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity getAttachedService(@PathVariable("vfcmtUuid") String vfcmtUuid, @ModelAttribute("requestId") String requestId) {
+
+ MessageResponse response = new MessageResponse();
+
+ try {
+ ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), vfcmt.toString());
+ checkVfcmtType(vfcmt);
+ String artifact = "No Artifacts";
+
+ if (!CollectionUtils.isEmpty(vfcmt.getArtifacts())) {
+ Artifact artifactObj = vfcmt.getArtifacts().stream().filter(a -> DcaeBeConstants.Composition.fileNames.SVC_REF.equals(a.getArtifactName())).findAny().orElse(null);
+ if (null != artifactObj)
+ artifact = baseBusinessLogic.getSdcRestClient().getResourceArtifact(vfcmtUuid, artifactObj.getArtifactUUID(), requestId);
+ }
+ response.setSuccessResponse(artifact);
+ return new ResponseEntity<>(response, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ErrConfMgr.ApiType.GET_VFCMT);
+ }
+ }
+
+ /**** PRIVATE METHODS ****/
+
+ private void updateReferenceArtifact(String userId, String VFCMTUuid, Artifact artifactObj, String reference, String requestId) throws Exception {
+ artifactObj.setDescription("updateReferenceArtifact");
+ artifactObj.setPayloadData(Base64Utils.encodeToString(reference.getBytes()));
+ baseBusinessLogic.getSdcRestClient().updateResourceArtifact(userId, VFCMTUuid, artifactObj, requestId);
+ }
+
+
+ /**
+ *
+ * @param lastUpdaterUserId
+ * @param services
+ * @param userId
+ * @return
+ */
+
+ //TODO move method to ci tests
+ public List<DcaeMinimizedService> parseAndFilterServicesByUser(String lastUpdaterUserId, List<LinkedHashMap<String, String>> services, String userId) {
+ List<DcaeMinimizedService> uuids = null;
+ if (services != null) {
+ //services.stream().filter(predicate)
+ uuids = services.stream()
+ .map(x -> new DcaeMinimizedService(x.get("uuid"), x.get("name"), x.get("lastUpdaterUserId"), x.get("lifecycleState"), x.get("version"), x.get("invariantUUID")))
+ .collect(Collectors.groupingBy(DcaeMinimizedService::getInvariantUUID)).values().stream()
+ .map(p -> p.stream()
+ .sorted(Comparator.comparing(DcaeMinimizedService::getVersionAsFloat).reversed())).map(p -> p.collect(Collectors.toList())).map(p -> p.get(0))
+ .filter(x -> (!(!x.getLastUpdaterUserId().equals(userId) && x.getLifeCycleState().equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name()))))
+ .sorted(Comparator.comparing(DcaeMinimizedService::getName)).collect(Collectors.toList());
+ }
+ return uuids;
+ }
+
+ private List<Service> filterServicesByUser(List<Service> services, String userId) {
+ return CollectionUtils.isEmpty(services) ? new ArrayList<>() : services.stream()
+ .collect(Collectors.groupingBy(Service::getInvariantUUID)).values().stream()
+ .map(p -> p.stream()
+ .sorted(Comparator.comparing(Service::versionAsFloat).reversed())).map(p -> p.collect(Collectors.toList())).map(p -> p.get(0))
+ .filter(x -> (!(!x.getLastUpdaterUserId().equals(userId) && x.getLifecycleState().equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name()))))
+ .sorted(Comparator.comparing(Service::getName)).collect(Collectors.toList());
+ }
+
+ /**
+ *
+ * @param serviceUuid
+ * @param vfiName
+ * @param requestId
+ * @throws Exception
+ */
+ private void verifyVfiExists(String serviceUuid, String vfiName, String requestId) throws Exception {
+ ServiceDetailed service = baseBusinessLogic.getSdcRestClient().getService(serviceUuid, requestId);
+ boolean isServiceContainsVfi = null != service && !CollectionUtils.isEmpty(service.getResources()) && service.getResources().stream()
+ .filter(vfi -> "VF".equals(vfi.getResoucreType()))
+ .anyMatch(vfi -> vfiName.equals(vfi.getResourceInstanceName()));
+ if (!isServiceContainsVfi) {
+ ResponseFormat responseFormat = ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.VFI_FETCH_ERROR, null, serviceUuid, vfiName);
+ throw new DcaeException(HttpStatus.NOT_FOUND, responseFormat.getRequestError());
+ }
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/VfcmtController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/VfcmtController.java
new file mode 100644
index 0000000..0e1b209
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/VfcmtController.java
@@ -0,0 +1,183 @@
+package org.onap.sdc.dcae.composition.controller;
+
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.impl.ReferenceBusinessLogic;
+import org.onap.sdc.dcae.composition.impl.VfcmtBusinessLogic;
+import org.onap.sdc.dcae.composition.restmodels.CreateVFCMTRequest;
+import org.onap.sdc.dcae.composition.restmodels.ImportVFCMTRequest;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ExternalReferencesMap;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Resource;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
+import org.onap.sdc.dcae.errormng.ErrConfMgr.ApiType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@EnableAutoConfiguration
+@CrossOrigin
+public class VfcmtController extends BaseController{
+
+
+ @Autowired
+ private VfcmtBusinessLogic vfcmtBusinessLogic;
+ @Autowired
+ private ReferenceBusinessLogic referenceBusinessLogic;
+
+ private static final String VFCMT = "VFCMT";
+ private static final String TEMPLATE = "Template";
+ private static final String BASE_MONITORING_TEMPLATE = "Base Monitoring Template";
+
+
+
+ /***
+ * Get one resource information
+ * @param theResourceId retrieved resource id
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = { "/resource/{theResourceId}" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity resource(@PathVariable String theResourceId, @ModelAttribute("requestId") String requestId) {
+ try {
+ ResourceDetailed resource = baseBusinessLogic.getSdcRestClient().getResource(theResourceId, requestId);
+ return new ResponseEntity<>(resource, HttpStatus.OK);
+ }catch (Exception e) {
+ return handleException(e, ApiType.GET_VFCMT);
+ }
+ }
+
+ /***
+ * Get All resources
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = { "/getResourcesByCategory" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity getResourcesByCategory(@ModelAttribute("requestId") String requestId) {
+ try {
+ List<Resource> resources = baseBusinessLogic.getSdcRestClient().getResources(VFCMT, null, null, requestId);
+ return new ResponseEntity<>(resources, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.GET_ALL_VFCMTS);
+ }
+ }
+
+ /***
+ * Get All resources by Service
+ * @return ResponseEntity
+ */
+
+ @RequestMapping(value = { "/{contextType}/{uuid}/{version}/getVfcmtsForMigration" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity getVfcmtsForMigration(@RequestHeader("USER_ID") String userId,
+ @PathVariable String contextType,
+ @PathVariable String uuid,
+ @PathVariable String version,
+ @ModelAttribute("requestId") String requestId){
+
+ return vfcmtBusinessLogic.getVfcmtsForMigration(userId, contextType, uuid, version, requestId);
+ }
+
+ /***
+ * Get All resources by Monitoring Template Category
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = { "/getResourcesByMonitoringTemplateCategory" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity getResourcesByMonitoringTemplateCategory(@ModelAttribute("requestId") String requestId) {
+ try {
+ List<Resource> resources = baseBusinessLogic.getSdcRestClient().getResources(VFCMT, TEMPLATE, BASE_MONITORING_TEMPLATE, requestId);
+ return new ResponseEntity<>(resources, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.GET_ALL_VFCMTS);
+ }
+ }
+
+ /***
+ * Create new Vfcmt
+ * @param userId retrieved user ID
+ * @param request retrieved request
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = "/createVFCMT", method = RequestMethod.POST, produces = {"application/json" })
+ public ResponseEntity createVFCMT(@RequestHeader("USER_ID") String userId, @RequestBody CreateVFCMTRequest request, @ModelAttribute("requestId") String requestId) {
+ vfcmtBusinessLogic.addSdcMandatoryFields(request, userId);
+ try {
+ ResourceDetailed response = baseBusinessLogic.getSdcRestClient().createResource(userId, request, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "createVFCMT after post: {}", response);
+ return new ResponseEntity<>(response, HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.CREATE_NEW_VFCMT);
+ }
+ }
+
+ /***
+ * Create new Vfcmt from general screen
+ * @param userId retrieved user ID
+ * @param request retrieved request
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = "/createMC", method = RequestMethod.POST, produces = {"application/json" })
+ public ResponseEntity createMC(@RequestHeader("USER_ID") String userId, @RequestBody CreateVFCMTRequest request, @ModelAttribute("requestId") String requestId) {
+ return vfcmtBusinessLogic.createMcFromTemplate(userId, request, requestId);
+ }
+
+
+ /***
+ * Clone or import existing VFCMT and attach to selected service/resource
+ * @param userId
+ * @param request
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = "/importMC", method = RequestMethod.POST, produces = {"application/json" })
+ public ResponseEntity importMC(@RequestHeader("USER_ID") String userId, @RequestBody ImportVFCMTRequest request, @ModelAttribute("requestId") String requestId) {
+ return vfcmtBusinessLogic.importMC(userId, request, requestId);
+ }
+
+ /***
+ * GET a list of Monitoring Components of a service by uuid and version
+ * @param context the context type of this request
+ * @param uuid the uuid of the type requested
+ * @param version the version of the entity requested
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = { "/{context}/{uuid}/{version}/monitoringComponents" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity getMonitoringComponents(@PathVariable String context, @PathVariable String uuid, @PathVariable String version, @ModelAttribute("requestId") String requestId) {
+ try {
+ ExternalReferencesMap mcRefs = baseBusinessLogic.getSdcRestClient().getMonitoringReferences(context, uuid, version, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Got monitoring references map from SDC: {}", mcRefs.values());
+ return new ResponseEntity<>(referenceBusinessLogic.fetchMonitoringComponents(mcRefs, requestId), HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.GET_SERVICE);
+ }
+ }
+
+ @RequestMapping(value = { "/{context}/{serviceUuid}/{vfiName}/{vfcmtUuid}/deleteVfcmtReference" }, method = { RequestMethod.DELETE }, produces = {"application/json" })
+ public ResponseEntity deleteVfcmtReference(@RequestHeader("USER_ID") String userId, @PathVariable String context, @PathVariable String serviceUuid, @PathVariable String vfiName, @PathVariable String vfcmtUuid, @ModelAttribute String requestId) {
+ try {
+ referenceBusinessLogic.deleteVfcmtReference(userId, context, serviceUuid, vfiName, vfcmtUuid, requestId);
+ return new ResponseEntity<>(HttpStatus.OK);
+ } catch (Exception e) {
+ return handleException(e, ApiType.DELETE_VFCMT_REFERENCE);
+ }
+ }
+
+ @RequestMapping(value = { "/{context}/{monitoringComponentName}/{serviceUuid}/{vfiName}/{vfcmtUuid}/deleteVfcmtReference" }, method = { RequestMethod.DELETE }, produces = {"application/json" })
+ public ResponseEntity deleteVfcmtReferenceWithBlueprint(@RequestHeader("USER_ID") String userId, @PathVariable String context, @PathVariable String monitoringComponentName, @PathVariable String serviceUuid, @PathVariable String vfiName, @PathVariable String vfcmtUuid, @ModelAttribute String requestId) {
+ try {
+ referenceBusinessLogic.deleteVfcmtReference(userId, context, serviceUuid, vfiName, vfcmtUuid, requestId);
+ } catch (Exception e) {
+ return handleException(e, ApiType.DELETE_VFCMT_REFERENCE);
+ }
+ return referenceBusinessLogic.deleteVfcmtReferenceBlueprint(userId, context, monitoringComponentName, serviceUuid, vfiName, vfcmtUuid, requestId);
+ }
+
+ @RequestMapping(value = { "/getVfcmtReferenceData/{vfcmtUuid}" }, method = { RequestMethod.GET }, produces = {"application/json" })
+ public ResponseEntity getVfcmtReferenceData(@PathVariable String vfcmtUuid, @ModelAttribute String requestId) {
+ try {
+ return vfcmtBusinessLogic.getVfcmtReferenceData(vfcmtUuid, requestId);
+ } catch (Exception e) {
+ return handleException(e, ApiType.GET_VFCMT);
+ }
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/HealthController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/HealthController.java
new file mode 100644
index 0000000..eaad1b0
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/HealthController.java
@@ -0,0 +1,77 @@
+package org.onap.sdc.dcae.composition.controller.health;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.health.ComponentsInfo;
+import org.onap.sdc.dcae.composition.restmodels.health.HealthResponse;
+import org.onap.sdc.dcae.composition.CompositionEngine;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.google.gson.Gson;
+
+@RestController
+@EnableAutoConfiguration
+@CrossOrigin
+public class HealthController {
+ private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+ Gson gson = new Gson();
+
+ @Autowired
+ ToscaLabHealthState toscaLabHealthState;
+
+ @RequestMapping(value = "/healthCheck", method = RequestMethod.GET)
+ public ResponseEntity<String> healthCheck() {
+ HttpStatus httpSts = HttpStatus.OK;
+ try{
+ HealthResponse healthResponse = new HealthResponse();
+ healthResponse.setHealthCheckComponent(DcaeBeConstants.Health.APP_NAME);
+ healthResponse.setHealthCheckStatus(DcaeBeConstants.Health.UP);
+ healthResponse.setSdcVersion(CompositionEngine.getDcaeVersion());
+ healthResponse.setDescription(DcaeBeConstants.Health.OK);
+
+ List<ComponentsInfo> componentsInfoList = new ArrayList<ComponentsInfo>();
+ ComponentsInfo componentsInfo = new ComponentsInfo();
+ componentsInfo.setHealthCheckComponent(DcaeBeConstants.Health.BE);
+ componentsInfo.setHealthCheckStatus(DcaeBeConstants.Health.UP);
+ componentsInfo.setVersion(CompositionEngine.getDcaeVersion());
+ componentsInfo.setDescription(DcaeBeConstants.Health.OK);
+ componentsInfoList.add(componentsInfo);
+
+ ComponentsInfo toscaLab = new ComponentsInfo();
+ ComponentsInfo toscaLabHealthRes = toscaLabHealthState.getToscaLabHealthResponse();
+ if(toscaLabHealthRes.getHealthCheckStatus().equals(DcaeBeConstants.Health.DOWN)){
+ healthResponse.setHealthCheckStatus(DcaeBeConstants.Health.DOWN);
+ healthResponse.setDescription(toscaLabHealthRes.getHealthCheckComponent()+" is down");
+ httpSts = HttpStatus.INTERNAL_SERVER_ERROR;
+ }
+ toscaLab.setHealthCheckComponent(toscaLabHealthRes.getHealthCheckComponent());
+ toscaLab.setHealthCheckStatus(toscaLabHealthRes.getHealthCheckStatus());
+ toscaLab.setVersion(toscaLabHealthRes.getVersion());
+ toscaLab.setDescription(toscaLabHealthRes.getDescription());
+ componentsInfoList.add(toscaLab);
+
+ healthResponse.setComponentsInfo(componentsInfoList);
+ String json = gson.toJson(healthResponse, HealthResponse.class);
+
+ return new ResponseEntity<String>(json, httpSts);
+ }
+ catch(Exception e){
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error occured while performing HealthCheck: {}", e.getLocalizedMessage());
+ return new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/HealthPoller.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/HealthPoller.java
new file mode 100644
index 0000000..609480d
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/HealthPoller.java
@@ -0,0 +1,97 @@
+package org.onap.sdc.dcae.composition.controller.health;
+
+import java.net.URI;
+import java.util.Collections;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.health.ComponentsInfo;
+import org.onap.sdc.dcae.catalog.commons.Future;
+import org.onap.sdc.dcae.catalog.commons.Http;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import com.google.gson.Gson;
+
+@Configuration
+@EnableAsync
+@EnableScheduling
+@ConfigurationProperties(prefix="blueprinter")
+public class HealthPoller {
+ private URI hcuri;
+ private String hcretrynum;
+ private Gson gson;
+
+ private OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ @Autowired
+ private ToscaLabHealthState toscaLabHealthState;
+
+ public HealthPoller() {
+ super();
+ gson = new Gson();
+ }
+
+ @Scheduled(fixedDelayString="${healthpoller.fixedDelay}")
+ public void pollToscaLabHealth() {
+ ComponentsInfo toscaLabHealthRes = null;
+ ResponseEntity<String> healthRes = null;
+ try {
+ for(int i=0; i<Integer.valueOf(hcretrynum); i++){ // 3 tries
+ healthRes = sendHealthCheck();
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Try #{}: {}", i, healthRes);
+ if(healthRes.getStatusCode()==HttpStatus.OK){
+ String result = (String) healthRes.getBody();
+ toscaLabHealthRes = gson.fromJson(result, ComponentsInfo.class);
+ break;
+ }
+ }
+ } catch (Exception e) {
+ toscaLabHealthRes = getNegativeHealth(e.getMessage());
+ }
+ if(toscaLabHealthRes == null){
+ toscaLabHealthRes = getNegativeHealth(healthRes.getBody() + "-" + healthRes.getStatusCode());
+ }
+ toscaLabHealthState.setToscaLabHealthResponse(toscaLabHealthRes);
+ }
+
+ private ComponentsInfo getNegativeHealth(String msg) {
+ ComponentsInfo toscaLabHealthRes = new ComponentsInfo();
+ String description = "DCAE-D BE failed while trying to fetch Tosca_Lab healthcheck. Exception: " +msg;
+ toscaLabHealthRes.setDescription(description);
+ toscaLabHealthRes.setHealthCheckComponent(DcaeBeConstants.Health.TOSCA_LAB);
+ toscaLabHealthRes.setHealthCheckStatus(DcaeBeConstants.Health.DOWN);
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), description);
+ return toscaLabHealthRes;
+ }
+
+ public ResponseEntity<String> sendHealthCheck() {
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
+ HttpEntity<String> entity = new HttpEntity<String>(headers);
+ return Http.exchangeSync(hcuri.toString(), HttpMethod.GET, entity, String.class, 5000);
+ }
+
+ public void setHcuri(URI hcuri) {
+ this.hcuri = hcuri;
+ }
+
+ public void setHcretrynum(String hcretrynum) {
+ this.hcretrynum = hcretrynum;
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/ToscaLabHealthState.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/ToscaLabHealthState.java
new file mode 100644
index 0000000..6fe469f
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/health/ToscaLabHealthState.java
@@ -0,0 +1,29 @@
+package org.onap.sdc.dcae.composition.controller.health;
+
+import org.onap.sdc.dcae.composition.restmodels.health.ComponentsInfo;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Scope(value = "singleton")
+@Component
+public class ToscaLabHealthState {
+ private ComponentsInfo toscaLabHealthResponse;
+
+ public ToscaLabHealthState() {
+ super();
+ toscaLabHealthResponse = new ComponentsInfo();
+ toscaLabHealthResponse.setDescription("Not up yet");
+ toscaLabHealthResponse.setHealthCheckComponent(DcaeBeConstants.Health.TOSCA_LAB);
+ toscaLabHealthResponse.setHealthCheckStatus(DcaeBeConstants.Health.DOWN);
+ }
+
+ public ComponentsInfo getToscaLabHealthResponse() {
+ return toscaLabHealthResponse;
+ }
+
+ public void setToscaLabHealthResponse(ComponentsInfo toscaLabHealthResponse) {
+ this.toscaLabHealthResponse = toscaLabHealthResponse;
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/swagger/SwaggerConfig.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/swagger/SwaggerConfig.java
new file mode 100644
index 0000000..48c7153
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/swagger/SwaggerConfig.java
@@ -0,0 +1,23 @@
+package org.onap.sdc.dcae.composition.controller.swagger;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+ @Bean
+ public Docket productApi() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("org.onap.sdc.dcae.composition.controller"))
+ .paths(PathSelectors.regex("/*.*"))
+ .build();
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BaseBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BaseBusinessLogic.java
new file mode 100644
index 0000000..f26c885
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BaseBusinessLogic.java
@@ -0,0 +1,49 @@
+package org.onap.sdc.dcae.composition.impl;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.dcae.client.ISdcClient;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
+import org.onap.sdc.dcae.utils.SdcRestClientUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.CollectionUtils;
+
+@Component
+public class BaseBusinessLogic {
+ @Autowired
+ protected ISdcClient sdcRestClient;
+
+ protected static OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ protected static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ public ISdcClient getSdcRestClient() {
+ return sdcRestClient;
+ }
+
+ void setSdcRestClient(ISdcClient sdcRestClient) {
+ this.sdcRestClient = sdcRestClient;
+ }
+
+ Artifact cloneArtifactToTarget(String userId, String targetId, String payload, Artifact artifactToClone, String requestId) throws Exception {
+ Artifact cloned = SdcRestClientUtils.generateDeploymentArtifact(artifactToClone.getArtifactDescription(), artifactToClone.getArtifactName(), artifactToClone.getArtifactType(), artifactToClone.getArtifactLabel(), payload.getBytes());
+ return sdcRestClient.createResourceArtifact(userId, targetId, cloned, requestId);
+ }
+
+ public void cloneArtifactToTarget(String userId, String targetId, String payload, Artifact artifactToClone, Artifact artifactToOverride, String requestId) throws Exception{
+ if (null != artifactToOverride) {
+ artifactToOverride.setDescription(artifactToOverride.getArtifactDescription());
+ artifactToOverride.setPayloadData(Base64Utils.encodeToString(payload.getBytes()));
+ sdcRestClient.updateResourceArtifact(userId, targetId, artifactToOverride, requestId);
+ } else {
+ cloneArtifactToTarget(userId, targetId, payload, artifactToClone, requestId);
+ }
+ }
+
+ Artifact findArtifactDataByArtifactName(ResourceDetailed vfcmt, String artifactName) {
+ return null == vfcmt ? null : CollectionUtils.isEmpty(vfcmt.getArtifacts()) ? null : vfcmt.getArtifacts().stream()
+ .filter(p -> artifactName.equals(p.getArtifactName())).findAny().orElse(null);
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/ReferenceBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/ReferenceBusinessLogic.java
new file mode 100644
index 0000000..d229b67
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/ReferenceBusinessLogic.java
@@ -0,0 +1,74 @@
+package org.onap.sdc.dcae.composition.impl;
+
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.MonitoringComponent;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ExternalReferencesMap;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceInstance;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ServiceDetailed;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.utils.Normalizers;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+
+import static org.springframework.util.CollectionUtils.isEmpty;
+
+@Component
+public class ReferenceBusinessLogic extends BaseBusinessLogic {
+
+ public ResponseEntity deleteVfcmtReferenceBlueprint(String userId, String context, String monitoringComponentName, String serviceUuid, String vfiName, String vfcmtUuid, String requestId) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Going to delete blueprint, monitoringComponentName = {}, vfiName = {}", monitoringComponentName, vfiName);
+ try {
+ String normalizedVfiName = Normalizers.normalizeComponentInstanceName(vfiName);
+ ServiceDetailed serviceDetailed = sdcRestClient.getService(serviceUuid, requestId);
+ Optional<ResourceInstance> resourceInstance = serviceDetailed.getResources().stream().filter(item -> item.getResourceInstanceName().equalsIgnoreCase(vfiName)).findAny();
+ if (resourceInstance.isPresent() && resourceInstance.get().getArtifacts() != null) {
+ Optional<Artifact> artifact = resourceInstance.get().getArtifacts().stream().filter(item -> item.getArtifactName().contains(monitoringComponentName)).findAny();
+ artifact.ifPresent(artifact1 -> sdcRestClient.deleteInstanceResourceArtifact(userId, context, serviceUuid, normalizedVfiName, artifact1.getArtifactUUID(), requestId));
+ }
+ } catch (Exception e) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"Failed to delete blueprint with serviceUuid {}, vfcmtUuid . message: {} ", serviceUuid, vfcmtUuid, e);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.DELETE_BLUEPRINT_FAILED);
+ }
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+ public void deleteVfcmtReference(String userId, String context, String serviceUuid, String vfiName, String vfcmtUuid, String requestId) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Going to delete vfcmt reference, vfiName = {}", vfiName);
+ String normalizedVfiName = Normalizers.normalizeComponentInstanceName(vfiName);
+ sdcRestClient.deleteExternalMonitoringReference(userId, context, serviceUuid, normalizedVfiName, vfcmtUuid, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Finished to delete vfcmt reference. serviceUuid {}, vfcmtUuid {}", serviceUuid, vfcmtUuid);
+ }
+
+ // 1806 US381853 Return a list of monitoring components by external reference id. Support partial success
+ public Map<String, List<MonitoringComponent>> fetchMonitoringComponents(ExternalReferencesMap mcRefs, String requestId) {
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Going to fetch monitoring components metadata for vfis {}", mcRefs.keySet());
+ Map<String, List<MonitoringComponent>> result = new LinkedHashMap<>();
+ List<MonitoringComponent> monitoringComponents = Collections.synchronizedList(new ArrayList<>());
+ List<MonitoringComponent> unavailable = Collections.synchronizedList(new ArrayList<>());
+ mcRefs.entrySet().parallelStream().forEach(entry ->
+ entry.getValue().parallelStream().forEach(id -> {
+ try{
+ monitoringComponents.add(new MonitoringComponent(getSdcRestClient().getResource(id, requestId), entry.getKey()));
+ } catch (Exception e) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"Failed to fetch monitoring component with uuid {}. message: {} ", id, e);
+ unavailable.add(new MonitoringComponent(id, entry.getKey(), "unavailable"));
+ }
+
+ })
+ );
+ result.put("monitoringComponents", monitoringComponents);
+ if(!isEmpty(unavailable)) {
+ result.put("unavailable", unavailable);
+ }
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Finished fetching monitoring components metadata for vfis {}", mcRefs.keySet());
+ return result;
+ }
+
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/VfcmtBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/VfcmtBusinessLogic.java
new file mode 100644
index 0000000..e68a8ee
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/VfcmtBusinessLogic.java
@@ -0,0 +1,283 @@
+package org.onap.sdc.dcae.composition.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang.StringUtils;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.*;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ExternalReferencesMap;
+import org.onap.sdc.dcae.composition.restmodels.sdc.Resource;
+import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
+import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
+import org.onap.sdc.dcae.enums.ArtifactType;
+import org.onap.sdc.dcae.enums.LifecycleOperationType;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.utils.SdcRestClientUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Base64Utils;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.onap.sdc.dcae.composition.util.DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT;
+import static org.onap.sdc.dcae.composition.util.DcaeBeConstants.LifecycleStateEnum.findState;
+
+@Component
+public class VfcmtBusinessLogic extends BaseBusinessLogic {
+
+ private static final String VFCMT = "VFCMT";
+ private static final String TEMPLATE = "Template";
+ private static final String MONITORING_TEMPLATE = "Monitoring Template";
+ private static final String DEFAULTICON = "defaulticon";
+ private static final String VENDOR_NAME = "vendorName";
+ private static final String VENDOR_RELEASE = "vendorRelease";
+
+ public ResponseEntity createMcFromTemplate(String userId, CreateVFCMTRequest request, String requestId) {
+ if(!validateMCRequestFields(request)) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Missing information");
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_CONTENT);
+ }
+ return cloneMcAndAddServiceReference(userId, request, requestId);
+ }
+
+ //1806 US388513 collect existing VFCMT data - flowType from cdump artifact and external reference from svc_reference artifact. If cdump not found - return error
+
+ public ResponseEntity getVfcmtReferenceData(String vfcmtUuid, String requestId) throws Exception {
+ ResourceDetailed vfcmt = sdcRestClient.getResource(vfcmtUuid, requestId);
+ Artifact artifactData = findCdumpArtifactData(vfcmt);
+ if(null == artifactData) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"No composition found on vfcmt {}", vfcmtUuid);
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.MISSING_TOSCA_FILE, "", vfcmt.getName());
+ }
+ VfcmtData vfcmtData = new VfcmtData(vfcmt);
+ //fetch cdump payload
+ String payload = getSdcRestClient().getResourceArtifact(vfcmtUuid, artifactData.getArtifactUUID(), requestId);
+ //extract and set flowType from cdump payload
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"Looking for flowType definition in cdump");
+ vfcmtData.setFlowType(StringUtils.substringBetween(payload,"\"flowType\":\"","\""));
+ //find svc_reference
+ artifactData = findArtifactDataByArtifactName(vfcmt, DcaeBeConstants.Composition.fileNames.SVC_REF);
+ if(null != artifactData) {
+ //fetch svc_reference payload
+ payload = getSdcRestClient().getResourceArtifact(vfcmtUuid, artifactData.getArtifactUUID(), requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"Looking for attached service and vfi info in svc_reference");
+ //extract and set serviceUuid from svc_reference payload
+ vfcmtData.setServiceUuid(StringUtils.substringBefore(payload, "/"));
+ //extract and set vfiName from svc_reference payload
+ vfcmtData.setVfiName(StringUtils.substringAfterLast(payload, "/"));
+ }
+ return new ResponseEntity<>(vfcmtData, HttpStatus.OK);
+ }
+
+
+ //1806 US388525 import or clone VFCMT - always pass the flowType - update will only take place if missing from cdump
+ public ResponseEntity importMC(String userId, ImportVFCMTRequest request, String requestId) {
+ if(!validateMCRequestFields(request)) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Missing information");
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_CONTENT);
+ }
+ // option 1 - clone
+ if(request.isCloneVFCMT()) {
+ return cloneMcAndAddServiceReference(userId, request, requestId);
+ }
+
+ ResourceDetailed vfcmt = null;
+ boolean undoCheckoutOnFailure = false;
+ // fetch vfcmt and cdump
+ try {
+ vfcmt = sdcRestClient.getResource(request.getTemplateUuid(), requestId);
+ Artifact cdumpArtifactData = fetchCdumpAndSetFlowType(vfcmt, request.getFlowType(), requestId);
+ if (null == cdumpArtifactData) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "No cdump found for monitoring component {}", vfcmt.getUuid());
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.MISSING_TOSCA_FILE, "", vfcmt.getName());
+ }
+ String cdumpPayload = cdumpArtifactData.getPayloadData();
+
+ // option 2 - edit original cdump - requires check out
+ if(request.isUpdateFlowType()) {
+ if(DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT != DcaeBeConstants.LifecycleStateEnum.findState(vfcmt.getLifecycleState())) {
+ vfcmt = sdcRestClient.changeResourceLifecycleState(userId, vfcmt.getUuid(), LifecycleOperationType.CHECKOUT.name(), "checking out VFCMT", requestId);
+ undoCheckoutOnFailure = true;
+ }
+ cdumpArtifactData.setDescription("updating flowType on cdump");
+ cdumpArtifactData.setPayloadData(Base64Utils.encodeToString(cdumpPayload.getBytes()));
+ sdcRestClient.updateResourceArtifact(userId, vfcmt.getUuid(), cdumpArtifactData, requestId);
+ }
+ // option 3 - update service reference only
+ updateReferenceToService(userId, request, vfcmt.getUuid(), requestId);
+ if(DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT == DcaeBeConstants.LifecycleStateEnum.findState(vfcmt.getLifecycleState())) {
+ // this will not throw an exception
+ checkinVfcmtAfterClone(userId, vfcmt, requestId);
+ }
+ return new ResponseEntity<>(buildVfcmtAndCdumpResponse(vfcmt, request.getVfiName(), request.getFlowType(), cdumpPayload), HttpStatus.OK);
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR,this.getClass().getName(),"Failed updating Monitoring Component:{}", e.getMessage());
+ if(undoCheckoutOnFailure) {
+ rollBack(userId, vfcmt, requestId);
+ }
+ return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.CREATE_NEW_VFCMT);
+ }
+
+ }
+
+ private boolean validateMCRequestFields(CreateVFCMTRequest request) {
+ return Stream.of(request.getFlowType(), request.getTemplateUuid(), request.getName(), request.getDescription(), request.getContextType(), request.getServiceUuid(), request.getVfiName())
+ .allMatch(StringUtils::isNotBlank);
+ }
+
+ private void updateReferenceToService(String userId, CreateVFCMTRequest request, String newVfcmtUuid, String requestId) {
+ String serviceUuid = request.getServiceUuid();
+ String vfiName = request.getVfiName();
+
+ debugLogger.log(LogLevel.INFO, this.getClass().getName(),"About to update service {}/{} to monitoring component {} ", serviceUuid, vfiName, request.getName());
+
+ sdcRestClient.addExternalMonitoringReference(userId, request, new ReferenceUUID(newVfcmtUuid), requestId);
+
+ }
+
+ private void rollBack(String userId, ResourceDetailed newVfcmt, String requestId) {
+ if (null != newVfcmt) {
+ try {
+ getSdcRestClient().changeResourceLifecycleState(userId, newVfcmt.getUuid(), LifecycleOperationType.UNDO_CHECKOUT.getValue(), "DCAE rollback", requestId);
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR,this.getClass().getName(),"Failed rolling back Monitoring Component. ID:{}", newVfcmt.getUuid());
+ debugLogger.log(LogLevel.ERROR,this.getClass().getName(),"Failed rolling back Monitoring Component:{}", e);
+ }
+ }
+ }
+
+ private ResponseEntity cloneMcAndAddServiceReference(String userId, CreateVFCMTRequest request, String requestId) {
+ addSdcMandatoryFields(request, userId);
+ ResourceDetailed newVfcmt = null;
+ try {
+ // Retrieve the Template VFCMT from SDC - use the template UUID provided from UI
+ ResourceDetailed templateMC = sdcRestClient.getResource(request.getTemplateUuid(), requestId);
+ // Download the CDUMP file from the template VFCMT
+ Artifact cdumpArtifactData = fetchCdumpAndSetFlowType(templateMC, request.getFlowType(), requestId);
+ if (null == cdumpArtifactData) {
+ errLogger.log(LogLevel.ERROR,this.getClass().getName(),"No cdump found for template {} while creating monitoring component", templateMC.getUuid());
+ return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.MISSING_TOSCA_FILE, "", templateMC.getName());
+ }
+ newVfcmt = sdcRestClient.createResource(userId, request, requestId);
+ // The cdump has the original template id. we need to replace it with the new vfcmt id
+ String newVfcmtUuid = newVfcmt.getUuid();
+ String cdumpPayload = cdumpArtifactData.getPayloadData().replaceAll(templateMC.getUuid(), newVfcmtUuid);
+
+ // Upload it to newly created VFCMT
+ cloneArtifactToTarget(userId, newVfcmtUuid, cdumpPayload, cdumpArtifactData, requestId);
+ cloneRuleArtifacts(userId, templateMC, newVfcmtUuid, requestId);
+ createReferenceArtifact(userId, request, newVfcmtUuid, requestId);
+ updateReferenceToService(userId, request, newVfcmtUuid, requestId);
+
+ // this will not throw an exception
+ checkinVfcmtAfterClone(userId, newVfcmt, requestId);
+ return new ResponseEntity<>(buildVfcmtAndCdumpResponse(newVfcmt, request.getVfiName(), request.getFlowType(), cdumpPayload), HttpStatus.OK);
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR,this.getClass().getName(),"Failed creating Monitoring Component:{}", e.getMessage());
+ rollBack(userId, newVfcmt, requestId);
+ return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.CREATE_NEW_VFCMT);
+ }
+ }
+
+ private CreateMcResponse buildVfcmtAndCdumpResponse(ResourceDetailed vfcmt, String vfiName, String flowType, String cdumpPayload) throws IOException {
+ return new CreateMcResponse(new VfcmtData(vfcmt, vfiName, flowType), new ObjectMapper().readValue(cdumpPayload, Object.class));
+ }
+
+ private void checkinVfcmtAfterClone(String userId, ResourceDetailed vfcmt, String requestId) {
+ try {
+ vfcmt = sdcRestClient.changeResourceLifecycleState(userId, vfcmt.getUuid(), LifecycleOperationType.CHECKIN.getValue(), "check in after clone", requestId);
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR,this.getClass().getName(),"Failed to check in Monitoring Component: {}. message: {}", vfcmt.getUuid(), e);
+ }
+ }
+
+
+ private Artifact findCdumpArtifactData(ResourceDetailed vfcmt) {
+ return findArtifactDataByArtifactName(vfcmt, DcaeBeConstants.Composition.fileNames.COMPOSITION_YML);
+ }
+
+ private void cloneRuleArtifacts(String userId, ResourceDetailed templateMC, String newVfcmtUuid, String requestId) throws Exception {
+ // handle rule artifacts using java 7 for-loop - exception propagation to calling method
+ for(Artifact artifact : templateMC.getArtifacts()) {
+ if(artifact.getArtifactName().endsWith(DcaeBeConstants.Composition.fileNames.MAPPING_RULE_POSTFIX)) {
+ cloneArtifactToTarget(userId, newVfcmtUuid, sdcRestClient.getResourceArtifact(templateMC.getUuid(), artifact.getArtifactUUID(), requestId), artifact, requestId);
+ }
+ }
+ }
+
+ // fetch the vfcmt cdump artifact payload and insert the flowType. Return the artifact with updated payload or null (artifact doesn't exist)
+ private Artifact fetchCdumpAndSetFlowType(ResourceDetailed vfcmt, String flowType, String requestId) throws Exception {
+ Artifact cdumpArtifactData = findCdumpArtifactData(vfcmt);
+ if (null != cdumpArtifactData) {
+ String cdumpPayload = sdcRestClient.getResourceArtifact(vfcmt.getUuid(), cdumpArtifactData.getArtifactUUID(), requestId);
+ // Add flowType data to cdump if provided
+ if(!cdumpPayload.contains("\"flowType\":\"") && StringUtils.isNotBlank(flowType)) {
+ cdumpPayload = cdumpPayload.replaceFirst("\\{", "{\"flowType\":\"" + flowType + "\",");
+ }
+ cdumpArtifactData.setPayloadData(cdumpPayload);
+ }
+ return cdumpArtifactData;
+ }
+
+ // backward compatibility (very backward)
+ private void createReferenceArtifact(String userId, CreateVFCMTRequest request, String newVfcmtUuid, String requestId) throws Exception {
+ String referencePayload = request.getServiceUuid() + "/resources/" + request.getVfiName();
+ Artifact refArtifact = SdcRestClientUtils.generateDeploymentArtifact("createReferenceArtifact", DcaeBeConstants.Composition.fileNames.SVC_REF, ArtifactType.DCAE_TOSCA.name(), "servicereference", referencePayload.getBytes());
+ sdcRestClient.createResourceArtifact(userId, newVfcmtUuid, refArtifact, requestId);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Artifact {} created with content: {}", DcaeBeConstants.Composition.fileNames.SVC_REF, referencePayload);
+ }
+
+ public ResponseEntity getVfcmtsForMigration(String userId, String contextType, String uuid, String version,
+ String requestId) {
+ List<Resource> resources;
+ ExternalReferencesMap connectedVfcmts;
+ try {
+ connectedVfcmts = getSdcRestClient().getMonitoringReferences(contextType, uuid, version, requestId);
+ resources = getSdcRestClient().getResources(VFCMT, TEMPLATE, MONITORING_TEMPLATE, requestId);
+ } catch (Exception e) {
+ errLogger.log(LogLevel.ERROR,this.getClass().getName(),"Exception getVfcmtsForMigration {}", e);
+ debugLogger.log(LogLevel.DEBUG,this.getClass().getName(),"Exception getVfcmtsForMigration {}", e);
+ return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.GET_ALL_VFCMTS);
+ }
+
+ List<Resource> vfcmts = resources.stream()
+ .filter(resource -> notCheckedOutOrMine(userId, resource))
+ .filter(resource -> !connected(resource, connectedVfcmts))
+ .collect(Collectors.toList());
+ return new ResponseEntity<>(vfcmts, HttpStatus.OK);
+ }
+
+ private boolean connected(Resource resource, ExternalReferencesMap connectedVfcmts){
+ return connectedVfcmts.values().stream().anyMatch(p -> p.contains(resource.getUuid()));
+ }
+
+ private boolean notCheckedOutOrMine(String userId, Resource resource) {
+ // if the resource belongs to this user then it is kosher
+ // or if it doesn't belong to the user check the lifecycle state is checked out
+
+ return resource.getLastUpdaterUserId().equalsIgnoreCase(userId) ||
+ NOT_CERTIFIED_CHECKOUT != findState(resource.getLifecycleState());
+ }
+
+
+ public void addSdcMandatoryFields(CreateVFCMTRequest createRequest, String user) {
+ createRequest.setContactId(user);
+ createRequest.setIcon(DEFAULTICON);
+ createRequest.setResourceType(VFCMT);
+ createRequest.setVendorName(VENDOR_NAME);
+ createRequest.setVendorRelease(VENDOR_RELEASE);
+ if (StringUtils.isBlank(createRequest.getCategory())) {
+ createRequest.setCategory(TEMPLATE);
+ }
+ if (StringUtils.isBlank(createRequest.getSubcategory())) {
+ createRequest.setSubcategory(MONITORING_TEMPLATE);
+ }
+ createRequest.setTags(new String[]{createRequest.getName()});
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ActionStatus.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ActionStatus.java
new file mode 100644
index 0000000..cac92f5
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ActionStatus.java
@@ -0,0 +1,48 @@
+package org.onap.sdc.dcae.errormng;
+
+public enum ActionStatus {
+
+ OK,
+ CREATED,
+ NO_CONTENT,
+ NOT_ALLOWED,
+ GENERAL_ERROR,
+ INVALID_CONTENT,
+ NOT_FOUND,
+ CONFIGURATION_ERROR,
+ VES_SCHEMA_NOT_FOUND,
+ VES_SCHEMA_INVALID,
+ FLOW_TYPES_CONFIGURATION_ERROR,
+ CLONE_FAILED,
+ EMPTY_SERVICE_LIST,
+ MONITORING_TEMPLATE_ATTACHMENT_ERROR,
+ MISSING_TOSCA_FILE,
+ VALIDATE_TOSCA_ERROR,
+ SUBMIT_BLUEPRINT_ERROR,
+ GENERATE_BLUEPRINT_ERROR,
+ INVALID_RULE_FORMAT,
+ SAVE_RULE_FAILED,
+ RESOURCE_NOT_VFCMT_ERROR,
+ VFI_FETCH_ERROR,
+ USER_CONFLICT,
+ MISSING_RULE_DESCRIPTION,
+ MISSING_ACTION,
+ MISSING_ACTION_FIELD,
+ MISSING_CONCAT_VALUE,
+ INVALID_GROUP_CONDITION,
+ MISSING_CONDITION_ITEM,
+ MISSING_OPERAND,
+ INVALID_OPERATOR,
+ MISSING_ENTRY,
+ MISSING_DEFAULT_VALUE,
+ DUPLICATE_KEY,
+ ACTION_DEPENDENCY,
+ RULE_DEPENDENCY,
+ NODE_NOT_FOUND,
+ DELETE_RULE_FAILED,
+ TRANSLATE_FAILED,
+ CATALOG_NOT_AVAILABLE,
+ AUTH_ERROR,
+ DELETE_BLUEPRINT_FAILED,
+ AS_IS
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/BasicConfiguration.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/BasicConfiguration.java
new file mode 100644
index 0000000..001109e
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/BasicConfiguration.java
@@ -0,0 +1,5 @@
+package org.onap.sdc.dcae.errormng;
+
+public class BasicConfiguration {
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/DcaeException.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/DcaeException.java
new file mode 100644
index 0000000..60b8e0e
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/DcaeException.java
@@ -0,0 +1,15 @@
+package org.onap.sdc.dcae.errormng;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.client.HttpClientErrorException;
+
+public class DcaeException extends BaseException {
+
+// public DcaeException(HttpClientErrorException theError) {
+// super(theError);
+// }
+
+ public DcaeException(HttpStatus status, RequestError re){
+ super(status, re);
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrConfMgr.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrConfMgr.java
new file mode 100644
index 0000000..de1d06b
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrConfMgr.java
@@ -0,0 +1,306 @@
+package org.onap.sdc.dcae.errormng;
+
+import org.onap.sdc.dcae.catalog.asdc.ASDCException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.util.*;
+
+public enum ErrConfMgr {
+ INSTANCE;
+
+ private static EnumMap<ApiType, Map<String, String>> sdcDcaeMsgIdMap;
+ public static final String AS_IS = "AS_IS";
+ private ResponseFormatManager responseFormatManager;
+
+ ErrConfMgr() {
+ responseFormatManager = ResponseFormatManager.getInstance();
+ populateSdcDcaeMsgIdMap();
+ }
+
+ private void setSdcCatalogPolicyMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("POL5000", AS_IS);
+ map.put("POL5001", "POL5500");
+ map.put("POL5002", "POL5501");
+ sdcDcaeMsgIdMap.put(ApiType.ALL_SDC_CATALOG, map);
+ }
+
+ private void setGetVfcmtMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", AS_IS);
+ map.put("SVC4505", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.GET_VFCMT, map);
+ }
+
+ private void setCreateNewVfcmtMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4050", AS_IS);
+ map.put("SVC4126", AS_IS);
+ map.put("SVC4500", AS_IS);
+ map.put("SVC4062", AS_IS);
+ map.put("SVC4064", AS_IS);
+ map.put("SVC4065", AS_IS);
+ map.put("SVC4066", AS_IS);
+ map.put("SVC4067", AS_IS);
+ map.put("SVC4068", AS_IS);
+ map.put("SVC4069", AS_IS);
+ map.put("SVC4070", AS_IS);
+ map.put("SVC4071", AS_IS);
+ map.put("SVC4072", AS_IS);
+ map.put("SVC4073", AS_IS);
+ map.put("SVC4053", AS_IS);
+ map.put("POL5003", AS_IS);
+ // adding service referencing error handling to create scenario
+ map.put("SVC4063", AS_IS);
+ map.put("SVC4122", AS_IS);
+ map.put("SVC4124", AS_IS);
+ map.put("SVC4128", AS_IS);
+ map.put("SVC4125", AS_IS);
+ map.put("SVC4127", AS_IS);
+ map.put("SVC4086", AS_IS);
+ map.put("SVC4301", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.CREATE_NEW_VFCMT, map);
+ }
+
+ private void setCloneVfcmtMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", AS_IS);
+ map.put("SVC4505", AS_IS);
+ map.put("SVC4085", AS_IS);
+ map.put("SVC4080", AS_IS);
+ map.put("SVC4122", "SVC6010");
+ map.put("SVC4124", "SVC6010");
+ map.put("SVC4128", "SVC6010");
+ map.put("SVC4125", AS_IS);
+ map.put("SVC4127", "SVC6010");
+ map.put("SVC4086", AS_IS);
+ map.put("SVC4301", AS_IS);
+ map.put("SVC4086", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.CLONE_VFCMT, map);
+ }
+
+
+ private void setGetServiceMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4503", AS_IS);
+ map.put("SVC4642", "200");
+ sdcDcaeMsgIdMap.put(ApiType.GET_SERVICE, map);
+ }
+
+ private void setAttachToServiceMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", "SVC6021");
+ map.put("SVC4122", "SVC6021");
+ map.put("SVC4124", "SVC6021");
+ map.put("SVC4128", "SVC6021");
+ map.put("SVC4125", AS_IS);
+ map.put("SVC4127", "SVC6021");
+ map.put("SVC4086", AS_IS);
+ map.put("SVC4301", AS_IS);
+ map.put("SVC4503", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.ATTACH_TO_SERVICE, map);
+ }
+
+ private void setGetCdumpMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", AS_IS);
+ map.put("SVC4505", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.GET_CDUMP, map);
+ }
+
+ private void setGetModelMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", AS_IS);
+ map.put("SVC4505", "SVC6031");
+ sdcDcaeMsgIdMap.put(ApiType.GET_MODEL, map);
+ }
+
+ private void setCheckoutResourceMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", "SVC6021");
+ map.put("SVC4085", AS_IS);
+ map.put("SVC4080", AS_IS);
+ map.put("SVC4002", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.CHECK_OUT_RESOURCE, map);
+ }
+
+ private void setCheckinResourceMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", "SVC6021");
+ map.put("SVC4086", AS_IS);
+ map.put("SVC4301", AS_IS);
+ map.put("SVC4084", AS_IS);
+ map.put("SVC4085", AS_IS);
+ map.put("SVC4002", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.CHECK_IN_RESOURCE, map);
+ }
+
+ private void setSaveCdumpMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", "SVC6021");
+ map.put("SVC4122", "SVC6021");
+ map.put("SVC4124", "SVC6021");
+ map.put("SVC4128", "SVC6021");
+ map.put("SVC4125", AS_IS);
+ map.put("SVC4127", "SVC6021");
+ map.put("SVC4086", AS_IS);
+ map.put("SVC4301", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.SAVE_CDUMP, map);
+ }
+
+ private void setSubmitBlueprintMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", AS_IS);
+ map.put("SVC4505", "SVC6031");
+ map.put("SVC4503", AS_IS);
+ map.put("SVC4085", AS_IS);
+ map.put("SVC4080", AS_IS);
+ map.put("SVC4122", "SVC6033");
+ map.put("SVC4124", "SVC6033");
+ map.put("SVC4128", "SVC6033");
+ map.put("SVC4125", AS_IS);
+ map.put("SVC4127", "SVC6033");
+ map.put("SVC4086", AS_IS);
+ map.put("SVC4301", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.SUBMIT_BLUEPRINT, map);
+ }
+
+ private void setGetRuleMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.GET_RULE_ARTIFACT, map);
+ }
+
+ private void setSaveRuleMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4063", "SVC6036");
+ map.put("SVC4122", "SVC6036");
+ map.put("SVC4124", "SVC6036");
+ map.put("SVC4128", "SVC6036");
+ map.put("SVC4125", AS_IS);
+ map.put("SVC4127", "SVC6036");
+ map.put("SVC4086", AS_IS);
+ map.put("SVC4301", AS_IS);
+ map.put("SVC4000", "SVC6036");
+ sdcDcaeMsgIdMap.put(ApiType.SAVE_RULE_ARTIFACT, map);
+ }
+
+ private void setGetAllVfcmtMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("SVC4642", "200");
+ sdcDcaeMsgIdMap.put(ApiType.GET_ALL_VFCMTS, map);
+ }
+
+
+ private void setDeleteReferenceMapping(){
+ Map<String, String> map = new HashMap<>();
+ map.put("POL5003", AS_IS);
+ map.put("SVC4063", AS_IS);
+ map.put("POL4050", AS_IS);
+ map.put("SVC4086", AS_IS);
+ map.put("SVC4301", AS_IS);
+ map.put("SVC4687", AS_IS);
+ sdcDcaeMsgIdMap.put(ApiType.DELETE_VFCMT_REFERENCE, map);
+ }
+
+ private void populateSdcDcaeMsgIdMap() {
+ sdcDcaeMsgIdMap = new EnumMap<>(ApiType.class);
+ setAttachToServiceMapping();
+ setCheckinResourceMapping();
+ setCheckoutResourceMapping();
+ setCloneVfcmtMapping();
+ setGetAllVfcmtMapping();
+ setGetRuleMapping();
+ setCreateNewVfcmtMapping();
+ setGetCdumpMapping();
+ setGetModelMapping();
+ setSaveCdumpMapping();
+ setSaveRuleMapping();
+ setSubmitBlueprintMapping();
+ setGetServiceMapping();
+ setGetVfcmtMapping();
+ setSdcCatalogPolicyMapping();
+ setDeleteReferenceMapping();
+ }
+
+ public enum ApiType {
+ CREATE_NEW_VFCMT,
+ GET_ALL_VFCMTS,
+ CLONE_VFCMT,
+ GET_VFCMT,
+ GET_SERVICE,
+ ATTACH_TO_SERVICE,
+ GET_CDUMP,
+ GET_MODEL,
+ CHECK_OUT_RESOURCE,
+ CHECK_IN_RESOURCE,
+ SAVE_CDUMP,
+ SUBMIT_BLUEPRINT,
+ GET_RULE_ARTIFACT,
+ SAVE_RULE_ARTIFACT,
+ ALL_SDC_CATALOG,
+ DELETE_VFCMT_REFERENCE
+ }
+
+ public ResponseFormat getResponseFormat(ActionStatus actionStatus, String notes, String... variables) {
+ return responseFormatManager.getResponseFormat(actionStatus, notes, variables);
+ }
+
+ public ResponseEntity buildErrorResponse(ActionStatus actionStatus, String notes, String... variables) {
+ ResponseFormat response = responseFormatManager.getResponseFormat(actionStatus, notes, variables);
+ return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus()));
+ }
+
+ public ResponseEntity buildErrorResponse(ActionStatus actionStatus) {
+ ResponseFormat response = responseFormatManager.getResponseFormat(actionStatus, "");
+ return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus()));
+ }
+
+ public ResponseEntity buildErrorResponse(BaseException baseException) {
+ ResponseFormat response = responseFormatManager.getResponseFormat(baseException);
+ return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus()));
+ }
+
+ public ResponseEntity buildErrorArrayResponse(List<ServiceException> errors) {
+ ResponseFormat response = responseFormatManager.getResponseFormat(errors);
+ return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus()));
+ }
+
+ // ActionStatus determined by sdc to dcae mapping
+ public ActionStatus convertToDcaeActionStatus(String messageId, ApiType apiType) {
+ // try the apiType's specific mapping from SDC messageId to dcaeMessageId
+ String dcaeMessageId = sdcDcaeMsgIdMap.get(apiType).get(messageId);
+ // if no specific mapping found try the general mapping
+ if(null == dcaeMessageId)
+ dcaeMessageId = sdcDcaeMsgIdMap.get(ApiType.ALL_SDC_CATALOG).get(messageId);
+ // if no mapping found return general error
+ if(null == dcaeMessageId)
+ return ActionStatus.GENERAL_ERROR;
+ // if mapped to 'AS_IS' return 'AS_IS'
+ if(AS_IS.equals(dcaeMessageId))
+ return ActionStatus.AS_IS;
+ // for any other valid mapping fetch the ActionStatus by corresponding dcaeMessageId
+ return responseFormatManager.getMsgIdToActionStatusMap().get(dcaeMessageId);
+ }
+
+ public ResponseEntity handleException(Exception e, ApiType apiType, String... variables){
+ if (e instanceof ASDCException){
+ ASDCException se = (ASDCException)e;
+ ActionStatus status = convertToDcaeActionStatus(se.getMessageId(), apiType);
+ switch (status) {
+ case AS_IS:
+ return buildErrorResponse(se);
+ case OK:
+ return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK);
+ default:
+ return buildErrorResponse(status, se.getMessage(), variables);
+ }
+ }
+ //TODO refactor - don't throw DcaeException
+ if (e instanceof DcaeException){
+ return buildErrorResponse((DcaeException)e);
+ }
+ return buildErrorResponse(ActionStatus.GENERAL_ERROR, e.getMessage());
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorConfiguration.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorConfiguration.java
new file mode 100644
index 0000000..8f6f5af
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorConfiguration.java
@@ -0,0 +1,46 @@
+package org.onap.sdc.dcae.errormng;
+
+import java.util.Map;
+
+/**
+ * Example:
+ * VES_SCHEMA_INVALID: {
+ code: 500,
+ message: "Error – Failed to parse VES Schema file '%1'. [%2]",
+ messageId: "SVC6007"
+ }
+
+ key will be "VES_SCHEMA_INVALID"
+ value is the json object containing code, message, messageId
+ */
+
+import org.onap.sdc.dcae.errormng.BasicConfiguration;
+
+public class ErrorConfiguration extends BasicConfiguration {
+
+ private Map<String, ErrorInfo> errors;
+
+ public Map<String, ErrorInfo> getErrors() {
+ return errors;
+ }
+
+ public void setErrors(Map<String, ErrorInfo> errors) {
+ this.errors = errors;
+ }
+
+ public ErrorInfo getErrorInfo(String key) {
+ ErrorInfo clone = null;
+ ErrorInfo other = errors.get(key);
+ if (other != null) {
+ clone = new ErrorInfo();
+ clone.cloneData(other);
+ }
+ return clone;
+ }
+
+ @Override
+ public String toString() {
+ return "ErrorConfiguration [errors=" + errors + "]";
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorConfigurationLoader.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorConfigurationLoader.java
new file mode 100644
index 0000000..8b7ab44
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorConfigurationLoader.java
@@ -0,0 +1,121 @@
+package org.onap.sdc.dcae.errormng;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+
+public class ErrorConfigurationLoader {
+
+ private static ErrorConfigurationLoader instance;
+ private String jettyBase;
+ private ErrorConfiguration errorConfiguration = new ErrorConfiguration();
+ private OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ public ErrorConfigurationLoader(String sourcePath) {
+ jettyBase = sourcePath;
+ loadErrorConfiguration();
+ instance = this;
+ }
+
+ private void loadErrorConfiguration(){
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "ErrorConfigurationLoader: Trying to load error configuration");
+ if (jettyBase == null) {
+ String msg = "Couldn't resolve jetty.base environmental variable";
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), msg);
+ throw new ExceptionInInitializerError (msg + ". Failed to load error configuration files... aborting");
+ }
+
+ String path = jettyBase + "/config/dcae-be";
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "jetty.base={}", jettyBase);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Configuration Path={}", path);
+
+ File dir = new File(path);
+ File[] files = dir.listFiles(new FilenameFilter() {
+ @Override public boolean accept(File dir, String name) {
+ return name.equals("error-configuration.yaml");
+ }
+ });
+
+ if (ArrayUtils.isEmpty(files)) {
+ String msg = "No error configuration files found";
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), msg);
+ throw new ExceptionInInitializerError (msg);
+ }else if (files.length>1){
+ String msg = "Multiple configuration files found. Make sure only one file exists. Path: "+ path;
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), msg);
+ throw new ExceptionInInitializerError (msg);
+ }
+ else {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Loading error configuration file: {}", files[0].getName());
+ try {
+ errorConfiguration = parseErrConfFileAndSaveToMap(files[0].getCanonicalPath());
+// convertToUsefulMaps(errorConfiguration);
+ } catch (IOException e) {
+ String msg = "Exception thrown while trying to read the error configuration file path. File="+files[0].getName();
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), msg);
+ throw new ExceptionInInitializerError (msg);
+ }
+ if(errorConfiguration == null){
+ String msg = "Error configuration file couldn't be parsed";
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), msg);
+ throw new ExceptionInInitializerError (msg);
+ }
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Error Configuration: {}", errorConfiguration.toString());
+ }
+ }
+
+
+ private ErrorConfiguration parseErrConfFileAndSaveToMap(String fullFileName) {
+
+ Yaml yaml = new Yaml();
+
+ InputStream in = null;
+ ErrorConfiguration errorConfiguration = null;
+ try {
+
+ File f = new File(fullFileName);
+ if (false == f.exists()) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "The file {} cannot be found. Ignore reading configuration.", fullFileName);
+ return null;
+ }
+ in = Files.newInputStream(Paths.get(fullFileName));
+
+ errorConfiguration = yaml.loadAs(in, ErrorConfiguration.class);
+
+ } catch (Exception e) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Failed to convert yaml file {} to object. {}", fullFileName, e);
+ return null;
+ }
+ finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Failed to close input stream {}", e.getMessage());
+ }
+ }
+ }
+
+ return errorConfiguration;
+ }
+
+ ErrorConfiguration getErrorConfiguration() {
+ return errorConfiguration;
+ }
+
+ public static ErrorConfigurationLoader getErrorConfigurationLoader() {
+ return instance;
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorInfo.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorInfo.java
new file mode 100644
index 0000000..3ec3cef
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrorInfo.java
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * 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.sdc.dcae.errormng;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+
+public class ErrorInfo {
+
+ private Integer code;
+ private String message;
+ private String messageId;
+ private ErrorInfoType errorInfoType;
+
+ private static final String SVC_PREFIX = "SVC";
+ private static final String POL_PREFIX = "POL";
+
+ private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+
+ public ErrorInfo() {
+ this.errorInfoType = ErrorInfoType.OK;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public void setCode(Integer code) {
+ this.code = code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessageId() {
+ return messageId;
+ }
+
+ public void setMessageId(String messageId) {
+ // Determining the type of error
+ if (messageId == null || "200".equals(messageId) || "201".equals(messageId) || "204".equals(messageId)) {
+ this.errorInfoType = ErrorInfoType.OK;
+ } else if (messageId.startsWith(SVC_PREFIX)) {
+ this.errorInfoType = ErrorInfoType.SERVICE_EXCEPTION;
+ } else if (messageId.startsWith(POL_PREFIX)) {
+ this.errorInfoType = ErrorInfoType.POLICY_EXCEPTION;
+ } else {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Error: unexpected error message ID {}, should start with {} or {}", messageId, SVC_PREFIX, POL_PREFIX);
+ }
+ this.messageId = messageId;
+ }
+
+ public ErrorInfoType getErrorInfoType() {
+ return this.errorInfoType;
+ }
+
+ public void cloneData(ErrorInfo other) {
+ this.code = other.getCode();
+ this.message = other.getMessage();
+ this.messageId = other.getMessageId();
+ this.errorInfoType = other.errorInfoType;
+ }
+
+ @Override
+ public String toString() {
+ return "ErrorInfo [code=" + code + ", messageId=" + messageId + ", message=" + message + "]";
+ }
+
+ public enum ErrorInfoType {
+ OK, POLICY_EXCEPTION, SERVICE_EXCEPTION
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ResponseFormatManager.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ResponseFormatManager.java
new file mode 100644
index 0000000..ada790f
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ResponseFormatManager.java
@@ -0,0 +1,103 @@
+package org.onap.sdc.dcae.errormng;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.errormng.ErrorInfo.ErrorInfoType;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ResponseFormatManager {
+
+ private volatile static ResponseFormatManager instance;
+ private static ErrorConfiguration errorConfiguration;
+ private static Map<String, ActionStatus> msgIdToActionStatusMap = new HashMap<>();
+ private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+
+ public static ResponseFormatManager getInstance() {
+ if (instance == null) {
+ instance = init();
+ }
+ return instance;
+ }
+
+ private static synchronized ResponseFormatManager init() {
+ if (instance == null) {
+ instance = new ResponseFormatManager();
+ errorConfiguration = ErrorConfigurationLoader.getErrorConfigurationLoader().getErrorConfiguration();
+ convertToActionMap();
+ }
+ return instance;
+ }
+
+ ResponseFormat getResponseFormat(ActionStatus actionStatus, String notes, String... variables) {
+ ErrorInfo errorInfo = errorConfiguration.getErrorInfo(actionStatus.name());
+ if (errorInfo == null) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "failed to locate {} in error configuration", actionStatus.name());
+ errorInfo = errorConfiguration.getErrorInfo(ActionStatus.GENERAL_ERROR.name());
+ }
+
+ ResponseFormat responseFormat = new ResponseFormat(errorInfo.getCode());
+ String errorMessage = errorInfo.getMessage();
+ String errorMessageId = errorInfo.getMessageId();
+ ErrorInfoType errorInfoType = errorInfo.getErrorInfoType();
+ responseFormat.setNotes(notes);
+
+ if (errorInfoType==ErrorInfoType.SERVICE_EXCEPTION) {
+ responseFormat.setServiceException(new ServiceException(errorMessageId, errorMessage, variables));
+ }
+ else if (errorInfoType==ErrorInfoType.POLICY_EXCEPTION) {
+ responseFormat.setPolicyException(new PolicyException(errorMessageId, errorMessage, variables));
+ }
+ else if (errorInfoType==ErrorInfoType.OK) {
+ responseFormat.setOkResponseInfo(new OkResponseInfo(errorMessageId, errorMessage, variables));
+ }
+ return responseFormat;
+ }
+
+ ResponseFormat getResponseFormat(BaseException baseException) {
+
+ ResponseFormat responseFormat = new ResponseFormat(baseException.getRawStatusCode());
+ AbstractSdncException e = baseException.getRequestError().getError();
+
+ if (e instanceof ServiceException) {
+ responseFormat.setServiceException((ServiceException)e);
+ }
+ else if (e instanceof PolicyException) {
+ responseFormat.setPolicyException((PolicyException)e);
+ }
+ else {
+ responseFormat.setOkResponseInfo((OkResponseInfo)e);
+ }
+ return responseFormat;
+ }
+
+ ResponseFormat getResponseFormat(List<ServiceException> errors) {
+ ResponseFormat responseFormat = new ResponseFormat(400);
+ responseFormat.setServiceExceptions(errors);
+ return responseFormat;
+ }
+
+ public Map<String, ActionStatus> getMsgIdToActionStatusMap() {
+ return msgIdToActionStatusMap;
+ }
+
+ private static void convertToActionMap() {
+ Map<String, ErrorInfo> errors = errorConfiguration.getErrors();
+
+ if(errors!=null){
+ errors.forEach((k, v) -> {
+ debugLogger.log(LogLevel.DEBUG, ResponseFormatManager.class.getName(), "{}, {}", v.getMessageId(), k);
+ msgIdToActionStatusMap.put(v.getMessageId(), ActionStatus.valueOf(k));
+ });
+ }
+ }
+
+ public ResponseFormatManager(){
+
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/filter/LoggingFilter.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/filter/LoggingFilter.java
new file mode 100644
index 0000000..919d244
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/filter/LoggingFilter.java
@@ -0,0 +1,247 @@
+package org.onap.sdc.dcae.filter;
+
+import static java.net.HttpURLConnection.HTTP_BAD_METHOD;
+import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+import static java.net.HttpURLConnection.HTTP_CLIENT_TIMEOUT;
+import static java.net.HttpURLConnection.HTTP_CONFLICT;
+import static java.net.HttpURLConnection.HTTP_ENTITY_TOO_LARGE;
+import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
+import static java.net.HttpURLConnection.HTTP_GONE;
+import static java.net.HttpURLConnection.HTTP_LENGTH_REQUIRED;
+import static java.net.HttpURLConnection.HTTP_NOT_ACCEPTABLE;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_PAYMENT_REQUIRED;
+import static java.net.HttpURLConnection.HTTP_PRECON_FAILED;
+import static java.net.HttpURLConnection.HTTP_PROXY_AUTH;
+import static java.net.HttpURLConnection.HTTP_REQ_TOO_LONG;
+import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
+import static java.net.HttpURLConnection.HTTP_UNSUPPORTED_TYPE;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.UUID;
+
+import javax.servlet.Filter;
+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 javax.servlet.http.HttpServletResponse;
+
+import org.apache.http.impl.EnglishReasonPhraseCatalog;
+import org.onap.sdc.common.onaplog.OnapLoggerAudit;
+import org.onap.sdc.common.onaplog.OnapMDCWrapper;
+import org.onap.sdc.common.onaplog.Enums.OnapLoggerErrorCode;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+
+public class LoggingFilter implements Filter {
+
+ private static final String serviceName = "DCAE-D-BE";
+
+ private OnapMDCWrapper commonLoggerArgs = OnapMDCWrapper.getInstance();
+ private OnapLoggerAudit auditLogger = OnapLoggerAudit.getInstance();
+
+ public LoggingFilter() {
+ super();
+ }
+
+
+ @Override
+ public void destroy() {}
+
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
+ throws IOException, ServletException {
+
+ boolean shouldLogRequest = true;
+
+ try {
+ if (request instanceof HttpServletRequest) {
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+ if (httpRequest.getServletPath().equals("/healthCheck")) {
+ shouldLogRequest = false;
+ }
+
+ if (shouldLogRequest) {
+ beforeHandle(httpRequest);
+ }
+ }
+ } catch (Exception e) {
+ // TODO: log problem with extracting parameters or writing to log
+ }
+
+ filterChain.doFilter(request, response); // handle request
+
+ try {
+ if (response instanceof HttpServletResponse && shouldLogRequest) {
+ afterHandle((HttpServletResponse) response);
+ }
+ } catch (Exception e) {
+ // TODO: log problem with extracting parameters or writing to log
+ }
+ }
+
+
+ private void beforeHandle(HttpServletRequest request) {
+
+ String requestId = getRequestId(request);
+ request.setAttribute("requestId", requestId); // making requestId available for the API controllers
+ commonLoggerArgs
+ .clear()
+ .startTimer()
+ .setRemoteHost(request.getRemoteAddr())
+ .setServiceName(serviceName)
+ .setPartnerName(getPartnerName(request.getHeader("USER_ID"), request.getHeader("user-agent")))
+ .setKeyRequestId(requestId)
+ .setAutoServerIPAddress(request.getLocalAddr())
+ .setOptCustomField1(request.getProtocol())
+ .setOptCustomField2(request.getMethod())
+ .setOptCustomField3(request.getServletPath());
+
+ }
+
+
+ private static String getRequestId(HttpServletRequest request) {
+ String requestId = request.getHeader("X-ECOMP-RequestID");
+ return isNullOrEmpty(requestId)
+ ? UUID.randomUUID().toString()
+ : requestId;
+ }
+
+
+ private void afterHandle(HttpServletResponse response) {
+ String responseDesc = EnglishReasonPhraseCatalog.INSTANCE.getReason(response.getStatus(), Locale.ENGLISH);
+ commonLoggerArgs
+ .stopTimer()
+ .setResponseCode(getLoggingErrorCode(response.getStatus()).getErrorCode())
+ .setResponseDesc(responseDesc)
+ .setOptCustomField4(Integer.toString(response.getStatus()));
+
+ auditLogger
+ .setStatusCode(Integer.toString(response.getStatus()))
+ .log(LogLevel.INFO, this.getClass().getName(), responseDesc);
+ }
+
+
+ private OnapLoggerErrorCode getLoggingErrorCode(int httpResponseCode) {
+ if (isSuccessError(httpResponseCode)) {
+ return OnapLoggerErrorCode.SUCCESS;
+ }
+ else if (isSchemaError(httpResponseCode)) {
+ return OnapLoggerErrorCode.SCHEMA_ERROR;
+ }
+ else if (isDataError(httpResponseCode)) {
+ return OnapLoggerErrorCode.DATA_ERROR;
+ }
+ else if (isPermissionsError(httpResponseCode)) {
+ return OnapLoggerErrorCode.PERMISSION_ERROR;
+ }
+ else if (isTimeoutOrAvailabilityError(httpResponseCode)) {
+ return OnapLoggerErrorCode.AVAILABILITY_TIMEOUTS_ERROR;
+ }
+ else if (isBusinessProcessError(httpResponseCode)) {
+ return OnapLoggerErrorCode.BUSINESS_PROCESS_ERROR;
+ }
+ else {
+ return OnapLoggerErrorCode.UNKNOWN_ERROR;
+ }
+ }
+
+
+ private boolean isTimeoutOrAvailabilityError(int httpResponseCode) {
+
+ switch (httpResponseCode) {
+ case HTTP_BAD_REQUEST:
+ case HTTP_UNAUTHORIZED:
+ case HTTP_NOT_FOUND:
+ case HTTP_CLIENT_TIMEOUT:
+ case HTTP_GONE:
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isPermissionsError(int httpResponseCode) {
+
+ switch (httpResponseCode) {
+ case HTTP_PAYMENT_REQUIRED:
+ case HTTP_FORBIDDEN:
+ case HTTP_BAD_METHOD:
+ case HTTP_PROXY_AUTH:
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isDataError(int httpResponseCode) {
+
+ switch (httpResponseCode) {
+ case HTTP_NOT_ACCEPTABLE:
+ case HTTP_LENGTH_REQUIRED:
+ case HTTP_PRECON_FAILED:
+ case HTTP_REQ_TOO_LONG:
+ case HTTP_ENTITY_TOO_LARGE:
+ case HTTP_UNSUPPORTED_TYPE:
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isSchemaError(int httpResponseCode) {
+
+ switch (httpResponseCode) {
+ case HTTP_CONFLICT:
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isSuccessError(int httpResponseCode) {
+ return httpResponseCode < 399;
+ }
+
+ private boolean isBusinessProcessError(int httpResponseCode) {
+ return httpResponseCode > 499;
+ }
+
+ private String getPartnerName(String userId, String userAgent) {
+ return (isNullOrEmpty(userId))
+ ? getClientApplication(userAgent)
+ : userId;
+ }
+
+ private String getClientApplication(String userAgent) {
+ if (userAgent != null && userAgent.length() > 0) {
+ if (userAgent.toLowerCase().contains("firefox")) {
+ return "fireFox_FE";
+ }
+
+ if (userAgent.toLowerCase().contains("msie")) {
+ return "explorer_FE";
+ }
+
+ if (userAgent.toLowerCase().contains("chrome")) {
+ return "chrome_FE";
+ }
+
+ return userAgent;
+ }
+ return "";
+ }
+
+
+ private static boolean isNullOrEmpty(String str) {
+ return (str == null || str.isEmpty());
+ }
+
+
+ @Override
+ public void init(FilterConfig config) throws ServletException {}
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/ConditionTypeEnum.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/ConditionTypeEnum.java
new file mode 100644
index 0000000..e4921e2
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/ConditionTypeEnum.java
@@ -0,0 +1,22 @@
+package org.onap.sdc.dcae.rule.editor.enums;
+
+import java.util.Arrays;
+
+public enum ConditionTypeEnum {
+ ALL("And"), ANY("Or");
+
+ public String getFilterClass() {
+ return filterClass;
+ }
+
+ private String filterClass;
+
+ ConditionTypeEnum(String filterClass) {
+
+ this.filterClass = filterClass;
+ }
+
+ public static ConditionTypeEnum getTypeByName(String name) {
+ return Arrays.stream(ConditionTypeEnum.values()).filter(type -> name.equalsIgnoreCase(type.name())).findAny().orElse(null);
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/OperatorTypeEnum.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/OperatorTypeEnum.java
new file mode 100644
index 0000000..2cd03a7
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/OperatorTypeEnum.java
@@ -0,0 +1,32 @@
+package org.onap.sdc.dcae.rule.editor.enums;
+
+import java.util.Arrays;
+
+public enum OperatorTypeEnum {
+ EQUALS("Equals", "OneOf"),
+ NOT_EQUAL("NotEqual", "NotOneOf"),
+ CONTAINS("Contains", null),
+ ENDS_WITH("EndsWith", null),
+ STARTS_WITH("StartsWith", null);
+
+ private String type;
+ private String modifiedType;
+
+ OperatorTypeEnum(String type, String modifiedType) {
+ this.type = type;
+ this.modifiedType = modifiedType;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getModifiedType() {
+ return modifiedType;
+ }
+
+ public static OperatorTypeEnum getTypeByName(String name) {
+ return Arrays.stream(OperatorTypeEnum.values()).filter(type -> name.replaceAll(" ", "").equalsIgnoreCase(type.getType())).findAny().orElse(null);
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/RuleEditorElementType.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/RuleEditorElementType.java
new file mode 100644
index 0000000..0bec7d8
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/RuleEditorElementType.java
@@ -0,0 +1,58 @@
+package org.onap.sdc.dcae.rule.editor.enums;
+
+import java.util.Arrays;
+
+import org.onap.sdc.dcae.rule.editor.translators.ConditionGroupTranslator;
+import org.onap.sdc.dcae.rule.editor.translators.ConditionTranslator;
+import org.onap.sdc.dcae.rule.editor.translators.CopyActionTranslator;
+import org.onap.sdc.dcae.rule.editor.translators.DateFormatterTranslator;
+import org.onap.sdc.dcae.rule.editor.translators.FieldConditionTranslator;
+import org.onap.sdc.dcae.rule.editor.translators.IRuleElementTranslator;
+import org.onap.sdc.dcae.rule.editor.translators.MapActionTranslator;
+import org.onap.sdc.dcae.rule.editor.translators.MappingRulesTranslator;
+import org.onap.sdc.dcae.rule.editor.translators.RegexActionTranslator;
+import org.onap.sdc.dcae.rule.editor.translators.RuleTranslator;
+import org.onap.sdc.dcae.rule.editor.validators.ActionValidator;
+import org.onap.sdc.dcae.rule.editor.validators.ConcatActionValidator;
+import org.onap.sdc.dcae.rule.editor.validators.ConditionGroupValidator;
+import org.onap.sdc.dcae.rule.editor.validators.ConditionValidator;
+import org.onap.sdc.dcae.rule.editor.validators.DateFormatterValidator;
+import org.onap.sdc.dcae.rule.editor.validators.IRuleElementValidator;
+import org.onap.sdc.dcae.rule.editor.validators.MapActionValidator;
+import org.onap.sdc.dcae.rule.editor.validators.RuleValidator;
+
+public enum RuleEditorElementType {
+ COPY("Copy", ActionValidator.getInstance(), CopyActionTranslator.getInstance()),
+ CONCAT("Concat", ConcatActionValidator.getInstance(), CopyActionTranslator.getInstance()),
+ MAP("Map", MapActionValidator.getInstance(), MapActionTranslator.getInstance()),
+ REGEX("Regex", ActionValidator.getInstance(), RegexActionTranslator.getInstance()),
+ DATE_FORMATTER("DateFormatter", DateFormatterValidator.getInstance(), DateFormatterTranslator.getInstance()),
+ CONDITION("Condition", ConditionValidator.getInstance(), ConditionTranslator.getInstance()),
+ FIELD_CONDITION("FieldCondition", ConditionValidator.getInstance(), FieldConditionTranslator.getInstance()),
+ CONDITION_GROUP("ConditionGroup", ConditionGroupValidator.getInstance(), ConditionGroupTranslator.getInstance()),
+ RULE("Rule", RuleValidator.getInstance(), RuleTranslator.getInstance()),
+ MAPPING_RULES("MappingRules", null, MappingRulesTranslator.getInstance());
+
+ private String elementType;
+ private IRuleElementValidator validator;
+ private IRuleElementTranslator translator;
+
+ public IRuleElementValidator getValidator() {
+ return validator;
+ }
+
+ public IRuleElementTranslator getTranslator() {
+ return translator;
+ }
+
+ RuleEditorElementType(String elementType, IRuleElementValidator validator, IRuleElementTranslator translator) {
+ this.elementType = elementType;
+ this.validator = validator;
+ this.translator = translator;
+ }
+
+ public static RuleEditorElementType getElementTypeByName(String name) {
+ return Arrays.stream(RuleEditorElementType.values()).filter(p -> p.elementType.equalsIgnoreCase(name))
+ .findAny().orElse(null);
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogic.java
new file mode 100644
index 0000000..849ad42
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogic.java
@@ -0,0 +1,149 @@
+package org.onap.sdc.dcae.rule.editor.impl;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.onap.sdc.dcae.errormng.ServiceException;
+import org.onap.sdc.dcae.rule.editor.translators.MappingRulesTranslator;
+import org.onap.sdc.dcae.rule.editor.utils.EmptyStringTranslationSerializer;
+import org.onap.sdc.dcae.rule.editor.validators.RuleValidator;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Component
+public class RulesBusinessLogic {
+
+ protected OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+ private RuleValidator ruleValidator = RuleValidator.getInstance();
+ private MappingRulesTranslator mappingRulesTranslator = MappingRulesTranslator.getInstance();
+ private static Gson gsonTranslator = new GsonBuilder().registerTypeAdapter(String.class, new EmptyStringTranslationSerializer()).enableComplexMapKeySerialization().create();
+
+ public List<ServiceException> validateRule(Rule rule) {
+ List<ResponseFormat> errors = new ArrayList<>();
+ if(ruleValidator.validate(rule, errors))
+ detectAndResolveActionDependencies(rule, errors);
+ return errors.stream().map(r -> r.getRequestError().getServiceException()).collect(Collectors.toList());
+ }
+
+ public List<ServiceException> validateRules(MappingRules rules) {
+ List<ResponseFormat> errors = new ArrayList<>();
+ detectAndResolveRuleDependencies(rules, errors);
+ return errors.stream().map(r -> r.getRequestError().getServiceException()).collect(Collectors.toList());
+ }
+
+ public String translateRules(MappingRules rules, String entryPointPhase, String lastPhase, String runPhase) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Start translating mapping rules");
+ return gsonTranslator.toJson(mappingRulesTranslator.translateToHpJson(rules, entryPointPhase, lastPhase, runPhase));
+ }
+
+ public boolean addOrEditRule(MappingRules rules, Rule rule) {
+ // in case the rule id is passed but the rule doesn't exist on the mapping rule file:
+ if(StringUtils.isNotBlank(rule.getUid()) && !rules.ruleExists(rule))
+ return false;
+ rules.addOrReplaceRule(rule);
+ return true;
+ }
+
+ public Rule deleteRule(MappingRules rules, String ruleUid) {
+ return rules.removeRule(ruleUid);
+ }
+
+ private <T> List<T> detectDependentItemsByDependencyDefinition(Collection<T> allItems, BiFunction<T, Collection<T>, Boolean> dependencyDefinition) {
+ return allItems.stream().filter(i -> dependencyDefinition.apply(i, allItems)).collect(Collectors.toList());
+ }
+
+ // if all dependencies are resolvable returns empty list
+ // else returns list of non resolvable items (circular dependent items)
+ // iterate through all dependentItems removing resolvable items each iteration.
+
+ private <T> List<T> detectCircularDependenciesByDependencyDefinition(List<T> dependentItems, BiFunction<T, Collection<T>, Boolean> dependencyDetector) {
+ while(!CollectionUtils.isEmpty(dependentItems)) {
+ List<T> resolvable = dependentItems.stream()
+ .filter(i -> !dependencyDetector.apply(i, dependentItems))
+ .collect(Collectors.toList());
+ if(CollectionUtils.isEmpty(resolvable))
+ break;
+ dependentItems.removeAll(resolvable);
+ }
+ return dependentItems;
+ }
+
+ private <T> List<T> reorderItemsByDependencyDefinition(Collection<T> allItems, BiFunction<T, T, Boolean> dependencyDetector) {
+ List<T> ordered = new ArrayList<>(allItems);
+ allItems.forEach(i -> {
+ List<T> dependencies = allItems.stream().filter(o -> dependencyDetector.apply(i, o)).collect(Collectors.toList());
+ dependencies.forEach(d -> {
+ if(ordered.indexOf(d) > ordered.indexOf(i)) {
+ ordered.remove(d);
+ ordered.add(ordered.indexOf(i), d);
+ }
+ });
+ });
+ return ordered;
+ }
+
+ private void detectAndResolveActionDependencies(Rule rule, List<ResponseFormat> errors) {
+ List<BaseAction> dependentActions = detectDependentItemsByDependencyDefinition(rule.getActions(), BaseAction::hasDependencies);
+ if(!CollectionUtils.isEmpty(dependentActions)) {
+ List<BaseAction> nonResolvable = detectCircularDependenciesByDependencyDefinition(dependentActions, BaseAction::hasDependencies);
+ if (!CollectionUtils.isEmpty(nonResolvable)) {
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.ACTION_DEPENDENCY, null, nonResolvable.stream().map(BaseAction::getTarget).collect(Collectors.joining(", "))));
+ return;
+ }
+ List<BaseAction> actions = reorderItemsByDependencyDefinition(rule.getActions(), BaseAction::referencesTarget);
+ rule.setActions(actions);
+ }
+ }
+
+ // first identify dependent rules
+ // if no dependencies found return true
+ // if non resolvable dependencies found return false
+ // else reorder and return true
+
+ private void detectAndResolveRuleDependencies(MappingRules rules, List<ResponseFormat> errors) {
+ List<Rule> dependentRules = detectDependentItemsByDependencyDefinition(rules.getRules().values(), Rule::referencesOtherRules);
+ if(!CollectionUtils.isEmpty(dependentRules)) {
+ List<Rule> nonResolvable = detectCircularDependenciesByDependencyDefinition(dependentRules, Rule::referencesOtherRules);
+ if (!CollectionUtils.isEmpty(nonResolvable)) {
+ String nonResolvableRuleIds = nonResolvable.stream().map(Rule::getUid).collect(Collectors.joining(", "));
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.RULE_DEPENDENCY, null, nonResolvableRuleIds, extractDependentActionTargetsFromRules(nonResolvable)));
+ return;
+ }
+ reorderRulesByDependency(rules);
+ }
+ }
+
+ private String extractDependentActionTargetsFromRules(List<Rule> dependentRules) {
+ List<BaseAction> allActions = dependentRules.stream().map(Rule::getActions).flatMap(List::stream).collect(Collectors.toList());
+ // option 1: circular dependency between actions
+ List<BaseAction> nonResolvable = detectCircularDependenciesByDependencyDefinition(allActions, BaseAction::hasDependencies);
+ if(CollectionUtils.isEmpty(nonResolvable))
+ // option 2: circular dependency between rules - collect dependent actions and condition dependencies
+ nonResolvable = dependentRules.stream()
+ .map(r -> r.findDependencies(dependentRules))
+ .flatMap(List::stream)
+ .collect(Collectors.toList());
+ return nonResolvable.stream()
+ .map(BaseAction::getTarget)
+ .collect(Collectors.joining(", "));
+ }
+
+ private void reorderRulesByDependency(MappingRules rules) {
+ List<Rule> ordered = reorderItemsByDependencyDefinition(rules.getRules().values(), Rule::referencesOtherRule);
+ Map<String, Rule> rulesMap = ordered.stream().collect(Collectors.toMap(Rule::getUid, Function.identity(), (u, v) -> {
+ throw new IllegalStateException(String.format("Duplicate key %s", u));
+ }, LinkedHashMap::new));
+ rules.setRules(rulesMap);
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionGroupTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionGroupTranslator.java
new file mode 100644
index 0000000..093c239
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionGroupTranslator.java
@@ -0,0 +1,47 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*;
+import org.onap.sdc.dcae.rule.editor.enums.ConditionTypeEnum;
+import org.onap.sdc.dcae.rule.editor.enums.OperatorTypeEnum;
+import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class ConditionGroupTranslator implements IRuleElementTranslator<ConditionGroup> {
+
+ private static ConditionGroupTranslator conditionGroupTranslator = new ConditionGroupTranslator();
+
+ public static ConditionGroupTranslator getInstance() {
+ return conditionGroupTranslator;
+ }
+
+ private ConditionGroupTranslator(){}
+
+ public Translation translateToHpJson(ConditionGroup conditionGroup) {
+ String clazz = ConditionTypeEnum.getTypeByName(conditionGroup.getType()).getFilterClass();
+ FiltersTranslation translation = new FiltersTranslation(clazz, conditionGroup.getChildren().stream()
+ .map(this::getTranslation)
+ .collect(Collectors.toList()));
+ flattenNestedFilters(translation, clazz);
+ return translation;
+ }
+
+
+ private IRuleElementTranslator getConditionTranslator(BaseCondition condition){
+ return condition instanceof ConditionGroup ? ConditionGroupTranslator.getInstance() :
+ ValidationUtils.validateNotEmpty(OperatorTypeEnum.getTypeByName(((Condition)condition).getOperator()).getModifiedType()) ? FieldConditionTranslator.getInstance() : ConditionTranslator.getInstance();
+ }
+
+ private Translation getTranslation(BaseCondition condition) {
+ return getConditionTranslator(condition).translateToHpJson(condition);
+ }
+
+ private void flattenNestedFilters(FiltersTranslation filtersTranslation, String clazz) {
+ Map<Boolean, List<Translation>> partitioned = filtersTranslation.filters.stream().collect(Collectors.partitioningBy(f -> clazz.equals(((ProcessorTranslation) f).clazz)));
+ filtersTranslation.filters.removeAll(partitioned.get(Boolean.TRUE));
+ filtersTranslation.filters.addAll(partitioned.get(Boolean.TRUE).stream().map(f -> ((FiltersTranslation) f).filters).flatMap(List::stream).collect(Collectors.toList()));
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionTranslator.java
new file mode 100644
index 0000000..f93101b
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionTranslator.java
@@ -0,0 +1,40 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Condition;
+import org.onap.sdc.dcae.rule.editor.enums.ConditionTypeEnum;
+import org.onap.sdc.dcae.rule.editor.enums.OperatorTypeEnum;
+
+import java.util.stream.Collectors;
+
+public class ConditionTranslator implements IRuleElementTranslator<Condition> {
+
+ private static ConditionTranslator conditionTranslator = new ConditionTranslator();
+
+ public static ConditionTranslator getInstance() {
+ return conditionTranslator;
+ }
+
+ private ConditionTranslator(){}
+
+ private class StringFilterTranslation extends ProcessorTranslation {
+ private String string;
+ private String value;
+
+ private StringFilterTranslation(Condition condition, String value){
+ this.clazz = OperatorTypeEnum.getTypeByName(condition.getOperator()).getType();
+ this.string = condition.getLeft();
+ this.value = value;
+ }
+
+ private StringFilterTranslation(Condition condition){
+ this(condition, condition.getRight().get(0));
+ }
+ }
+
+ public Translation translateToHpJson(Condition condition) {
+ return 1 == condition.getRight().size() ? new StringFilterTranslation(condition) : new FiltersTranslation(ConditionTypeEnum.ANY.getFilterClass(), condition.getRight().stream()
+ .map(r -> new StringFilterTranslation(condition, r)).collect(Collectors.toList()));
+ }
+
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/CopyActionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/CopyActionTranslator.java
new file mode 100644
index 0000000..9d02c8e
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/CopyActionTranslator.java
@@ -0,0 +1,47 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseAction;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseAction;
+
+public class CopyActionTranslator<A extends BaseAction> implements IRuleElementTranslator<A>{
+
+ private static CopyActionTranslator copyActionTranslator = new CopyActionTranslator();
+
+ public static CopyActionTranslator getInstance() {
+ return copyActionTranslator;
+ }
+
+ CopyActionTranslator(){}
+
+ public Translation translateToHpJson(A action) {
+ return new CopyActionSetTranslation(action.getTarget(), action.getFromValue());
+ }
+
+ void addToHpJsonProcessors(A action, List<Translation> processors) {
+ processors.add(translateToHpJson(action));
+ }
+
+ public boolean addToHpJsonProcessors(A action, List<Translation> processors, boolean asNewProcessor) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Translating {} action. New Processor: {}", action.getActionType(), asNewProcessor);
+ if(asNewProcessor)
+ addToHpJsonProcessors(action, processors);
+ else
+ ((CopyActionSetTranslation) processors.get(processors.size()-1)).updates.put(action.getTarget(), action.getFromValue());
+ return false;
+ }
+
+ class CopyActionSetTranslation extends ProcessorTranslation {
+ Map<String, String> updates = new LinkedHashMap<>();
+ CopyActionSetTranslation(String target, String from) {
+ clazz = "Set";
+ updates.put(target, from);
+ }
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/DateFormatterTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/DateFormatterTranslator.java
new file mode 100644
index 0000000..89f0def
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/DateFormatterTranslator.java
@@ -0,0 +1,49 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import java.util.List;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.DateFormatterAction;
+
+public class DateFormatterTranslator extends CopyActionTranslator<DateFormatterAction> {
+
+ private static DateFormatterTranslator dateFormatterTranslator = new DateFormatterTranslator();
+
+ public static DateFormatterTranslator getInstance() {
+ return dateFormatterTranslator;
+ }
+
+ private DateFormatterTranslator(){}
+
+ private class DateFormatterTranslation extends ProcessorTranslation {
+ private String fromFormat;
+ private String fromTz;
+ private String toField;
+ private String toFormat;
+ private String toTz;
+ private String value;
+
+ private DateFormatterTranslation(DateFormatterAction action){
+ clazz = "DateFormatter";
+ fromFormat = action.getFromFormat();
+ fromTz = action.getFromTz();
+ toField = action.getTarget();
+ toFormat = action.getToFormat();
+ toTz = action.getToTz();
+ value = action.getFromValue();
+ }
+ }
+
+ @Override
+ public boolean addToHpJsonProcessors(DateFormatterAction action, List<Translation> processors, boolean asNewProcessor) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Translating date formatter action");
+ addToHpJsonProcessors(action, processors);
+ return true;
+ }
+
+ @Override
+ public Translation translateToHpJson(DateFormatterAction action){
+ return new DateFormatterTranslation(action);
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/FieldConditionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/FieldConditionTranslator.java
new file mode 100644
index 0000000..ef2949e
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/FieldConditionTranslator.java
@@ -0,0 +1,43 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Condition;
+import org.onap.sdc.dcae.rule.editor.enums.OperatorTypeEnum;
+
+import java.util.List;
+
+public class FieldConditionTranslator implements IRuleElementTranslator<Condition> {
+
+ private static FieldConditionTranslator fieldConditionTranslator = new FieldConditionTranslator();
+
+ public static FieldConditionTranslator getInstance() {
+ return fieldConditionTranslator;
+ }
+
+ private FieldConditionTranslator(){}
+
+ private class FieldFilterTranslation extends ProcessorTranslation {
+ private String field;
+ private String value;
+
+ private FieldFilterTranslation(Condition condition) {
+ clazz = OperatorTypeEnum.getTypeByName(condition.getOperator()).getType();
+ field = condition.getLeft();
+ value = condition.getRight().get(0);
+ }
+ }
+
+ private class MultiFieldFilterTranslation extends ProcessorTranslation {
+ private String field;
+ private List<String> values;
+
+ private MultiFieldFilterTranslation(Condition condition) {
+ field = condition.getLeft();
+ values = condition.getRight();
+ clazz = OperatorTypeEnum.getTypeByName(condition.getOperator()).getModifiedType();
+ }
+ }
+
+ public Translation translateToHpJson(Condition condition) {
+ return 1 == condition.getRight().size() ? new FieldFilterTranslation(condition) : new MultiFieldFilterTranslation(condition);
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/IRuleElementTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/IRuleElementTranslator.java
new file mode 100644
index 0000000..dac818d
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/IRuleElementTranslator.java
@@ -0,0 +1,50 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import com.google.gson.annotations.SerializedName;
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface IRuleElementTranslator<T> {
+
+ OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ Translation translateToHpJson(T element);
+
+ abstract class Translation {
+ }
+
+ class ProcessorTranslation extends Translation {
+ @SerializedName("class")
+ protected String clazz;
+ }
+
+
+ class FiltersTranslation extends ProcessorTranslation {
+ protected List<Translation> filters;
+
+ protected FiltersTranslation(String clazz, List<Translation> filters) {
+ this.clazz = clazz;
+ this.filters = filters;
+ }
+ }
+
+ class RuleTranslation extends Translation {
+ protected String phase;
+ protected Translation filter;
+ protected List<Translation> processors = new ArrayList<>();
+ }
+
+ class RunPhaseProcessorsTranslation extends ProcessorTranslation {
+ protected String phase;
+
+ protected RunPhaseProcessorsTranslation(String runPhase){
+ clazz ="RunPhase";
+ phase = runPhase;
+ }
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MapActionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MapActionTranslator.java
new file mode 100644
index 0000000..922312e
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MapActionTranslator.java
@@ -0,0 +1,50 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+
+import java.util.List;
+import java.util.Map;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.MapAction;
+
+public class MapActionTranslator extends CopyActionTranslator<MapAction> {
+
+ private static MapActionTranslator mapActionTranslator = new MapActionTranslator();
+
+ public static MapActionTranslator getInstance() {
+ return mapActionTranslator;
+ }
+
+ private MapActionTranslator(){}
+
+ private class MapActionTranslation extends ProcessorTranslation {
+
+ private Map<String, String> map;
+ private String field;
+ private String toField;
+ @SerializedName("default")
+ private String Default;
+
+ private MapActionTranslation(MapAction action) {
+ clazz = "MapAlarmValues";
+ Default = action.getMapDefaultValue();
+ field = action.getFromValue();
+ toField = action.getTarget();
+ map = action.transformToMap();
+ }
+ }
+
+ @Override
+ public Translation translateToHpJson(MapAction action) {
+ return new MapActionTranslation(action);
+ }
+
+ @Override
+ public boolean addToHpJsonProcessors(MapAction action, List<Translation> processors, boolean asNewProcessor) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Translating map action");
+ addToHpJsonProcessors(action, processors);
+ return true;
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MappingRulesTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MappingRulesTranslator.java
new file mode 100644
index 0000000..0164446
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MappingRulesTranslator.java
@@ -0,0 +1,69 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.MappingRules;
+
+public class MappingRulesTranslator implements IRuleElementTranslator<MappingRules> {
+
+ private static MappingRulesTranslator mappingRulesTranslator = new MappingRulesTranslator();
+
+ public static MappingRulesTranslator getInstance() {
+ return mappingRulesTranslator;
+ }
+
+ private MappingRulesTranslator() {
+ }
+
+ private RuleTranslator ruleTranslator = RuleTranslator.getInstance();
+
+ public Translation translateToHpJson(MappingRules mappingRules) {
+ return new MappingRulesTranslation(mappingRules);
+ }
+
+ public Translation translateToHpJson(MappingRules mappingRules, String entryPointPhaseName, String lastPhaseName, String runPhase) {
+ // 1806 US349308 assign Vfcmt name as rule phaseName
+ mappingRules.getRules().forEach((k,v) -> v.setPhase(runPhase));
+ return new MappingRulesTranslation(mappingRules, entryPointPhaseName, lastPhaseName, runPhase);
+ }
+
+ private class MappingRulesTranslation extends Translation {
+
+ private List<Translation> processing;
+
+ private MappingRulesTranslation(MappingRules mappingRules) {
+ processing = mappingRules.getRules().values().stream().map(ruleTranslator::translateToHpJson).collect(Collectors.toList());
+ }
+
+ private MappingRulesTranslation(MappingRules mappingRules, String entryPointPhaseName, String lastPhaseName, String runPhase) {
+ this(mappingRules);
+ //hardcoded entry point processor
+ processing.add(0, new RunPhaseRuleTranslation(entryPointPhaseName, runPhase));
+ //hardcoded map_publish processor
+ processing.add(new RunPhaseRuleTranslation(runPhase, lastPhaseName));
+ }
+ }
+
+ private class RunPhaseRuleTranslation extends RuleTranslation {
+
+ private RunPhaseRuleTranslation(String phaseName, String runPhase) {
+ phase = phaseName;
+ if ("snmp_map".equals(phaseName))
+ processors.add(new SnmpConvertor());
+ processors.add(new RunPhaseProcessorsTranslation(runPhase));
+ }
+ }
+
+ // hardcoded SNMP processor
+ private class SnmpConvertor extends ProcessorTranslation {
+ private String array = "varbinds";
+ private String datacolumn = "varbind_value";
+ private String keycolumn = "varbind_oid";
+
+ private SnmpConvertor() {
+ clazz = "SnmpConvertor";
+ }
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RegexActionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RegexActionTranslator.java
new file mode 100644
index 0000000..c49a04e
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RegexActionTranslator.java
@@ -0,0 +1,44 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import java.util.List;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseAction;
+
+public class RegexActionTranslator extends CopyActionTranslator<BaseAction> {
+
+ private static RegexActionTranslator regexActionTranslator = new RegexActionTranslator();
+
+ public static RegexActionTranslator getInstance() {
+ return regexActionTranslator;
+ }
+
+ private RegexActionTranslator(){}
+
+ private class RegexCopyActionTranslation extends ProcessorTranslation {
+
+ private String regex;
+ private String field;
+ private String value;
+
+ private RegexCopyActionTranslation(BaseAction action) {
+ clazz = "ExtractText";
+ regex = action.getRegexValue();
+ field = action.getTarget();
+ value = action.getFromValue();
+ }
+ }
+
+ @Override
+ public boolean addToHpJsonProcessors(BaseAction action, List<Translation> processors, boolean asNewProcessor) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Translating copy action as regex action");
+ addToHpJsonProcessors(action, processors);
+ return true;
+ }
+
+ @Override
+ public Translation translateToHpJson(BaseAction action) {
+ return new RegexCopyActionTranslation(action);
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RuleTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RuleTranslator.java
new file mode 100644
index 0000000..f7dea47
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RuleTranslator.java
@@ -0,0 +1,51 @@
+package org.onap.sdc.dcae.rule.editor.translators;
+
+import com.google.gson.Gson;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*;
+import org.onap.sdc.dcae.rule.editor.enums.OperatorTypeEnum;
+import org.onap.sdc.dcae.rule.editor.enums.RuleEditorElementType;
+import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils;
+
+public class RuleTranslator implements IRuleElementTranslator<Rule> {
+
+ private static RuleTranslator ruleTranslator = new RuleTranslator();
+
+ public static RuleTranslator getInstance() {
+ return ruleTranslator;
+ }
+
+ private RuleTranslator() {
+ }
+
+ private class ActionRuleTranslation extends RuleTranslation {
+ private ActionRuleTranslation(Rule rule) {
+ phase = rule.getPhase();
+ filter = rule.isConditionalRule() ? getConditionTranslator(rule.getCondition()).translateToHpJson(rule.getCondition()) : null;
+ boolean asNewProcessor = true;
+ for (BaseAction action : rule.getActions()) {
+ // consecutive copy actions are aggregated into a single processor
+ asNewProcessor = getActionTranslator(action).addToHpJsonProcessors(action, processors, asNewProcessor);
+ }
+ }
+ }
+
+ public Translation translateToHpJson(Rule rule) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Start translating rule {}", rule.getUid());
+ Translation translation = new ActionRuleTranslation(rule);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Finished translation for rule {}. Result: {}", rule.getUid(), new Gson().toJson(translation));
+ return translation;
+ }
+
+ private IRuleElementTranslator getConditionTranslator(BaseCondition condition){
+ return condition instanceof ConditionGroup ? ConditionGroupTranslator.getInstance() :
+ ValidationUtils.validateNotEmpty(OperatorTypeEnum.getTypeByName(((Condition)condition).getOperator()).getModifiedType()) ? FieldConditionTranslator.getInstance() : ConditionTranslator.getInstance();
+ }
+
+ private CopyActionTranslator getActionTranslator(BaseAction action) {
+ ActionTypeEnum type = ActionTypeEnum.getTypeByName(action.getActionType());
+ if(ActionTypeEnum.COPY == type && ValidationUtils.validateNotEmpty(action.getRegexValue()))
+ return RegexActionTranslator.getInstance();
+ return (CopyActionTranslator)RuleEditorElementType.getElementTypeByName(type.getType()).getTranslator();
+ }
+} \ No newline at end of file
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/EmptyStringTranslationSerializer.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/EmptyStringTranslationSerializer.java
new file mode 100644
index 0000000..c65076f
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/EmptyStringTranslationSerializer.java
@@ -0,0 +1,14 @@
+package org.onap.sdc.dcae.rule.editor.utils;
+
+import com.google.gson.*;
+
+import java.lang.reflect.Type;
+
+public class EmptyStringTranslationSerializer implements JsonSerializer<String> {
+
+ public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {
+ if("\"\"".equals(src))
+ return new JsonPrimitive("");
+ return new JsonPrimitive(src);
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/RulesPayloadUtils.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/RulesPayloadUtils.java
new file mode 100644
index 0000000..33f9e92
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/RulesPayloadUtils.java
@@ -0,0 +1,38 @@
+package org.onap.sdc.dcae.rule.editor.utils;
+
+import java.util.List;
+
+import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact;
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+
+public class RulesPayloadUtils {
+ private static Gson gson = new GsonBuilder().serializeNulls()
+ .registerTypeAdapter(BaseAction.class, new ActionDeserializer())
+ .registerTypeAdapter(BaseCondition.class, new ConditionDeserializer()).create();
+
+ public static Rule parsePayloadToRule(String payload) throws JsonParseException {
+ return gson.fromJson(payload, Rule.class);
+ }
+
+ public static MappingRules parseMappingRulesArtifactPayload(String payload) throws JsonParseException {
+ return gson.fromJson(payload, MappingRules.class);
+ }
+
+ public static SchemaInfo extractInfoFromDescription(Artifact rulesArtifact) {
+ try {
+ return gson.fromJson(rulesArtifact.getArtifactDescription(), SchemaInfo.class);
+ }catch (JsonParseException e) {
+ return null;
+ }
+ }
+
+ public static String buildSchemaAndRulesResponse(String payload, List<EventTypeDefinitionUI> schema) {
+ return "{\"schema\":"+gson.toJson(schema)+","+payload.replaceFirst("\\{", "");
+ }
+
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/ValidationUtils.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/ValidationUtils.java
new file mode 100644
index 0000000..7a3b206
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/ValidationUtils.java
@@ -0,0 +1,20 @@
+package org.onap.sdc.dcae.rule.editor.utils;
+
+import org.apache.commons.lang3.StringUtils;
+
+
+public class ValidationUtils {
+
+ private static final String EXPLICIT_EMPTY = "\"\"";
+
+ public static boolean validateNotEmpty(String value){
+ return StringUtils.isNoneBlank(value);
+ }
+
+ public static boolean validateTargetField(String value) {
+ return validateNotEmpty(value) && !EXPLICIT_EMPTY.equals(value);
+ }
+
+
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ActionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ActionValidator.java
new file mode 100644
index 0000000..3eb0eb5
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ActionValidator.java
@@ -0,0 +1,40 @@
+package org.onap.sdc.dcae.rule.editor.validators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseAction;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils;
+
+import java.util.List;
+
+public class ActionValidator<A extends BaseAction> implements IRuleElementValidator<A> {
+
+ private static ActionValidator actionValidator = new ActionValidator();
+
+ public static ActionValidator getInstance() {
+ return actionValidator;
+ }
+
+ ActionValidator(){}
+
+ public boolean validate(A action, List<ResponseFormat> errors) {
+
+ // validate from is populated
+ boolean valid = validateFromValue(action, errors);
+ //validate target is populated
+ if (!ValidationUtils.validateTargetField(action.getTarget())) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "target", action.getActionType(), action.getTarget()));
+ }
+ return valid;
+ }
+
+ protected boolean validateFromValue(A action, List<ResponseFormat> errors) {
+ if(!ValidationUtils.validateNotEmpty(action.getFromValue())) {
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "from", action.getActionType(), action.getTarget()));
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConcatActionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConcatActionValidator.java
new file mode 100644
index 0000000..965c898
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConcatActionValidator.java
@@ -0,0 +1,29 @@
+package org.onap.sdc.dcae.rule.editor.validators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseAction;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils;
+
+import java.util.List;
+
+public class ConcatActionValidator extends ActionValidator<BaseAction> {
+
+ private static ConcatActionValidator concatActionValidator = new ConcatActionValidator();
+
+ public static ConcatActionValidator getInstance() {
+ return concatActionValidator;
+ }
+
+ private ConcatActionValidator(){}
+
+ @Override
+ protected boolean validateFromValue(BaseAction action, List<ResponseFormat> errors) {
+ if(!ValidationUtils.validateNotEmpty(action.getFromValue()) || 2 > action.getFromValues().size()) {
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_CONCAT_VALUE, null, action.getTarget()));
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionGroupValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionGroupValidator.java
new file mode 100644
index 0000000..995a817
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionGroupValidator.java
@@ -0,0 +1,40 @@
+package org.onap.sdc.dcae.rule.editor.validators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.ConditionGroup;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.onap.sdc.dcae.rule.editor.enums.ConditionTypeEnum;
+import org.onap.sdc.dcae.rule.editor.enums.RuleEditorElementType;
+import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+public class ConditionGroupValidator implements IRuleElementValidator<ConditionGroup> {
+
+ private static ConditionGroupValidator conditionGroupValidator = new ConditionGroupValidator();
+
+ public static ConditionGroupValidator getInstance() {
+ return conditionGroupValidator;
+ }
+
+ private ConditionGroupValidator(){}
+
+ public boolean validate(ConditionGroup condition, List<ResponseFormat> errors) {
+ boolean valid = true;
+ if(!ValidationUtils.validateNotEmpty(condition.getType()) || null == ConditionTypeEnum.getTypeByName(condition.getType())) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_GROUP_CONDITION, null, condition.getType()));
+ }
+ if(CollectionUtils.isEmpty(condition.getChildren()) || 2 > condition.getChildren().size()) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_CONDITION_ITEM, null, null));
+ } else {
+ valid = condition.getChildren().stream()
+ .map(c -> RuleEditorElementType.getElementTypeByName(c.getClass().getSimpleName()).getValidator().validate(c, errors))
+ .reduce(true, (x,y) -> x && y) && valid;
+ }
+ return valid;
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionValidator.java
new file mode 100644
index 0000000..1b4ae94
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionValidator.java
@@ -0,0 +1,40 @@
+package org.onap.sdc.dcae.rule.editor.validators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Condition;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.onap.sdc.dcae.rule.editor.enums.OperatorTypeEnum;
+import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+public class ConditionValidator implements IRuleElementValidator<Condition> {
+
+ private static ConditionValidator conditionValidator = new ConditionValidator();
+
+ public static ConditionValidator getInstance() {
+ return conditionValidator;
+ }
+
+ private ConditionValidator(){}
+
+ public boolean validate(Condition condition, List<ResponseFormat> errors) {
+ boolean valid = true;
+ if(!ValidationUtils.validateNotEmpty(condition.getLeft())) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_OPERAND, null, "left"));
+ }
+ if(CollectionUtils.isEmpty(condition.getRight())) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_OPERAND, null, "right"));
+ }
+ if(!ValidationUtils.validateNotEmpty(condition.getOperator()) || null == OperatorTypeEnum.getTypeByName(condition.getOperator())) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_OPERATOR, null, condition.getOperator()));
+ }
+ return valid;
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/DateFormatterValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/DateFormatterValidator.java
new file mode 100644
index 0000000..d5ec0fc
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/DateFormatterValidator.java
@@ -0,0 +1,41 @@
+package org.onap.sdc.dcae.rule.editor.validators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.DateFormatterAction;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils;
+
+import java.util.List;
+
+public class DateFormatterValidator extends ActionValidator<DateFormatterAction> {
+ private static DateFormatterValidator dateFormatterValidator = new DateFormatterValidator();
+
+ public static DateFormatterValidator getInstance() {
+ return dateFormatterValidator;
+ }
+
+ private DateFormatterValidator(){}
+
+ @Override
+ public boolean validate(DateFormatterAction action, List<ResponseFormat> errors) {
+ boolean valid = super.validate(action, errors);
+ if(!ValidationUtils.validateNotEmpty(action.getFromFormat())){
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "from format", action.getActionType(), action.getTarget()));
+ }
+ if(!ValidationUtils.validateNotEmpty(action.getFromTz())){
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "from timezone", action.getActionType(), action.getTarget()));
+ }
+ if(!ValidationUtils.validateNotEmpty(action.getToFormat())){
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "to format", action.getActionType(), action.getTarget()));
+ }
+ if(!ValidationUtils.validateNotEmpty(action.getToTz())){
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "to timezone", action.getActionType(), action.getTarget()));
+ }
+ return valid;
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/IRuleElementValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/IRuleElementValidator.java
new file mode 100644
index 0000000..dd1eaf4
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/IRuleElementValidator.java
@@ -0,0 +1,9 @@
+package org.onap.sdc.dcae.rule.editor.validators;
+
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+
+import java.util.List;
+
+public interface IRuleElementValidator <T> {
+ boolean validate(T element, List<ResponseFormat> errors);
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MapActionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MapActionValidator.java
new file mode 100644
index 0000000..8cbcaa8
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MapActionValidator.java
@@ -0,0 +1,49 @@
+package org.onap.sdc.dcae.rule.editor.validators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.MapAction;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+public class MapActionValidator extends ActionValidator<MapAction> {
+
+ private static MapActionValidator mapActionValidator = new MapActionValidator();
+
+ public static MapActionValidator getInstance() {
+ return mapActionValidator;
+ }
+
+ private MapActionValidator(){}
+
+ @Override
+ public boolean validate(MapAction action, List<ResponseFormat> errors) {
+ boolean valid = super.validate(action, errors);
+ if (action.getMap() == null || CollectionUtils.isEmpty(action.getMapValues())) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ENTRY, null, action.getTarget()));
+ } else {
+ if (action.mapHasDefault() && !ValidationUtils.validateNotEmpty(action.getMapDefaultValue())) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_DEFAULT_VALUE, null, action.getTarget()));
+ }
+ try {
+ if (!validateMapValues(action)) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ENTRY, null, action.getTarget()));
+ }
+ } catch (IllegalStateException err) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.DUPLICATE_KEY, null));
+ }
+ }
+ return valid;
+ }
+
+ private boolean validateMapValues(MapAction action) {
+ return action.transformToMap().entrySet().stream().noneMatch(p -> !ValidationUtils.validateNotEmpty(p.getKey()) || !ValidationUtils.validateNotEmpty(p.getValue()));
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/RuleValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/RuleValidator.java
new file mode 100644
index 0000000..371d1e9
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/RuleValidator.java
@@ -0,0 +1,56 @@
+package org.onap.sdc.dcae.rule.editor.validators;
+
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.ActionTypeEnum;
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseAction;
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseCondition;
+import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Rule;
+import org.onap.sdc.dcae.errormng.ActionStatus;
+import org.onap.sdc.dcae.errormng.ErrConfMgr;
+import org.onap.sdc.dcae.errormng.ResponseFormat;
+import org.onap.sdc.dcae.errormng.ServiceException;
+import org.onap.sdc.dcae.rule.editor.enums.RuleEditorElementType;
+import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+public class RuleValidator implements IRuleElementValidator<Rule> {
+
+ private static RuleValidator ruleValidator = new RuleValidator();
+
+ public static RuleValidator getInstance() {
+ return ruleValidator;
+ }
+
+ private RuleValidator(){}
+
+
+ public boolean validate(Rule rule, List<ResponseFormat> errors) {
+ boolean valid = true;
+ if(rule.isConditionalRule())
+ valid = getConditionValidator(rule.getCondition()).validate(rule.getCondition(), errors);
+ if(!ValidationUtils.validateNotEmpty(rule.getDescription())) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_RULE_DESCRIPTION, null, null));
+ }
+ if(CollectionUtils.isEmpty(rule.getActions())) {
+ valid = false;
+ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION, null, null));
+ } else {
+ valid = rule.getActions().stream()
+ .map(a -> getActionValidator(a).validate(a, errors))
+ .reduce(true, (x,y) -> x && y) && valid;
+ }
+ return valid;
+ }
+
+
+ private IRuleElementValidator getActionValidator(BaseAction action) {
+ ActionTypeEnum type = ActionTypeEnum.getTypeByName(action.getActionType());
+ return RuleEditorElementType.getElementTypeByName(type.getType()).getValidator();
+ }
+
+ private IRuleElementValidator getConditionValidator(BaseCondition condition) {
+ return RuleEditorElementType.getElementTypeByName(condition.getClass().getSimpleName()).getValidator();
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/EventListenerDefinition.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/EventListenerDefinition.java
new file mode 100644
index 0000000..cc5bec1
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/EventListenerDefinition.java
@@ -0,0 +1,101 @@
+package org.onap.sdc.dcae.ves;
+
+import com.google.gson.Gson;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+public class EventListenerDefinition extends VesDataTypeDefinition {
+
+ public static final String EVENT_ROOT = "event";
+ private String $schema;
+ private Map<String, VesDataTypeDefinition> definitions;
+
+ public String get$schema() {
+ return $schema;
+ }
+
+ public void set$schema(String $schema) {
+ this.$schema = $schema;
+ }
+
+ public Map<String, VesDataTypeDefinition> getDefinitions() {
+ return definitions;
+ }
+
+ public void setDefinitions(Map<String, VesDataTypeDefinition> definitions) {
+ this.definitions = definitions;
+ }
+
+ // returns error message detailing unresolvable types - or null (success)
+ public String resolveRefTypes() {
+
+ Predicate<Map.Entry<String, VesDataTypeDefinition>> isFullyResolved = dt -> !dt.getValue().containsAnyReferenceItem();
+ Map<String, VesDataTypeDefinition> resolved = definitions.entrySet().stream()
+ .filter(isFullyResolved)
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+
+ int initialUnresolvedItems = -1;
+ int remainingUnresolvedItems = 0;
+
+ while (resolved.size() != definitions.size() && initialUnresolvedItems != remainingUnresolvedItems) {
+ initialUnresolvedItems = definitions.size() - resolved.size();
+ definitions.entrySet().forEach(definition -> {
+ if (!resolved.containsKey(definition.getKey()) && definition.getValue().isResolvable(resolved)) {
+ definition.getValue().resolveAllReferences(resolved);
+ resolved.put(definition.getKey(), definition.getValue());
+ }
+ });
+ remainingUnresolvedItems = definitions.size() - resolved.size();
+ }
+
+ if (resolved.size() != definitions.size()) {
+ definitions.keySet().removeAll(resolved.keySet());
+ return constructErrorMessage(definitions.keySet());
+ }
+ return resolveRootRefTypes();
+
+ }
+
+ private String constructErrorMessage(Set<String> unresolvable) {
+ return "the following definitions containing unresolvable references: " + new Gson().toJson(unresolvable);
+ }
+
+ private String resolveRootRefTypes() {
+ Set<String> unresolvable = new HashSet<>();
+ getProperties().forEach((k, v) -> {
+ if (isResolvable(definitions))
+ resolveAllReferences(definitions);
+ else
+ unresolvable.add(k);
+ });
+ return unresolvable.isEmpty() ? null : constructErrorMessage(unresolvable);
+
+ }
+
+ @Override
+ public String validate() {
+ String error = getProperties().containsKey(EVENT_ROOT) ? null : "schema not containing property: event";
+ if (StringUtils.isBlank(error))
+ error = super.validate();
+ if (StringUtils.isBlank(error))
+ error = validateDefinitions();
+ return error;
+ }
+
+ private String validateDefinitions() {
+ String error = null;
+ for (VesDataTypeDefinition def : definitions.values()) {
+ if (StringUtils.isBlank(error))
+ error = def.validate();
+ else
+ break;
+ }
+ return error;
+ }
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesDataItemsDefinition.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesDataItemsDefinition.java
new file mode 100644
index 0000000..ad1b2f9
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesDataItemsDefinition.java
@@ -0,0 +1,9 @@
+package org.onap.sdc.dcae.ves;
+
+import java.util.ArrayList;
+
+// json 'items' value can be either a single object or an array. customized POJO will always be an array
+public class VesDataItemsDefinition extends ArrayList<VesDataTypeDefinition> {
+
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesDataTypeDefinition.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesDataTypeDefinition.java
new file mode 100644
index 0000000..5465d62
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesDataTypeDefinition.java
@@ -0,0 +1,270 @@
+package org.onap.sdc.dcae.ves;
+
+import com.google.gson.JsonElement;
+import com.google.gson.annotations.SerializedName;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.*;
+
+public class VesDataTypeDefinition {
+
+ private static final String jsonReferencePrefix = "#/definitions/";
+ private String type;
+ private String description;
+ private String format;
+ private String title;
+ private Map<String, VesDataTypeDefinition> properties;
+ private List<String> required = new ArrayList<>();
+ @SerializedName("enum")
+ private List<String> enums;
+ @SerializedName("default")
+ private JsonElement defaultValue;
+ private VesDataItemsDefinition items;
+ @SerializedName("$ref")
+ private String ref;
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getFormat() {
+ return format;
+ }
+
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public Map<String, VesDataTypeDefinition> getProperties() {
+ return properties;
+ }
+
+ public void setProperties(Map<String, VesDataTypeDefinition> properties) {
+ this.properties = properties;
+ }
+
+ public List<String> getRequired() {
+ return required;
+ }
+
+ public void setRequired(List<String> required) {
+ this.required = required;
+ }
+
+ public List<String> getEnums() {
+ return enums;
+ }
+
+ public void setEnums(List<String> enums) {
+ this.enums = enums;
+ }
+
+ public JsonElement getDefaultValue() {
+ return defaultValue;
+ }
+
+ public void setDefaultValue(JsonElement defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+ public VesDataItemsDefinition getItems() {
+ return items;
+ }
+
+ public void setItems(VesDataItemsDefinition items) {
+ this.items = items;
+ }
+
+ public String getRef() {
+ return ref;
+ }
+
+ public void setRef(String ref) {
+ this.ref = ref;
+ }
+
+ protected boolean hasReference() {
+ return StringUtils.isNotBlank(getRef());
+ }
+
+ protected boolean itemsContainReference() {
+ return CollectionUtils.isNotEmpty(getItems()) && getItems().stream().anyMatch(VesDataTypeDefinition::containsAnyReferenceItem);
+ }
+
+ protected boolean propertiesContainReference() {
+ return MapUtils.isNotEmpty(getProperties()) && getProperties().values().stream().anyMatch(VesDataTypeDefinition::containsAnyReferenceItem);
+ }
+
+ protected boolean containsAnyReferenceItem() {
+ return hasReference() || itemsContainReference() || propertiesContainReference();
+ }
+
+ protected String getJsonRefPointer() {
+ return getRef().replace(jsonReferencePrefix, "");
+ }
+
+ private void addReferenceItem(Set<String> allRefs) {
+ if (hasReference()) {
+ allRefs.add(getJsonRefPointer());
+ }
+ }
+
+ private Set<String> extractAllReferenceTokens() {
+ Set<String> allRefs = new HashSet<>();
+ extractReferenceTokens(allRefs);
+ return allRefs;
+ }
+
+ private void extractReferenceTokens(Set<String> allRefs) {
+
+ addReferenceItem(allRefs);
+ if (itemsContainReference()) {
+ getItems().forEach(item -> item.extractReferenceTokens(allRefs));
+ }
+ if (propertiesContainReference()) {
+ getProperties().values().forEach(property -> property.extractReferenceTokens(allRefs));
+ }
+ }
+
+ protected boolean isResolvable(Map<String, VesDataTypeDefinition> resolvedTypes) {
+ return resolvedTypes.keySet().containsAll(extractAllReferenceTokens());
+ }
+
+ private void resolveReference(Map<String, VesDataTypeDefinition> resolvedTypes) {
+ if (hasReference()) {
+ VesDataTypeDefinition other = resolvedTypes.get(getJsonRefPointer());
+ setType(other.getType());
+ setRef(other.getRef());
+ setDefaultValue(other.getDefaultValue());
+ setDescription(other.getDescription());
+ setEnums(other.getEnums());
+ setProperties(other.getProperties());
+ setFormat(other.getFormat());
+ setRequired(other.getRequired());
+ setItems(other.getItems());
+ setTitle(other.getTitle());
+ }
+ }
+
+ private void resolveItemReferences(Map<String, VesDataTypeDefinition> resolvedTypes) {
+ if (itemsContainReference()) {
+ for (VesDataTypeDefinition item : getItems()) {
+ item.resolveAllReferences(resolvedTypes);
+ }
+ }
+ }
+
+ private void resolvePropertyReferences(Map<String, VesDataTypeDefinition> resolvedTypes) {
+ if (propertiesContainReference()) {
+ for (VesDataTypeDefinition property : getProperties().values()) {
+ property.resolveAllReferences(resolvedTypes);
+ }
+ }
+ }
+
+ // the reference resolver is called on each VesDataTypeDefinition after it passes the 'isResolvable' validation, affirming that all its references(direct/properties/items) point to a resolved VesDataTypeDefinition (has no references)
+ protected void resolveAllReferences(Map<String, VesDataTypeDefinition> resolvedTypes) {
+ resolveReference(resolvedTypes);
+ resolveItemReferences(resolvedTypes);
+ resolvePropertyReferences(resolvedTypes);
+ }
+
+ private String validateType() {
+ return null == type? null : VesSimpleTypesEnum.getSimpleTypes().contains(type) ? null : "invalid type declaration: " + type;
+ }
+
+ private String validateRequired() {
+ String invalid = null == type? null : !type.equals(VesSimpleTypesEnum.OBJECT.getType()) ? null : required.stream().filter(r -> !properties.keySet().contains(r)).findAny().orElse(null);
+ return StringUtils.isBlank(invalid) ? invalid : "invalid required entry: " + invalid;
+ }
+
+ // returns error message detailing invalid 'type' or 'required' fields (null for success)
+ protected String validate() {
+ String error = validateType();
+ if (StringUtils.isBlank(error))
+ error = validateRequired();
+ if (StringUtils.isBlank(error) && CollectionUtils.isNotEmpty(items))
+ error = validateItems();
+ if(StringUtils.isBlank(error) && MapUtils.isNotEmpty(properties))
+ error = validateProperties();
+ return error;
+ }
+
+ private String validateItems(){
+ String error = null;
+ for (VesDataTypeDefinition def : items) {
+ if (StringUtils.isBlank(error))
+ error = def.validate();
+ else
+ break;
+ }
+ return error;
+ }
+
+ private String validateProperties(){
+ String error = null;
+ for (VesDataTypeDefinition def : properties.values()) {
+ if (StringUtils.isBlank(error))
+ error = def.validate();
+ else
+ break;
+ }
+ return error;
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (null == obj || getClass() != obj.getClass())
+ return false;
+ VesDataTypeDefinition other = (VesDataTypeDefinition) obj;
+ return Objects.equals(type, other.type) &&
+ Objects.equals(description, other.description) &&
+ Objects.equals(format, other.format) &&
+ Objects.equals(title, other.title) &&
+ Objects.equals(required, other.required) &&
+ Objects.equals(enums, other.enums) &&
+ Objects.equals(defaultValue, other.defaultValue) &&
+ Objects.equals(items, other.items) &&
+ Objects.equals(properties, other.properties) &&
+ Objects.equals(ref, other.ref);
+ }
+
+ @Override public int hashCode() {
+ int result = type != null ? type.hashCode() : 0;
+ result = 31 * result + (description != null ? description.hashCode() : 0);
+ result = 31 * result + (format != null ? format.hashCode() : 0);
+ result = 31 * result + (title != null ? title.hashCode() : 0);
+ result = 31 * result + (properties != null ? properties.hashCode() : 0);
+ result = 31 * result + (required != null ? required.hashCode() : 0);
+ result = 31 * result + (enums != null ? enums.hashCode() : 0);
+ result = 31 * result + (defaultValue != null ? defaultValue.hashCode() : 0);
+ result = 31 * result + (items != null ? items.hashCode() : 0);
+ result = 31 * result + (ref != null ? ref.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesJsonDeserializer.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesJsonDeserializer.java
new file mode 100644
index 0000000..f5cfd2a
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesJsonDeserializer.java
@@ -0,0 +1,20 @@
+package org.onap.sdc.dcae.ves;
+
+import com.google.gson.*;
+
+import java.lang.reflect.Type;
+
+// json 'items' value can be either a single object or an array. customized POJO will always be an array
+public class VesJsonDeserializer implements JsonDeserializer<VesDataItemsDefinition> {
+ @Override
+ public VesDataItemsDefinition deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
+
+ if(json instanceof JsonArray){
+ return new Gson().fromJson(json, VesDataItemsDefinition.class);
+ }
+
+ VesDataItemsDefinition items = new VesDataItemsDefinition();
+ items.add(new Gson().fromJson(json, VesDataTypeDefinition.class));
+ return items;
+ }
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesSimpleTypesEnum.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesSimpleTypesEnum.java
new file mode 100644
index 0000000..0606a6d
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesSimpleTypesEnum.java
@@ -0,0 +1,26 @@
+package org.onap.sdc.dcae.ves;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public enum VesSimpleTypesEnum {
+
+ ARRAY("array"), BOOLEAN("boolean"), INTEGER("integer"), NULL("null"), NUMBER("number"), OBJECT("object"), STRING("string");
+
+ private String type;
+
+ public String getType() {
+ return type;
+ }
+
+ private VesSimpleTypesEnum(String type) {
+ this.type = type;
+ }
+
+ public static Set<String> getSimpleTypes() {
+ return Arrays.stream(VesSimpleTypesEnum.values()).map(t -> t.getType()).collect(Collectors.toSet());
+ }
+
+
+}
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesStructureLoader.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesStructureLoader.java
new file mode 100644
index 0000000..cb8a16c
--- /dev/null
+++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/ves/VesStructureLoader.java
@@ -0,0 +1,115 @@
+package org.onap.sdc.dcae.ves;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.io.*;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Service("vesstructureloader")
+public class VesStructureLoader {
+
+
+
+ private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ private static Map<String, EventListenerDefinition> eventListeners = new HashMap<>();
+ private static final Type type = new TypeToken<VesDataItemsDefinition>(){}.getType();
+ private static final Gson gson = new GsonBuilder().registerTypeAdapter(type, new VesJsonDeserializer()).create();
+ private static final String SCHEMA_NAME_PREFIX = "CommonEventFormat_v";
+ private static final String SCHEMA_NAME_SUFFIX = ".json";
+
+ private VesStructureLoader() {
+ }
+
+ @PostConstruct public void init() {
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "VesStructureLoader: Trying to load json schemas");
+ String jettyBase = System.getProperty("jetty.base");
+ if (jettyBase == null) {
+ String msg = "Couldn't resolve jetty.base environmental variable";
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), msg);
+ throw new IllegalArgumentException(msg + ". Failed to load VES schema files... aborting");
+ }
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "jetty.base={}", jettyBase);
+
+ File dir = new File(jettyBase + "/config/dcae-be/ves-schema");
+ File[] files = dir.listFiles((dir1, name) -> name.startsWith(SCHEMA_NAME_PREFIX) && name.endsWith(SCHEMA_NAME_SUFFIX));
+
+ if (ArrayUtils.isEmpty(files)) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error – Failed to find VES Schema definitions.");
+ } else {
+
+ for (File f : files) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Loading VES schema file: {}", f.getName());
+ parseJsonFileAndSaveToMap(f);
+ }
+ }
+
+ }
+
+ private void parseJsonFileAndSaveToMap(File file) {
+
+ try {
+ EventListenerDefinition eventListener = gson.fromJson(new FileReader(file), EventListenerDefinition.class);
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), gson.toJson(eventListener));
+ String validationError = getValidatorMessage(eventListener);
+ if (StringUtils.isEmpty(validationError)) {
+ eventListeners.put(getVersionFromFileName(file.getName()), eventListener);
+ } else {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error: Failed to parse VES schema file {}. [{}]", file.getName(), validationError);
+ }
+ } catch (FileNotFoundException | JsonIOException | JsonSyntaxException e) {
+ errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error: Failed to parse VES schema file {}. [{}]", file.getName(), e);
+ }
+ }
+
+ public static Map<String, VesDataTypeDefinition> getEventListenerDefinitionByVersion(String version) {
+ return eventListeners.get(version).getProperties().get(EventListenerDefinition.EVENT_ROOT).getProperties();
+ }
+
+ public static Set<String> getAvailableVersionsList() {
+ return eventListeners.keySet();
+ }
+
+ public static Map<String, Set<String>> getAvailableVersionsAndEventTypes() {
+ return eventListeners.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> getEventListenerDefinitionByVersion(e.getKey()).keySet()));
+ }
+
+ public static Set<String> getEventTypeListByVersion(String version) {
+ return getEventListenerDefinitionByVersion(version).keySet();
+ }
+
+ private String getValidatorMessage(EventListenerDefinition eventListenerDefinition) {
+ String validationError = eventListenerDefinition.validate();
+ if (StringUtils.isBlank(validationError)) {
+ validationError = eventListenerDefinition.resolveRefTypes();
+ }
+ return validationError;
+ }
+
+ private String getVersionFromFileName(String fileName) {
+ return fileName.replace(SCHEMA_NAME_PREFIX, "").replace(SCHEMA_NAME_SUFFIX, "");
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ // why is this method empty?
+ }
+}