diff options
25 files changed, 691 insertions, 59 deletions
@@ -14,3 +14,5 @@ test1.json bpmnworkflow.bpmn20.xml dist *.log +.idea/ +*.iml diff --git a/workflow-designer-be/pom.xml b/workflow-designer-be/pom.xml index ddcb9c63..58041472 100644 --- a/workflow-designer-be/pom.xml +++ b/workflow-designer-be/pom.xml @@ -16,6 +16,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> + <onap.version>1.3.0-SNAPSHOT</onap.version> </properties> <dependencies> @@ -34,12 +35,15 @@ <artifactId>spring-boot-starter-jetty</artifactId> </dependency> - <!-- - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-cassandra</artifactId> - </dependency> - --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-cassandra</artifactId> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <optional>true</optional> + </dependency> <dependency> <groupId>org.springframework.boot</groupId> @@ -47,13 +51,16 @@ </dependency> <dependency> <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-test</artifactId> - <scope>test</scope> + <artifactId>spring-boot-devtools</artifactId> </dependency> + <dependency> <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-devtools</artifactId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> </dependency> + + <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> @@ -66,6 +73,34 @@ <version>2.8.0</version> <scope>compile</scope> </dependency> + <dependency> + <groupId>org.openecomp.sdc</groupId> + <artifactId>openecomp-sdc-versioning-api</artifactId> + <version>${onap.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdc</groupId> + <artifactId>openecomp-sdc-versioning-core</artifactId> + <version>${onap.version}</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.openecomp.sdc.core</groupId> + <artifactId>openecomp-zusammen-api</artifactId> + <version>${onap.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdc.core</groupId> + <artifactId>openecomp-zusammen-core</artifactId> + <version>${onap.version}</version> + <scope>runtime</scope> + <exclusions> + <exclusion> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + </exclusion> + </exclusions> + </dependency> </dependencies> diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java index e1bd8eac..b7e3b345 100644 --- a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java @@ -6,16 +6,15 @@ import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.context.annotation.Bean; - @SpringBootApplication public class SpringBootWebApplication { - public static void main(String[] args) { - SpringApplication.run(SpringBootWebApplication.class, args); - } - @Bean - public ConfigurableServletWebServerFactory webServerFactory() { - JettyServletWebServerFactory factory = new JettyServletWebServerFactory(); - return factory; - } + public static void main(String[] args) { + SpringApplication.run(SpringBootWebApplication.class, args); + } + + @Bean + public ConfigurableServletWebServerFactory webServerFactory() { + return new JettyServletWebServerFactory(); + } } diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/RestConstants.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/RestConstants.java new file mode 100644 index 00000000..8f02be0f --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/RestConstants.java @@ -0,0 +1,9 @@ +package org.onap.sdc.workflow.api; + +public class RestConstants { + + private RestConstants() { + } + + public static final String USER_ID_HEADER_PARAM = "USER_ID"; +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java new file mode 100644 index 00000000..90657709 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java @@ -0,0 +1,37 @@ +package org.onap.sdc.workflow.api; + +import static org.onap.sdc.workflow.api.RestConstants.USER_ID_HEADER_PARAM; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.onap.sdc.workflow.api.types.CollectionWrapper; +import org.onap.sdc.workflow.persistence.types.Workflow; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; + +@RequestMapping("/workflows") +@Api("Workflows") +public interface WorkflowController { + + @GetMapping + @ApiOperation("List workflows") + CollectionWrapper<Workflow> list(@RequestHeader(USER_ID_HEADER_PARAM) String user); + + @PostMapping + @ApiOperation("Create workflow") + Workflow create(@RequestBody Workflow workflow, @RequestHeader(USER_ID_HEADER_PARAM) String user); + + @GetMapping("/{id}") + @ApiOperation("Get workflow") + Workflow get(@PathVariable("id") String id, @RequestHeader(USER_ID_HEADER_PARAM) String user); + + @PutMapping("/{id}") + @ApiOperation("Update workflow") + Workflow update(@RequestBody Workflow workflow, @PathVariable("id") String id, + @RequestHeader(USER_ID_HEADER_PARAM) String user); +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowsController.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowsController.java deleted file mode 100644 index 229bc8c1..00000000 --- a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowsController.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.onap.sdc.workflow.api; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Arrays; -import java.util.Collection; - -@RestController -@RequestMapping("/workflows") -@Api(value = "Workflows kalsjkaj") -public class WorkflowsController { - - @GetMapping - @ApiOperation(value = "List workflows", response = Collection.class) - public Collection<String> list() { - return Arrays.asList("a", "c"); - } - -} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/impl/WorkflowControllerImpl.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/impl/WorkflowControllerImpl.java new file mode 100644 index 00000000..b7a122b8 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/impl/WorkflowControllerImpl.java @@ -0,0 +1,51 @@ +package org.onap.sdc.workflow.api.impl; + +import static org.onap.sdc.workflow.api.RestConstants.USER_ID_HEADER_PARAM; + +import org.onap.sdc.workflow.api.WorkflowController; +import org.onap.sdc.workflow.api.types.CollectionWrapper; +import org.onap.sdc.workflow.persistence.types.Workflow; +import org.onap.sdc.workflow.services.WorkflowManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +@RestController("workflowController") +public class WorkflowControllerImpl implements WorkflowController { + + private final WorkflowManager workflowManager; + + @Autowired + public WorkflowControllerImpl(@Qualifier("workflowManager") WorkflowManager workflowManager) { + this.workflowManager = workflowManager; + } + + @Override + public CollectionWrapper<Workflow> list(@RequestHeader(USER_ID_HEADER_PARAM) String user) { + return new CollectionWrapper<>(workflowManager.list()); + } + + @Override + public Workflow create(@RequestBody Workflow workflow, @RequestHeader(USER_ID_HEADER_PARAM) String user) { + workflowManager.create(workflow); + return workflow; + } + + @Override + public Workflow get(@PathVariable("id") String id, @RequestHeader(USER_ID_HEADER_PARAM) String user) { + Workflow workflow = new Workflow(); + workflow.setId(id); + return workflowManager.get(workflow); + } + + @Override + public Workflow update(@RequestBody Workflow workflow, @PathVariable("id") String id, + @RequestHeader(USER_ID_HEADER_PARAM) String user) { + workflow.setId(id); + workflowManager.update(workflow); + return workflow; + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/CollectionWrapper.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/CollectionWrapper.java new file mode 100644 index 00000000..653b0dcf --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/CollectionWrapper.java @@ -0,0 +1,18 @@ +package org.onap.sdc.workflow.api.types; + +import java.util.Collection; +import lombok.Data; + +@Data +public class CollectionWrapper<T> { + + private int total; + private int limit; + private int offset; + private Collection<T> results; + + public CollectionWrapper(Collection<T> results) { + this.results = results; + this.total = results.size(); + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/UniqueValueRepository.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/UniqueValueRepository.java new file mode 100644 index 00000000..d374a404 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/UniqueValueRepository.java @@ -0,0 +1,10 @@ +package org.onap.sdc.workflow.persistence; + +import org.onap.sdc.workflow.persistence.types.UniqueValueEntity; +import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UniqueValueRepository extends CassandraRepository<UniqueValueEntity, UniqueValueEntity> { + +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/UniqueValueEntity.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/UniqueValueEntity.java new file mode 100644 index 00000000..925ec5cb --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/UniqueValueEntity.java @@ -0,0 +1,23 @@ +package org.onap.sdc.workflow.persistence.types; + +import static org.springframework.data.cassandra.core.cql.PrimaryKeyType.PARTITIONED; + +import lombok.Data; +import org.springframework.data.cassandra.core.mapping.PrimaryKeyColumn; +import org.springframework.data.cassandra.core.mapping.Table; + +@Table("unique_value") +@Data +public class UniqueValueEntity { + + @PrimaryKeyColumn(ordinal = 0, type = PARTITIONED) + private String type; + + @PrimaryKeyColumn(ordinal = 1, type = PARTITIONED) + private String value; + + public UniqueValueEntity(String type, String value) { + this.type = type; + this.value = value; + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java new file mode 100644 index 00000000..76a6591c --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java @@ -0,0 +1,13 @@ +package org.onap.sdc.workflow.persistence.types; + + +import lombok.Data; + +@Data +public class Workflow { + + private String id; + private String name; + private String description; + private String category; +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowProperty.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowProperty.java new file mode 100644 index 00000000..6c2d804d --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowProperty.java @@ -0,0 +1,9 @@ +package org.onap.sdc.workflow.persistence.types; + +public final class WorkflowProperty { + + private WorkflowProperty() { + } + + public static final String CATEGORY = "category"; +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/config/SwaggerConfig.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/SwaggerConfig.java index ed317f4b..5105114f 100644 --- a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/config/SwaggerConfig.java +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/SwaggerConfig.java @@ -1,32 +1,18 @@ -package org.onap.sdc.workflow.config; +package org.onap.sdc.workflow.server.config; + +import static springfox.documentation.builders.PathSelectors.regex; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; -import static springfox.documentation.builders.PathSelectors.regex; @Configuration @EnableSwagger2 public class SwaggerConfig { - /*@Bean - public Docket api() { - return new Docket(DocumentationType.SWAGGER_2) - .select() - .apis(RequestHandlerSelectors.any()) - .paths(PathSelectors.any()) - .build(); - }*/ - @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ZusammenConfig.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ZusammenConfig.java new file mode 100644 index 00000000..092c3464 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ZusammenConfig.java @@ -0,0 +1,32 @@ +package org.onap.sdc.workflow.server.config; + +import javax.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ZusammenConfig { + + @Value("${zusammen-tenant:workflow}") + private String tenant; + @Value("${spring.data.cassandra.contact-points:localhost}") + private String cassandraAddress; + @Value("${spring.data.cassandra.username:}") + private String cassandraUser; + @Value("${spring.data.cassandra.password:}") + private String cassandraPassword; + @Value("${zusammen.cassandra.isAuthenticate:false}") + private String cassandraAuth; + + @PostConstruct + public void init(){ + System.setProperty("cassandra.nodes", cassandraAddress); + System.setProperty("cassandra.user", cassandraUser); + System.setProperty("cassandra.password", cassandraPassword); + System.setProperty("cassandra.authenticate", Boolean.toString(Boolean.valueOf(cassandraAuth))); + } + + public String getTenant() { + return tenant; + } +}
\ No newline at end of file diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/filters/SessionContextFilter.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/filters/SessionContextFilter.java new file mode 100644 index 00000000..d4dc8a80 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/filters/SessionContextFilter.java @@ -0,0 +1,63 @@ +package org.onap.sdc.workflow.server.filters; + +import static org.onap.sdc.workflow.api.RestConstants.USER_ID_HEADER_PARAM; + +import java.io.IOException; +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 org.onap.sdc.workflow.server.config.ZusammenConfig; +import org.openecomp.sdc.common.session.SessionContextProvider; +import org.openecomp.sdc.common.session.SessionContextProviderFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SessionContextFilter implements Filter { + + private ZusammenConfig zusammenConfig; + + @Autowired + public SessionContextFilter(ZusammenConfig zusammenConfig) { + this.zusammenConfig = zusammenConfig; + } + + @Override + public void init(FilterConfig filterConfig) { + // not implemented + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + SessionContextProvider contextProvider = SessionContextProviderFactory.getInstance().createInterface(); + + try { + if (servletRequest instanceof HttpServletRequest) { + + contextProvider.create(getUser(servletRequest), getTenant()); + } + + filterChain.doFilter(servletRequest, servletResponse); + } finally { + contextProvider.close(); + } + } + + @Override + public void destroy() { + // not implemented + } + + private String getUser(ServletRequest servletRequest) { + return ((HttpServletRequest) servletRequest).getHeader(USER_ID_HEADER_PARAM); + } + + private String getTenant() { + return zusammenConfig.getTenant(); + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/UniqueValueService.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/UniqueValueService.java new file mode 100644 index 00000000..e6e88ed9 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/UniqueValueService.java @@ -0,0 +1,107 @@ +package org.onap.sdc.workflow.services; + +import java.util.Optional; +import org.onap.sdc.workflow.persistence.UniqueValueRepository; +import org.onap.sdc.workflow.persistence.types.UniqueValueEntity; +import org.onap.sdc.workflow.services.errors.UniqueValueViolationException; +import org.openecomp.core.utilities.CommonMethods; // todo get rid of +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service("uniqueValueService") +public class UniqueValueService { + + private static final char FORMATTED_UNIQUE_VALUE_SEPARATOR = '_'; + + private final UniqueValueRepository uniqueValueRepository; + + @Autowired + public UniqueValueService(UniqueValueRepository uniqueValueRepository) { + this.uniqueValueRepository = uniqueValueRepository; + } + + /** + * Create unique value. + * + * @param type the type + * @param uniqueCombination the unique combination + */ + public void createUniqueValue(String type, String... uniqueCombination) { + formatValue(uniqueCombination).ifPresent(formattedValue -> { + validateUniqueValue(type, formattedValue, uniqueCombination); + uniqueValueRepository.insert(new UniqueValueEntity(type, formattedValue)); + }); + } + + /** + * Delete unique value. + * + * @param type the type + * @param uniqueCombination the unique combination + */ + public void deleteUniqueValue(String type, String... uniqueCombination) { + formatValue(uniqueCombination) + .ifPresent(formattedValue -> uniqueValueRepository.delete(new UniqueValueEntity(type, formattedValue))); + + } + + /** + * Update unique value. + * + * @param type the type + * @param oldValue the old value + * @param newValue the new value + * @param uniqueContext the unique context + */ + public void updateUniqueValue(String type, String oldValue, String newValue, String... uniqueContext) { + if (newValue == null || !newValue.equalsIgnoreCase(oldValue)) { + createUniqueValue(type, CommonMethods.concat(uniqueContext, new String[] {newValue})); + deleteUniqueValue(type, CommonMethods.concat(uniqueContext, new String[] {oldValue})); + } + } + + /** + * Validate unique value. + * + * @param type the type + * @param uniqueCombination the unique combination + */ + public void validateUniqueValue(String type, String... uniqueCombination) { + formatValue(uniqueCombination) + .ifPresent(formattedValue -> validateUniqueValue(type, formattedValue, uniqueCombination)); + } + + /** + * Checks if a unique value is taken. + * + * @return true if the unique value is occupied, false otherwise + */ + public boolean isUniqueValueOccupied(String type, String... uniqueCombination) { + return formatValue(uniqueCombination).map(formattedValue -> isUniqueValueOccupied(type, formattedValue)) + .orElse(false); + } + + private void validateUniqueValue(String type, String formattedValue, String... uniqueCombination) { + if (isUniqueValueOccupied(type, formattedValue)) { + throw new UniqueValueViolationException(type, getValueWithoutContext(uniqueCombination)); + } + } + + private boolean isUniqueValueOccupied(String type, String formattedValue) { + return uniqueValueRepository.findById(new UniqueValueEntity(type, formattedValue)).isPresent(); + } + + private static Optional<String> formatValue(String[] uniqueCombination) { + if (uniqueCombination == null || uniqueCombination.length == 0 + || getValueWithoutContext(uniqueCombination) == null) { + return Optional.empty(); + } + + uniqueCombination[uniqueCombination.length - 1] = getValueWithoutContext(uniqueCombination).toLowerCase(); + return Optional.of(CommonMethods.arrayToSeparatedString(uniqueCombination, FORMATTED_UNIQUE_VALUE_SEPARATOR)); + } + + private static String getValueWithoutContext(String... uniqueCombination) { + return uniqueCombination[uniqueCombination.length - 1]; + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowManager.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowManager.java new file mode 100644 index 00000000..565c4f5a --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowManager.java @@ -0,0 +1,15 @@ +package org.onap.sdc.workflow.services; + +import java.util.Collection; +import org.onap.sdc.workflow.persistence.types.Workflow; + +public interface WorkflowManager { + + Collection<Workflow> list(); + + Workflow get(Workflow workflow); + + void create(Workflow workflow); + + void update(Workflow workflow); +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/errors/UniqueValueViolationException.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/errors/UniqueValueViolationException.java new file mode 100644 index 00000000..358863e9 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/errors/UniqueValueViolationException.java @@ -0,0 +1,16 @@ +package org.onap.sdc.workflow.services.errors; + + +import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY; + +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(UNPROCESSABLE_ENTITY) +public class UniqueValueViolationException extends RuntimeException { + + private static final String UNIQUE_VALUE_VIOLATION_MSG = "%s with the value '%s' already exists."; + + public UniqueValueViolationException(String uniqueType, String value) { + super(String.format(UNIQUE_VALUE_VIOLATION_MSG, uniqueType, value)); + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/errors/WorkflowNotFoundException.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/errors/WorkflowNotFoundException.java new file mode 100644 index 00000000..46a6d5ef --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/errors/WorkflowNotFoundException.java @@ -0,0 +1,13 @@ +package org.onap.sdc.workflow.services.errors; + +import static org.springframework.http.HttpStatus.NOT_FOUND; + +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(NOT_FOUND) +public class WorkflowNotFoundException extends RuntimeException { + + public WorkflowNotFoundException(String workflowId) { + super(String.format("Workflow with id %s does not exist", workflowId)); + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/CollaborationConfiguration.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/CollaborationConfiguration.java new file mode 100644 index 00000000..2a4cd5aa --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/CollaborationConfiguration.java @@ -0,0 +1,22 @@ +package org.onap.sdc.workflow.services.impl; + +import org.openecomp.sdc.versioning.ItemManager; +import org.openecomp.sdc.versioning.ItemManagerFactory; +import org.openecomp.sdc.versioning.VersioningManager; +import org.openecomp.sdc.versioning.VersioningManagerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CollaborationConfiguration { + + @Bean + public ItemManager itemManager() { + return ItemManagerFactory.getInstance().createInterface(); + } + + @Bean + public VersioningManager versioningManager() { + return VersioningManagerFactory.getInstance().createInterface(); + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java new file mode 100644 index 00000000..40750f10 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java @@ -0,0 +1,76 @@ +package org.onap.sdc.workflow.services.impl; + +import java.util.Collection; +import java.util.stream.Collectors; +import org.onap.sdc.workflow.persistence.types.Workflow; +import org.onap.sdc.workflow.services.UniqueValueService; +import org.onap.sdc.workflow.services.WorkflowManager; +import org.onap.sdc.workflow.services.errors.WorkflowNotFoundException; +import org.onap.sdc.workflow.services.impl.mappers.ItemToWorkflowMapper; +import org.onap.sdc.workflow.services.impl.mappers.WorkflowToItemMapper; +import org.openecomp.sdc.versioning.ItemManager; +import org.openecomp.sdc.versioning.types.Item; +import org.openecomp.sdc.versioning.types.ItemStatus; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service("workflowManager") +public class WorkflowManagerImpl implements WorkflowManager { + + public static final String WORKFLOW_TYPE = "WORKFLOW"; + private static final String WORKFLOW_NAME_UNIQUE_TYPE = "WORKFLOW_NAME"; + private final ItemManager itemManager; + private final UniqueValueService uniqueValueService; + + @Autowired + public WorkflowManagerImpl(ItemManager itemManager, + @Qualifier("uniqueValueService") UniqueValueService uniqueValueService) { + this.itemManager = itemManager; + this.uniqueValueService = uniqueValueService; + } + + @Override + public Collection<Workflow> list() { + ItemToWorkflowMapper mapper = new ItemToWorkflowMapper(); + return itemManager.list(item -> WORKFLOW_TYPE.equals(item.getType())).stream() + .map(item -> mapper.applyMapping(item, Workflow.class)).collect(Collectors.toList()); + } + + @Override + public Workflow get(Workflow workflow) { + ItemToWorkflowMapper mapper = new ItemToWorkflowMapper(); + Item retrievedItem = itemManager.get(workflow.getId()); + if (retrievedItem == null) { + throw new WorkflowNotFoundException(workflow.getId()); + } + return mapper.applyMapping(retrievedItem, Workflow.class); + } + + @Override + public void create(Workflow workflow) { + Item item = new WorkflowToItemMapper().applyMapping(workflow, Item.class); + item.setStatus(ItemStatus.ACTIVE); + + uniqueValueService.validateUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, workflow.getName()); + workflow.setId(itemManager.create(item).getId()); + uniqueValueService.createUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, workflow.getName()); + } + + @Override + public void update(Workflow workflow) { + Item retrievedItem = itemManager.get(workflow.getId()); + if (retrievedItem == null) { + throw new WorkflowNotFoundException(workflow.getId()); + } + + uniqueValueService.updateUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, retrievedItem.getName(), workflow.getName()); + + Item item = new WorkflowToItemMapper().applyMapping(workflow, Item.class); + item.setId(workflow.getId()); + item.setStatus(retrievedItem.getStatus()); + item.setVersionStatusCounters(retrievedItem.getVersionStatusCounters()); + + itemManager.update(item); + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/ItemToWorkflowMapper.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/ItemToWorkflowMapper.java new file mode 100644 index 00000000..09e3cbd6 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/ItemToWorkflowMapper.java @@ -0,0 +1,16 @@ +package org.onap.sdc.workflow.services.impl.mappers; + +import org.onap.sdc.workflow.persistence.types.Workflow; +import org.onap.sdc.workflow.persistence.types.WorkflowProperty; +import org.openecomp.sdc.versioning.types.Item; + +public class ItemToWorkflowMapper extends Mapper<Item, Workflow> { + + @Override + public void map(Item source, Workflow target) { + target.setId(source.getId()); + target.setName(source.getName()); + target.setDescription(source.getDescription()); + target.setCategory((String) source.getProperties().get(WorkflowProperty.CATEGORY)); + } +} diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/Mapper.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/Mapper.java new file mode 100644 index 00000000..a66f8608 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/Mapper.java @@ -0,0 +1,80 @@ +package org.onap.sdc.workflow.services.impl.mappers; + +import org.openecomp.sdc.common.errors.CoreException; +import org.openecomp.sdc.common.errors.ErrorCode; + +/** + * Base class for all mapping classes. Mapping classes will perform data mapping from source object + * to target object Base class provides following<br> <ol> <li>provides life cycle of + * mapping class , first mapSimpleProperties is called and then mapComplexProperties is + * called.</li> <li>methods mapSimpleProperties and mapComplexProperties with default + * implementation, these should be overridden by concrete mapping classes for writing mapping + * logic.</li> </ol> + */ + +public abstract class Mapper<S, T> { + + /** + * Method is called for starting mapping from source object to target object method sets context + * in the thread locale and than calls mapSimpleProperties and mapComplexProperties + * respectively. + * + * @param source : source object for mapping + * @param clazz : target <code>Class</code> for mapping + * @return <code>T</code> - instance of type <code>T</code> + */ + + public final T applyMapping(final S source, Class<T> clazz) { + T target = (T) instantiateTarget(clazz); + if (source != null && target != null) { + preMapping(source, target); + map(source, target); + postMapping(source, target); + + } + return target; + + } + + /** + * This method is called before the <code>map</code> method. + */ + protected void preMapping(final S source, T target) { + // extension point + } + + /** + * The actual method that does the mapping between the <code>source</code> to <code>target</code> + * objects. This method is being called automatically as part of the mapper class. This + * method must be override (it is abstract) by the mapper class. + * + * @param source - the source object. + * @param target - the target object. + */ + + public abstract void map(final S source, T target); + + /** + * This method is called after the <code>map</code> method. + */ + protected void postMapping(final S source, T target) { + // extension point + } + + /** + * Creates the instance of the input class. + * + * @return <code>Object</code> + */ + + private Object instantiateTarget(final Class<?> clazz) { + + try { + return clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException exception) { + throw new CoreException((new ErrorCode.ErrorCodeBuilder()).withMessage(exception.getMessage()).build(), + exception); + } + } +} + diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowToItemMapper.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowToItemMapper.java new file mode 100644 index 00000000..0b569f09 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowToItemMapper.java @@ -0,0 +1,18 @@ +package org.onap.sdc.workflow.services.impl.mappers; + +import static org.onap.sdc.workflow.services.impl.WorkflowManagerImpl.WORKFLOW_TYPE; + +import org.onap.sdc.workflow.persistence.types.Workflow; +import org.onap.sdc.workflow.persistence.types.WorkflowProperty; +import org.openecomp.sdc.versioning.types.Item; + +public class WorkflowToItemMapper extends Mapper<Workflow, Item> { + + @Override + public void map(Workflow source, Item target) { + target.setType(WORKFLOW_TYPE); + target.setName(source.getName()); + target.setDescription(source.getDescription()); + target.addProperty(WorkflowProperty.CATEGORY, source.getCategory()); + } +} diff --git a/workflow-designer-be/src/main/resources/application.properties b/workflow-designer-be/src/main/resources/application.properties index 5df521b5..b7cfc5aa 100644 --- a/workflow-designer-be/src/main/resources/application.properties +++ b/workflow-designer-be/src/main/resources/application.properties @@ -1,2 +1,7 @@ server.servlet.context-path=/wf -server.port=8080
\ No newline at end of file +server.port=8080 + +#CASSANDRA +spring.data.cassandra.contact-points=localhost +spring.data.cassandra.keyspace-name=workflow +spring.data.cassandra.port=9042
\ No newline at end of file |