aboutsummaryrefslogtreecommitdiffstats
path: root/workflow
diff options
context:
space:
mode:
Diffstat (limited to 'workflow')
-rw-r--r--workflow/README.md29
-rw-r--r--workflow/pom.xml103
-rw-r--r--workflow/workflow-bdd/.gitignore11
-rw-r--r--workflow/workflow-bdd/README.txt4
-rw-r--r--workflow/workflow-bdd/config.json28
-rw-r--r--workflow/workflow-bdd/cucumber.js3
-rw-r--r--workflow/workflow-bdd/features/Version_Create_Update.feature28
-rw-r--r--workflow/workflow-bdd/features/Version_State.feature30
-rw-r--r--workflow/workflow-bdd/features/Workflow_Create_Update.feature27
-rw-r--r--workflow/workflow-bdd/package.json31
-rw-r--r--workflow/workflow-bdd/plugins/README.md23
-rw-r--r--workflow/workflow-bdd/plugins/jsdoc_config.json15
-rw-r--r--workflow/workflow-bdd/plugins/reporter.js31
-rw-r--r--workflow/workflow-bdd/plugins/steps.js65
-rw-r--r--workflow/workflow-bdd/pom.xml173
-rw-r--r--workflow/workflow-bdd/resources/json/createWorkflow.json1
-rw-r--r--workflow/workflow-bdd/stepDefinitions/Collaboration_Steps.js113
-rw-r--r--workflow/workflow-bdd/stepDefinitions/General_Steps.js321
-rw-r--r--workflow/workflow-bdd/stepDefinitions/InputData_steps.js83
-rw-r--r--workflow/workflow-bdd/stepDefinitions/InterfaceOperationSteps.js118
-rw-r--r--workflow/workflow-bdd/stepDefinitions/Item_steps.js91
-rw-r--r--workflow/workflow-bdd/stepDefinitions/REST_Steps.js80
-rw-r--r--workflow/workflow-bdd/stepDefinitions/Utils.js153
-rw-r--r--workflow/workflow-bdd/stepDefinitions/Workflow_Steps.js19
-rw-r--r--workflow/workflow-bdd/stepDefinitions/world.js87
-rw-r--r--workflow/workflow-designer-be/pom.xml182
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java20
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/RestConstants.java9
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java66
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java117
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/exceptionshandlers/CustomizedResponseEntityExceptionHandler.java48
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/CollectionWrapper.java18
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionRequestDto.java11
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionStateDto.java20
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/ArtifactRepository.java18
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/UniqueValueRepository.java10
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/impl/ArtifactRepositoryImpl.java104
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/ArtifactEntity.java16
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/UniqueValueEntity.java23
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java12
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowProperty.java9
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowVersion.java26
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowVersionState.java20
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/SwaggerConfig.java24
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ZusammenConfig.java32
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/filters/SessionContextFilter.java64
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/UniqueValueService.java107
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowManager.java15
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowVersionManager.java30
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/EntityNotFoundException.java8
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/InvalidArtifactException.java8
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/UniqueValueViolationException.java11
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionCreationException.java15
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionModificationException.java10
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionStateModificationException.java12
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/CollaborationConfiguration.java22
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java79
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImpl.java186
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/VersionMapper.java19
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/VersionStateMapper.java22
-rw-r--r--workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowMapper.java19
-rw-r--r--workflow/workflow-designer-be/src/main/resources/application.properties10
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/RestPath.java24
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/TestUtil.java38
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowControllerTest.java121
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowVersionControllerTest.java118
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/persistence/impl/ArtifactRepositoryTest.java29
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/UniqueValueServiceTest.java98
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImplTest.java119
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImplTest.java258
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/VersionMapperTest.java80
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/VersionStateMapperTest.java75
-rw-r--r--workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowMapperTest.java50
-rw-r--r--workflow/workflow-designer-init/pom.xml45
-rw-r--r--workflow/workflow-designer-init/src/main/docker/Dockerfile10
-rw-r--r--workflow/workflow-designer-init/src/main/docker/create_workflow_db.cql125
-rw-r--r--workflow/workflow-designer-init/src/main/docker/start.sh18
-rw-r--r--workflow/workflow-designer-ui/pom.xml34
78 files changed, 4331 insertions, 0 deletions
diff --git a/workflow/README.md b/workflow/README.md
new file mode 100644
index 00000000..40b4bbb2
--- /dev/null
+++ b/workflow/README.md
@@ -0,0 +1,29 @@
+# Steps to run the Workflow application on Docker
+
+## 1. Initialize Workflow Database
+
+`docker run -d -e CS_HOST={HOST} -e CS_PORT={PORT} -e CS_USER={USER} -e CS_PASSWORD={PASSWORD} {INIT_IMAGE}`
+
+This is done only once to initialize the DB schema.
+
+**Example**
+
+`docker run -d -e CS_HOST=10.247.41.19 -e CS_USER=test -e CS_PASSWORD=secret -e CS_PORT=9160 onap/workflow-init:latest`
+
+## 2. Start Backend
+
+`docker run -d -e JAVA_OPTIONS={JAVA_OPTIONS} -e CS_HOSTS={COMMA_SEPARATED_HOSTS} -e CS_PORT={PORT}
+-e CS_USER={USER} -e CS_PASSWORD={PASSWORD} -p {HOST_PORT}:{APPLICATION_PORT} {BACKEND_IMAGE}`
+
+or, if Cassandra authentication is not required
+
+`docker run -d -e JAVA_OPTIONS={JAVA_OPTIONS} -e CS_HOSTS={COMMA_SEPARATED_HOSTS} -e CS_PORT={PORT}
+-e CS_AUTHENTICATE=false -p {HOST_PORT}:{APPLICATION_PORT} {BACKEND_IMAGE}`
+
+The server listens on 8080 by default, but it is possible to change the application port by passing
+`-e SERVER_PORT={PORT}` to Docker _run_ command.
+
+**Example**
+
+`docker run -d -e JAVA_OPTIONS="-Xmx128m -Xms128m -Xss1m" -e CS_HOSTS=10.247.41.19,10.247.41.20
+-e CS_PORT=9042 -e CS_AUTHENTICATE=false -p 8080:8080 onap/workflow-backend:latest` \ No newline at end of file
diff --git a/workflow/pom.xml b/workflow/pom.xml
new file mode 100644
index 00000000..ea4edbcf
--- /dev/null
+++ b/workflow/pom.xml
@@ -0,0 +1,103 @@
+<project
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.sdc.workflow_designer</groupId>
+ <artifactId>workflow-designer-parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <onap.version>1.3.0-SNAPSHOT</onap.version>
+ <mvn.docker.version>0.23.0</mvn.docker.version>
+ <docker.optimize>true</docker.optimize>
+ <docker.username>docker</docker.username>
+ <docker.password>docker</docker.password>
+ <nexus.registry>nexus3.onap.org:10001</nexus.registry>
+ <nexus.proxy>https://nexus.onap.org</nexus.proxy>
+ <sitePath>/content/sites/site/org/onap/sdc/workflow/${project.version}</sitePath>
+ </properties>
+
+ <modules>
+ <module>workflow-designer-init</module>
+ <module>workflow-designer-be</module>
+ <module>workflow-designer-ui</module>
+ </modules>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <version>${mvn.docker.version}</version>
+ <configuration>
+ <verbose>false</verbose>
+ <registry>${nexus.registry}</registry>
+ <authConfig>
+ <pull>
+ <username>${docker.username}</username>
+ <password>${docker.password}</password>
+ </pull>
+ </authConfig>
+ </configuration>
+ <executions>
+ <execution>
+ <id>docker-build</id>
+ <phase>install</phase>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>push-images</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>push</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <repositories>
+ <repository>
+ <id>ecomp-releases</id>
+ <name>Release Repository</name>
+ <url>${nexus.proxy}/content/repositories/releases/</url>
+ </repository>
+ <repository>
+ <id>ecomp-snapshots</id>
+ <name>Snapshots Repository</name>
+ <url>${nexus.proxy}/content/repositories/snapshots/</url>
+ </repository>
+ <repository>
+ <id>ecomp-public</id>
+ <name>Public Repository</name>
+ <url>${nexus.proxy}/content/repositories/public/</url>
+ </repository>
+ </repositories>
+ <distributionManagement>
+ <repository>
+ <id>ecomp-releases</id>
+ <name>Release Repository</name>
+ <url>${nexus.proxy}/content/repositories/releases/</url>
+ </repository>
+ <snapshotRepository>
+ <id>ecomp-snapshots</id>
+ <name>Snapshot Repository</name>
+ <url>${nexus.proxy}/content/repositories/snapshots/</url>
+ </snapshotRepository>
+ <site>
+ <id>ecomp-site</id>
+ <url>dav:${nexus.proxy}${sitePath}</url>
+ </site>
+ </distributionManagement>
+
+</project> \ No newline at end of file
diff --git a/workflow/workflow-bdd/.gitignore b/workflow/workflow-bdd/.gitignore
new file mode 100644
index 00000000..316e3984
--- /dev/null
+++ b/workflow/workflow-bdd/.gitignore
@@ -0,0 +1,11 @@
+.idea
+.vscode
+.history
+debug.log
+dist
+docs
+node_modules
+.npmrc
+npm-debug.log
+devConfig.json
+jenkinsConfig.json
diff --git a/workflow/workflow-bdd/README.txt b/workflow/workflow-bdd/README.txt
new file mode 100644
index 00000000..35250ed3
--- /dev/null
+++ b/workflow/workflow-bdd/README.txt
@@ -0,0 +1,4 @@
+In order to setup the project:
+
+Run "mvn install -DskipTests", this will create the documentation under the "docs".
+Open the index.html under the docs directory and continue from there. \ No newline at end of file
diff --git a/workflow/workflow-bdd/config.json b/workflow/workflow-bdd/config.json
new file mode 100644
index 00000000..260f2859
--- /dev/null
+++ b/workflow/workflow-bdd/config.json
@@ -0,0 +1,28 @@
+{
+ "protocol" : "http",
+
+ "onboarding" : {
+ "port" : 8285,
+ "prefix" : "sdc1/feProxy/onboarding-api/v1.0",
+ "server" : "onboarding.server",
+ "user" : "user"
+ },
+ "vf" : {
+ "port" : 8285,
+ "prefix" : "sdc1/feProxy/rest/v1",
+ "server" : "vf.server",
+ "user" : "user"
+ },
+ "workflow" : {
+ "port" : 8080,
+ "prefix" : "wf",
+ "server" : "",
+ "user" : "user"
+ },
+ "activity_spec" : {
+ "port" : 8080,
+ "prefix" : "activity-spec-api/v1.0",
+ "server" : "activity_spec.server",
+ "user" : "user"
+ }
+}
diff --git a/workflow/workflow-bdd/cucumber.js b/workflow/workflow-bdd/cucumber.js
new file mode 100644
index 00000000..4ade9b1c
--- /dev/null
+++ b/workflow/workflow-bdd/cucumber.js
@@ -0,0 +1,3 @@
+module.exports = {
+ "default" : "--require stepDefinitions -f summary -r ./features -f json:report/report.json"
+}; \ No newline at end of file
diff --git a/workflow/workflow-bdd/features/Version_Create_Update.feature b/workflow/workflow-bdd/features/Version_Create_Update.feature
new file mode 100644
index 00000000..2cb05804
--- /dev/null
+++ b/workflow/workflow-bdd/features/Version_Create_Update.feature
@@ -0,0 +1,28 @@
+Feature: Workflow Versions
+
+ Background: Init
+ Given I want to create a Workflow
+
+ Scenario: Create and get version
+ When I want to create input data
+ Then I want to update the input property "description" with value "workflow version description"
+ Then I want to create for path "/workflows/{item.id}/versions" with the input data from the context
+ Then I want to copy to property "versionId" from response data path "id"
+ Then I want to get path "/workflows/{item.id}/versions/{versionId}"
+ Then I want to check that property "id" in the response equals to value of saved property "versionId"
+
+ When I want to get path "/workflows/{item.id}/versions"
+ Then I want to check that element in the response list with "id" equals to value of saved property "versionId" exists
+
+
+ Scenario: Update version
+ When I want to create input data
+ Then I want to update the input property "description" with value "workflow version description"
+ Then I want to create for path "/workflows/{item.id}/versions" with the input data from the context
+ Then I want to copy to property "versionId" from response data path "id"
+
+ Then I want to update the input property "description" with value "workflow version description updated"
+ Then I want to set property "desc" to value "workflow version description updated"
+ Then I want to update for path "/workflows/{item.id}/versions/{versionId}" with the input data from the context
+ Then I want to get path "/workflows/{item.id}/versions/{versionId}"
+ Then I want to check that property "description" in the response equals to value of saved property "desc" \ No newline at end of file
diff --git a/workflow/workflow-bdd/features/Version_State.feature b/workflow/workflow-bdd/features/Version_State.feature
new file mode 100644
index 00000000..8c1e13fd
--- /dev/null
+++ b/workflow/workflow-bdd/features/Version_State.feature
@@ -0,0 +1,30 @@
+Feature: Workflow Version State
+
+ Background: Create workflow and first version
+ Given I want to create a Workflow
+ And I want to update the input property "description" with value "workflow version description"
+ And I want to create for path "/workflows/{item.id}/versions" with the input data from the context
+ And I want to copy to property "item.versionId" from response data path "id"
+
+ Scenario: Get state after creation
+ When I want to get path "/workflows/{item.id}/versions/{item.versionId}/state"
+ Then I want to check property "name" for value "DRAFT"
+ And I want to check property "nextStates[0]" for value "CERTIFIED"
+
+ Scenario: Update state to current state
+ Then I want the following to fail with response status code 422
+ When I want to update the input property "name" with value "DRAFT"
+ And I want to create for path "/workflows/{item.id}/versions/{item.versionId}/state" with the input data from the context
+
+ Scenario: Update state - DRAFT to CERTIFIED
+ When I want to update the input property "name" with value "CERTIFIED"
+ And I want to create for path "/workflows/{item.id}/versions/{item.versionId}/state" with the input data from the context
+ Then I want to get path "/workflows/{item.id}/versions/{item.versionId}/state"
+ And I want to check property "name" for value "CERTIFIED"
+ And I want to check property "nextStates" to have length 0
+
+ Scenario: Update state when CERTIFIED
+ When I want to update the input property "name" with value "CERTIFIED"
+ And I want to create for path "/workflows/{item.id}/versions/{item.versionId}/state" with the input data from the context
+ When I want the following to fail with response status code 422
+ Then I want to create for path "/workflows/{item.id}/versions/{item.versionId}/state" with the input data from the context \ No newline at end of file
diff --git a/workflow/workflow-bdd/features/Workflow_Create_Update.feature b/workflow/workflow-bdd/features/Workflow_Create_Update.feature
new file mode 100644
index 00000000..04a64bf8
--- /dev/null
+++ b/workflow/workflow-bdd/features/Workflow_Create_Update.feature
@@ -0,0 +1,27 @@
+Feature: Workflow Example File
+
+ Scenario: Create and get workflow
+ When I want to create input data
+ Then I want to update the input property "name" with a random value
+ Then I want to update the input property "description" with value "workflow desc"
+ Then I want to update the input property "category" with value "workflow category"
+
+ Then I want to create for path "/workflows" with the input data from the context
+ Then I want to copy to property "workflowId" from response data path "id"
+ When I want to get path "/workflows"
+ Then I want to check that element in the response list with "id" equals to value of saved property "workflowId" exists
+
+
+ Scenario: Update workflow
+ When I want to create input data
+ Then I want to update the input property "name" with a random value
+ Then I want to update the input property "description" with value "workflow desc"
+ Then I want to update the input property "category" with value "workflow category"
+ Then I want to create for path "/workflows" with the input data from the context
+ Then I want to copy to property "workflowId" from response data path "id"
+
+ Then I want to update the input property "description" with value "workflow desc updated"
+ Then I want to set property "desc" to value "workflow desc updated"
+ Then I want to update for path "/workflows/{workflowId}" with the input data from the context
+ Then I want to get path "/workflows/{workflowId}"
+ Then I want to check that property "description" in the response equals to value of saved property "desc"
diff --git a/workflow/workflow-bdd/package.json b/workflow/workflow-bdd/package.json
new file mode 100644
index 00000000..e8841bc3
--- /dev/null
+++ b/workflow/workflow-bdd/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "sdctests",
+ "version": "1.0.0",
+ "description": "SDC Cucumber testing",
+ "main": "reporter.js",
+ "directories": {
+ "doc": "docs"
+ },
+ "scripts": {
+ "test": "cucumber-js",
+ "test-and-report": "npm-run-all -c -s test cucumber-html-report",
+ "cucumber-html-report": "node plugins/reporter.js",
+ "cucumber-docs": "jsdoc ./stepDefinitions -c plugins/jsdoc_config.json --readme plugins/README.md"
+ },
+ "author": "",
+ "license": "SEE LICENSE IN LICENSE.TXT",
+ "dependencies": {
+ "assert": "^1.4.1",
+ "cucumber": "^3.2.1",
+ "cucumber-html-reporter": "^3.0.4",
+ "docdash": "^0.4.0",
+ "jsdoc": "^3.5.5",
+ "jsdoc-one-page": "0.0.5",
+ "lodash": "^4.17.4",
+ "node-zip": "^1.1.1",
+ "normalize-newline": "^3.0.0",
+ "npm-run-all": "^4.1.2",
+ "request": "^2.83.0",
+ "yamljs": "^0.3.0"
+ }
+}
diff --git a/workflow/workflow-bdd/plugins/README.md b/workflow/workflow-bdd/plugins/README.md
new file mode 100644
index 00000000..956fe772
--- /dev/null
+++ b/workflow/workflow-bdd/plugins/README.md
@@ -0,0 +1,23 @@
+<br>
+<h1>Welcome!</h1>
+This is the documentation for using the BDD testing framework for SDC.<br>
+The Modules on the left contains all steps for particalar aress and/or explanations of what they do.<br>
+<br><br>
+<h3>How to set the server configuration</h3>
+<li> Copy the config.json to devConfig.json
+<li> Replace the server and user values with the correct values
+<h3>How to run with Maven</h3>
+<li>"mvn install" will install npm if needed, download all modules and create the documentation under the "docs" folder
+<li>"mvn test-and-report" will run all tests in the features folder and create an HTML report under the "reports" folder
+<h3>How to develop tests</h3>
+You can open the project in IntelliJ and Webstorm to run and develop scenarios.<br>
+<li><b>You will need to install the Cucumber.Js plugin</b> In order to install, go to "Settings/Plugins". If cucumber.js in not on the list, go to "Browse repositories.." and install .
+<li>First time only: Right click on feature file and try to run. Now go to "Run/edit configurations" and set the "executable path" to the "node_modules\.bin\cucumber-js.cmd" under your current project.
+<li>Now you can run the feature files by right clicking on the file and selecting "Run" from IDEA.<br>
+<li>Add to existing scenarios or create new files under the "features" directory for additional tests
+<br>
+<li>You can also run a specific test from the command line by running "npm run test -- [features/path to file]
+<h3>More Information</h3>
+<li> More on <a href="https://cucumber.io/docs/reference">Cucumber</a>
+<li> More on <a herf="https://github.com/cucumber/cucumber/wiki/Gherkin">Gherkin</a>
+<li> More on <a href="https://github.com/cucumber/cucumber-js">Cucumber-js</a>
diff --git a/workflow/workflow-bdd/plugins/jsdoc_config.json b/workflow/workflow-bdd/plugins/jsdoc_config.json
new file mode 100644
index 00000000..a5a608e8
--- /dev/null
+++ b/workflow/workflow-bdd/plugins/jsdoc_config.json
@@ -0,0 +1,15 @@
+{
+ "tags": {
+ "allowUnknownTags": true
+ },
+ "templates": {
+ "default": {
+ "outputSourceFiles": false
+ }
+ },
+ "plugins": ["plugins/steps"],
+ "opts": {
+ "template": "node_modules/jsdoc-one-page",
+ "destination": "docs/"
+ }
+} \ No newline at end of file
diff --git a/workflow/workflow-bdd/plugins/reporter.js b/workflow/workflow-bdd/plugins/reporter.js
new file mode 100644
index 00000000..8913789c
--- /dev/null
+++ b/workflow/workflow-bdd/plugins/reporter.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * 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.
+ */
+var reporter = require('cucumber-html-reporter');
+
+var options = {
+ theme: 'bootstrap',
+ jsonFile: 'report/report.json',
+ output: 'report/report.html',
+ reportSuiteAsScenarios: true,
+ launchReport: false,
+ metadata: {
+ "ONAP" : "Some build",
+ "Executed": "Local"
+ }
+};
+
+reporter.generate(options);
+
diff --git a/workflow/workflow-bdd/plugins/steps.js b/workflow/workflow-bdd/plugins/steps.js
new file mode 100644
index 00000000..2faa7efb
--- /dev/null
+++ b/workflow/workflow-bdd/plugins/steps.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * 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.
+ */
+/**
+ * @module plugins/steptag
+ */
+'use strict';
+
+
+exports.handlers = {
+ /**
+ * Support @step tag.
+ *
+ * @step description
+ */
+ newDoclet: function(e) {
+ var tags = e.doclet.tags;
+ var tag;
+ var value;
+
+ // any user-defined tags in this doclet?
+ if (typeof tags !== 'undefined') {
+
+ tags = tags.filter(function($) {
+ return $.title === 'step' || $.title === 'examplefile';
+ });
+
+ if (tags.length) {
+ // take the first one
+ tag = tags[0];
+ let step = null;
+ let exampleFile = null;
+ for (tag in tags) {
+ if (tags[tag].title === "step") {
+ step = "<b>" + tags[tag].value + "</b><br>";
+ }
+ if (tags[tag].title === "examplefile") {
+ exampleFile = "<i> Example Features File: " + tags[tag].value + "</i><br>";
+ }
+ }
+ if (exampleFile !== null) {
+ step += exampleFile;
+ }
+ e.doclet.meta = e.doclet.meta || {};
+ if (e.doclet.description !== undefined) {
+ e.doclet.description = step + e.doclet.description;
+ } else {
+ e.doclet.description = step;
+ }
+ }
+ }
+ }
+}; \ No newline at end of file
diff --git a/workflow/workflow-bdd/pom.xml b/workflow/workflow-bdd/pom.xml
new file mode 100644
index 00000000..3502451c
--- /dev/null
+++ b/workflow/workflow-bdd/pom.xml
@@ -0,0 +1,173 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.openecomp.sdc</groupId>
+ <artifactId>workflow-cucumber</artifactId>
+ <name>cucumber-report</name>
+ <version>1.2.0-SNAPSHOT</version>
+
+<!-- <parent>
+ <groupId>org.onap.sdc.sdc-workflow-designer</groupId>
+ <artifactId>sdc-workflow-designer</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>-->
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.6.1</version>
+ <executions>
+ <execution>
+ <id>clean.dist.folder</id>
+ <phase>clean</phase>
+ <goals>
+ <goal>clean</goal>
+ </goals>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>${basedir}/report</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </fileset>
+ <fileset>
+ <directory>${basedir}/resources/downloads</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </fileset>
+ <fileset>
+ <directory>${basedir}/docs</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </fileset>
+ <fileset>
+ <directory>${basedir}</directory>
+ <includes>
+ <include>jenkinsConfig.json</include>
+ </includes>
+ </fileset>
+
+ </filesets>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>create-reporting-folders</id>
+ <phase>generate-sources</phase>
+ <configuration>
+ <tasks>
+ <echo message="Generate reports and downloads folders"/>
+ <mkdir dir="${basedir}/report"/>
+ <mkdir dir="${basedir}/resources/downloads"/>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- ============================================= -->
+ <!-- Build the UI module node code -->
+ <!-- ============================================= -->
+ <plugin>
+ <groupId>com.github.eirslett</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.6</version>
+
+ <configuration>
+ <installDirectory>${project.parent.parent.basedir}</installDirectory>
+ </configuration>
+
+ <executions>
+
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <configuration>
+ <nodeVersion>v9.4.0</nodeVersion>
+ <yarnVersion>v1.3.2</yarnVersion>
+ </configuration>
+ </execution>
+
+ <execution>
+ <id>yarn run install</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>install</arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn run cucumber docs</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <yarnInheritsProxyConfigFromMaven>false</yarnInheritsProxyConfigFromMaven>
+ <arguments>run cucumber-docs</arguments>
+ </configuration>
+ </execution>
+
+ <execution>
+ <id>yarn run cucumber test</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <yarnInheritsProxyConfigFromMaven>false</yarnInheritsProxyConfigFromMaven>
+ <arguments>run test-and-report</arguments>
+ </configuration>
+ <phase>test</phase>
+ </execution>
+
+
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-config</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${basedir}</outputDirectory>
+ <resources>
+ <resource>
+ <directory>${basedir}/resources</directory>
+ <includes>
+ <include>jenkinsConfig.json</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+
+</project>
diff --git a/workflow/workflow-bdd/resources/json/createWorkflow.json b/workflow/workflow-bdd/resources/json/createWorkflow.json
new file mode 100644
index 00000000..074899e9
--- /dev/null
+++ b/workflow/workflow-bdd/resources/json/createWorkflow.json
@@ -0,0 +1 @@
+{"name":"RANDOM","description":"Workflow Description","category":"category"} \ No newline at end of file
diff --git a/workflow/workflow-bdd/stepDefinitions/Collaboration_Steps.js b/workflow/workflow-bdd/stepDefinitions/Collaboration_Steps.js
new file mode 100644
index 00000000..c4de7583
--- /dev/null
+++ b/workflow/workflow-bdd/stepDefinitions/Collaboration_Steps.js
@@ -0,0 +1,113 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * 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.
+ */
+const {Then, When, Given} = require('cucumber');
+const assert = require('assert');
+const util = require('./Utils.js');
+
+/**
+ * @module Collaboration
+ * @description Adds the user with the given user ID as a contributor on the item
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to add user {string} as a contributor to this Item
+ **/
+When('I want to add user {string} as a contributor to this Item', function(string) {
+ let path = '/items/' + this.context.item.id + '/permissions/Contributor';
+ let inputData = {removedUsersIds:[],addedUsersIds:[string]};
+ return util.request(this.context, 'PUT', path, inputData);
+});
+
+/**
+ * @module Collaboration
+ * @description Adds the user with the given user ID as a contributor on the item
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to remove user {string} as a contributor to this Item
+ **/
+When('I want to remove user {string} as a contributor to this Item', function(string) {
+ let path = '/items/' + this.context.item.id + '/permissions/Contributor';
+ let inputData = {removedUsersIds:[string],addedUsersIds:[]};
+ return util.request(this.context, 'PUT', path, inputData);
+});
+
+/**
+ * @module Collaboration
+ * @description Changes the owner to the given User ID
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to change the owner to user {string} on this Item
+ **/
+When('I want to change the owner to user {string} on this Item', function(string) {
+ let path = '/items/' + this.context.item.id + '/permissions/Owner';
+ let inputData = {removedUsersIds:[],addedUsersIds:[string]};
+ return util.request(this.context, 'PUT', path, inputData);
+});
+
+
+/**
+ * @module Collaboration
+ * @description Checks the role for a user on the item by User id and Role can be either: Contributor/Owner
+ * @exampleFile Example_Collaboration.feature
+ * @step I want check user {string} has role {string} on this Item
+ **/
+When('I want to check user {string} has role {string} on this Item', function(string, string2) {
+ let path = '/items/' + this.context.item.id + '/permissions';
+ return util.request(this.context, 'GET', path).then(results => {
+ for (i in results.data.results) {
+ if (results.data.results[i].userId === string) {
+ assert.equal(string2.toLowerCase(), results.data.results[i].permission.toLowerCase());
+ return;
+ }
+ }
+ assert.fail('User not found');
+ });
+});
+
+/**
+ * @module Collaboration
+ * @description Checks the user wth this Id has no permissions on this item
+ * @exampleFile Example_Collaboration.feature
+ * @step I want check user {string} has rno permissions on this Item
+ **/
+When('I want to check user {string} has no permissions on this Item', function(string) {
+ let path = '/items/' + this.context.item.id + '/permissions';
+ return util.request(this.context, 'GET', path).then(results => {
+ for (i in results.data.results) {
+ if (results.data.results[i].userId === string) {
+ assert.fail('Found', null, 'User should not have permissions');
+ return;
+ }
+ }
+ });
+});
+
+/**
+ * @module Collaboration
+ * @description Gets the permissions for the Item
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to get the permissions for this Item
+ **/
+When('I want to get the permissions for this Item', function() {
+ let path = '/items/' + this.context.item.id + '/permissions';
+ return util.request(this.context, 'GET', path);
+});
+
+/**
+ * @module Collaboration
+ * @description Changes the user for the Rest calls
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to set the user to {string}
+ **/
+When('I want to set the user to {string}', function(string) {
+ this.context.headers['onboarding'].USER_ID = string;
+});
diff --git a/workflow/workflow-bdd/stepDefinitions/General_Steps.js b/workflow/workflow-bdd/stepDefinitions/General_Steps.js
new file mode 100644
index 00000000..0550e415
--- /dev/null
+++ b/workflow/workflow-bdd/stepDefinitions/General_Steps.js
@@ -0,0 +1,321 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * 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.
+ */
+const {Then, When, Given} = require('cucumber');
+const assert = require('assert');
+const _ = require('lodash');
+const normalizeNewline = require('normalize-newline');
+require('node-zip');
+YAML = require('yamljs');
+const fs = require('fs');
+const util = require('./Utils.js');
+
+function getPath(path, context) {
+ let compiled = _.template(path);
+ return compiled(context);
+}
+
+/**
+ * @module ContextData
+ * @description Use with "Given". Use ONLY for local testing when you know the value of the Item you want to use
+ * instead of creating a new one.
+ * @step Item {string} and version Id {string}
+ **/
+Given('Item {string} and version Id {string}', function (string, string2) {
+ this.context.item.id = string;
+ this.context.item.versionId = string2;
+});
+/**
+ * @module ContextData
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @description Response Data::<br>
+ * """<br>
+ * {jsonObject}<br>
+ * """<br>
+ * @step Use with "Given". Use ONLY for local testing, creates a response data object
+ **/
+Given('Response Data:', function (docString) {
+ this.context.responseData = JSON.parse(docString);
+});
+
+/**
+ * @module ContextData
+ * @description Copy a property from the response data to context Item data, example: item.componentId
+ * @step I want to save on the context for {string} property {string} with value {string}
+ **/
+Then('I want to save on the context for {string} property {string} with value {string}', function(string, string1, string2) {
+ assert.equal(_.includes(['Item'], string), true);
+ let val = _.get(this.context.responseData, string2);
+ _.set(this.context, string1, val);
+});
+/**
+ * @module ContextData
+ * @description Copy a property from the response data to saved data on the context. Example: save newly generated IDs. Response data value can be from a path, xample: results[0].id
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to save to property {string} from response data path {string}
+ **/
+Then('I want to copy to property {string} from response data path {string}', function(string, string2) {
+ let val = _.get(this.context.responseData, string2);
+ _.set(this.context, string, val);
+});
+/**
+ * @module ContextData
+ * @description This will set the value of a saved property on the context
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to set property {string} to value {string}
+ **/
+Then('I want to set property {string} to value {string}', function(string, string2) {
+ _.set(this.context, string, string2);
+});
+
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a value. property can be a path (example: results[0].id)
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} for value {string}
+ **/
+Then('I want to check property {string} for value {string}', function(string, string2) {
+ assert.equal(_.get(this.context.responseData, string), string2);
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a value. property can be a path
+ * (example: results[0].id). Supports comparison to a long String by allowing a line break
+ * @exampleFile VirtualMachineInterfaceValidationHeatResourceMissingProperties.feature
+ * @step I want to check property {string} for value {string}
+ **/
+
+Then('I want to check property {string} for value:', function(string, docString) {
+ assert.equal(_.get(this.context.responseData, string), docString.trim());
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a integer. property can be a path (example: results[0].id)
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} for value {int}
+ **/
+Then('I want to check property {string} for value {int}', function(string, int) {
+ assert.equal(_.get(this.context.responseData, string), int);
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a boolean. property can be a path (example: results[0].id)
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} to be "True/False"
+ **/
+Then('I want to check property {string} to be {word}', function(string, string2) {
+ assert.equal(_.get(this.context.responseData, string), string2.toLowerCase() == "true");
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a boolean. property can be a path (example: results[0].id)
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} to have length {int}
+ **/
+Then('I want to check property {string} to have length {int}', function(string, intLength) {
+ let arrayProp = _.get(this.context.responseData, string);
+ assert.equal(arrayProp.length, intLength);
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and make sure it exists
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} exists
+ **/
+Then('I want to check property {string} exists', function(string) {
+ assert.equal(_.has(this.context.responseData, string), true);
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and make sure it does not exist
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} does not exist
+ **/
+Then('I want to check property {string} does not exist', function(string) {
+ assert.equal(_.has(this.context.responseData, string), false);
+});
+
+/**
+* @module ContextData
+* @description Use during development to see what is on the context
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+* @step I want to print context data
+**/
+Then('I want to print the context data', function() {
+ console.log('------------ context ---------------');
+ console.log(JSON.stringify(this.context, null, 2));
+ console.log('--------------------------------------');
+});
+/**
+ * @module ContextData
+ * @description Set this in order to check that the following Rest call will not have response code 200
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want the following to fail
+ **/
+Then('I want the following to fail', function() {
+ this.context.shouldFail = true;
+});
+
+/**
+ * @module ContextData
+ * @description Set this in order to check that the following Rest call will not have response code 200
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want the following to fail
+ **/
+Then('I want the following to fail with response status code {int}', function(int) {
+ this.context.shouldFail = true;
+ this.context.responseStatusCode = int;
+});
+
+/**
+ * @module ContextData
+ * @description Set this in order to check that the following Rest call will have the error code on the return data
+ * @exampleFile Example_VSP.feature
+ * @step I want the following to fail with error code {string}
+ **/
+Then('I want the following to fail with error code {string}', function(string) {
+ this.context.shouldFail = true;
+ this.context.errorCode = string;
+});
+
+
+/**
+ * @module ContextData
+ * @description Set this in order to check that the following Rest call will have the error message on the return data
+ * @exampleFile DeleteVLMCertified.feature
+ * @step I want the following to fail with error message {string}
+ **/
+Then('I want the following to fail with error message {string}', function(string) {
+ this.context.shouldFail = true;
+ let errorMessage = getPath(string, this.context);
+ this.context.errorMessage = errorMessage;
+});
+
+/**
+ * @module ZipData
+ * @description Use this in order to extract a file from a zip file and to compare it to a local file (string comparison).
+ * @exampleFile Example_VSP.feature
+ * @step I want to compare the content of the entry {string} in the zip {string} with file {string}
+ **/
+Then ('I want to compare the content of the entry {string} in the zip {string} with file {string}', function (string, string2, string3) {
+ let zipFile = fs.readFileSync(string2, 'binary');
+ let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
+ let fileData = zip.files[string]._data;
+ let compareFileData = fs.readFileSync(string3, {encoding: 'ascii'});
+ assert.equal(normalizeNewline(compareFileData), normalizeNewline(fileData));
+});
+
+/**
+ * @module ZipData
+ * @description Loads the yaml from zip file onto the context responseData as JSON for running checks on the output
+ * @exampleFile Example_VSP.feature
+ * @step I want to load the yaml content of the entry {string} in the zip {string} to context
+ **/
+Then ('I want to load the yaml content of the entry {string} in the zip {string} to context', function (string, string2, callback) {
+ let zipFile = fs.readFileSync(string2, 'binary');
+ let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
+ let fileData = zip.files[string]._data;
+ let nativeObject = YAML.parse(fileData);
+ this.context.responseData = nativeObject;
+ callback();
+});
+
+
+/**
+ * @module ZipData
+ * @description Loads the json from zip file onto the context responseData for running check son the output
+ * @exampleFile Example_VSP.feature
+ * @step I want to load the json content of the entry {string} in the zip {string} to context
+ **/
+When('I want to load the json content of the entry {string} in the zip {string} to context', function (string, string2, callback) {
+ let zipFile = fs.readFileSync(string2, 'binary');
+ let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
+ let str = zip.files[string]._data;
+ this.context.responseData = JSON.parse(str);
+ callback();
+});
+
+/**
+ * @module ResponseData
+ * @description Check that the result list doesn't contain an element with property x which has value
+ * equals to saved property y
+ * @exampleFile ListItemsFilters.feature
+ * @step I want to check that element in the response list with {string} equals to value of saved property {string} does not exist
+ **/
+Then('I want to check that element in the response list with {string} equals to value of saved property {string} does not exist', function (propertyPath, valueProperty) {
+ const results = this.context.responseData.results;
+ assert.equal(results.find(result => this.context[valueProperty] === _.get(result, propertyPath)), undefined);
+});
+
+/**
+ * @module ResponseData
+ * @description Check that the result list contains an element with property x which has value
+ * equals to saved property y
+ * @exampleFile ListItemsFilters.feature
+ * @step I want to check that element in the response list with {string} equals to value of saved property {string} exists
+ **/
+Then('I want to check that element in the response list with {string} equals to value of saved property {string} exists', function(propertyPath, valueProperty) {
+ const results = this.context.responseData.results;
+ assert.notEqual(results.find(result => this.context[valueProperty] === _.get(result, propertyPath)), undefined);
+});
+
+
+Then('I want to check that property {string} in the response equals to value of saved property {string}', function(propertyPath, valueProperty) {
+ const results = this.context.responseData;
+ assert.equal(results[propertyPath],this.context[valueProperty]);
+});
+
+/**
+ * @module ResponseData
+ * @description Check that the itemId from context exits in result of responseData
+ * exampleFile ArchiveItem.feature
+ * step I want to check that item exits in response
+ **/
+Then('I want to check that item exits in response', function() {
+
+ const id = this.context.item.id;
+ const results = this.context.responseData.results;
+ var testResult = false;
+
+ for(var i=0; i< results.length; i++){
+ if ( id == results[i].id){
+ testResult = true;
+ }
+ }
+
+ assert.equal(testResult,true);
+});
+
+
+/**
+ * @module ResponseData
+ * @description Check that the itemId from context does NOT exits in result of responseData
+ * exampleFile ArchiveItem.feature
+ * step I want to check that item does not exits in response
+ **/
+Then('I want to check that item does not exits in response', function() {
+
+ const id = this.context.item.id;
+ const results = this.context.responseData.results;
+ var testResult = false;
+
+ for(var i=0; i< results.length; i++){
+ if ( id == results[i].id){
+ testResult = true;
+ }
+ }
+
+ assert.equal(testResult,false);
+}); \ No newline at end of file
diff --git a/workflow/workflow-bdd/stepDefinitions/InputData_steps.js b/workflow/workflow-bdd/stepDefinitions/InputData_steps.js
new file mode 100644
index 00000000..73695d0e
--- /dev/null
+++ b/workflow/workflow-bdd/stepDefinitions/InputData_steps.js
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * 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.
+ */
+const {Then, When, Given} = require('cucumber');
+const assert = require('assert');
+const _ = require('lodash');
+const fs = require('fs');
+const util = require('./Utils.js');
+
+/**
+ * @module InputData
+ * @description creates an ampty input data object
+ * @exampleFile Example_Rest_Calls.feature, Example_VLM.feature
+ * @step I want to create input data
+ **/
+When('I want to create input data', function () {
+ this.context.inputData = {};
+});
+
+/**
+ * @module InputData
+ * @exampleFile Example_Heat.feature
+ * @description I want to set the input data to:<br>
+ * """<br>
+ * {jsonObject}<br>
+ * """<br>
+ * @step creates an input data element with the given json object
+ **/
+When('I want to set the input data to:', function (docString) {
+ this.context.inputData = JSON.parse(docString);
+});
+
+/**
+ * @module InputData
+ * @description creates an input data object from the json in the given file
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to set the input data to file {string}
+ **/
+When('I want to set the input data to file {string}', function (string) {
+ this.context.inputData = util.getJSONFromFile(string);
+});
+
+/**
+ * @module InputData
+ * @description sets the property on the input data to the given value
+ * @exampleFile Example_Rest_Calls.feature, Example_VLM.feature
+ * @step I want to update the input property {string} with value {string}
+ **/
+Then('I want to update the input property {string} with value {string}', function(string, string2) {
+ _.set(this.context.inputData, string, string2);
+});
+
+/**
+ * @module InputData
+ * @description removes a property from the input data object
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to remove {string} from the input data
+ **/
+Then('I want to remove {string} from the input data', function(string) {
+ delete this.context.inputData[string];
+});
+
+/**
+ * @module InputData
+ * @description sets the input data property to a random value
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to update the input property {string} with a random value
+ **/
+Then('I want to update the input property {string} with a random value', function(string) {
+ _.set(this.context.inputData, string, util.random());
+});
diff --git a/workflow/workflow-bdd/stepDefinitions/InterfaceOperationSteps.js b/workflow/workflow-bdd/stepDefinitions/InterfaceOperationSteps.js
new file mode 100644
index 00000000..4c00debc
--- /dev/null
+++ b/workflow/workflow-bdd/stepDefinitions/InterfaceOperationSteps.js
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * 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.
+ */
+const {Then, When} = require('cucumber');
+const assert = require('assert');
+const util = require('./Utils.js');
+
+
+When('I want to create a VF', function() {
+ let inputData = util.getJSONFromFile('resources/json/operation/createVF_From_Catalog.json');
+
+ inputData.name = util.random();
+ inputData.tags[0] = util.random();
+
+ let path = '/catalog/resources';
+ return util.request(this.context, 'POST', path, inputData, false, 'vf').then(result => {
+ this.context.item = {uniqueId : result.data.uniqueId, id : result.data.inputs[0].uniqueId, name : result.data.inputs[0].name};
+ this.context.vf = {uniqueId : result.data.uniqueId, id : result.data.inputs[0].uniqueId, name : result.data.inputs[0].name};
+});
+});
+
+function makeType() {
+ var text = "";
+ var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+ for (var i = 0; i < 5; i++)
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
+
+ return text;
+}
+
+When('I want to create an Operation', function() {
+ let inputData = util.getJSONFromFile('resources/json/operation/createOperation.json');
+ //let path = '/catalog/resources/f3dc81bb-85e9-4dfd-bd1b-37f5dc5e5534/interfaceOperations';
+ let path = '/catalog/resources/' + this.context.vf.uniqueId +'/interfaceOperations';
+
+ inputData.interfaceOperations.create.operationType = makeType();
+ inputData.interfaceOperations.create.inputParams.listToscaDataDefinition[0].paramName = util.random();
+ inputData.interfaceOperations.create.inputParams.listToscaDataDefinition[0].paramId = this.context.vf.id;
+
+ return util.request(this.context, 'POST', path, inputData, false, 'vf').then(result => {
+ this.context.item = {uniqueId : result.data.uniqueId, operationType : result.data.operationType};
+ this.context.operation = {uniqueId : result.data.uniqueId, operationType : result.data.operationType};
+});
+});
+
+
+
+When('I want to list Operations', function () {
+ let path = '/catalog/resources/' + this.context.vf.uniqueId + '/filteredDataByParams?include=interfaces';
+ return util.request(this.context, 'GET', path, null, false, 'vf').then((result)=> {
+});
+});
+
+
+When('I want to get an Operation by Id', function () {
+ let path = '/catalog/resources/' + this.context.vf.uniqueId + '/interfaceOperations/' + this.context.operation.uniqueId;
+ return util.request(this.context, 'GET', path, null, false, 'vf').then((result)=> {
+ this.context.item ={uniqueId : result.data.uniqueId, operationType: result.data.operationType};
+ this.context.operation = {uniqueId : result.data.uniqueId, operationType : result.data.operationType};
+});
+});
+
+
+When('I want to update an Operation', function () {
+ let inputData = util.getJSONFromFile('resources/json/operation/updateOperation.json');
+ let path = '/catalog/resources/' + this.context.vf.uniqueId + '/interfaceOperations/';
+ inputData.interfaceOperations.create.uniqueId = this.context.operation.uniqueId;
+ inputData.interfaceOperations.create.operationType = this.context.operation.operationType;
+ inputData.interfaceOperations.create.inputParams.listToscaDataDefinition[0].paramName = util.random();
+ inputData.interfaceOperations.create.inputParams.listToscaDataDefinition[0].paramId = this.context.vf.id;
+ return util.request(this.context, 'PUT', path, inputData, false, 'vf').then((result)=> {
+ this.context.item ={uniqueId : result.data.uniqueId, operationType: result.data.operationType};
+ this.context.operation = {uniqueId : result.data.uniqueId, operationType : result.data.operationType};
+});
+});
+
+
+When('I want to delete an Operation', function() {
+ let path = '/catalog/resources/' + this.context.vf.uniqueId + '/interfaceOperations/' + this.context.operation.uniqueId;
+ return util.request(this.context, 'DELETE', path, null, false, 'vf');
+});
+
+
+When('I want to checkin this VF', function () {
+ let path = '/catalog/resources/' + this.context.vf.uniqueId + '/lifecycleState/CHECKIN' ;
+ let inputData = {userRemarks: 'checkin'};
+ return util.request(this.context, 'POST', path, inputData, false, 'vf').then((result)=> {
+ this.context.item ={uniqueId : result.data.uniqueId};
+ this.context.vf = {uniqueId : result.data.uniqueId};
+});
+});
+
+
+Then('I want to submit this VF', function () {
+ let path = '/catalog/resources/' + this.context.vf.uniqueId + '/lifecycleState/certificationRequest' ;
+ let inputData = {userRemarks: 'submit'};
+ return util.request(this.context, 'POST', path, inputData, false, 'vf').then((result)=> {
+ this.context.item ={uniqueId : result.data.uniqueId};
+ this.context.vf = {uniqueId : result.data.uniqueId};
+});
+});
+
+
+
+
diff --git a/workflow/workflow-bdd/stepDefinitions/Item_steps.js b/workflow/workflow-bdd/stepDefinitions/Item_steps.js
new file mode 100644
index 00000000..3ff7f20f
--- /dev/null
+++ b/workflow/workflow-bdd/stepDefinitions/Item_steps.js
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * 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.
+ */
+const {Then, When} = require('cucumber');
+const assert = require('assert');
+const util = require('./Utils.js');
+/**
+ * @module Item
+ * @description uses item id and version id from context
+ * @exampleFile Example_VSP.feature, Example_VLM.feature
+ * @step I want to make sure this Item has status {string}
+ **/
+Then('I want to make sure this Item has status {string}', function (string) {
+ let path = '/items/' + this.context.item.id + '/versions';
+ return util.request(this.context, 'GET', path).then(result => {
+ assert.equal(result.data.results[0].id, this.context.item.versionId);
+ assert.equal(result.data.results[0].status, string);
+ });
+});
+/**
+ * @module Item
+ * @description uses item id and version id from context
+ * @exampleFile Example_VSP.feature, Example_VLM.feature
+ * @step I want to commit this Item
+ **/
+Then('I want to commit this Item', function () {
+ let path = '/items/' + this.context.item.id + '/versions/' + this.context.item.versionId + '/actions';
+ let inputData = {action: 'Commit', commitRequest: {message: '00Behave'}};
+ return util.request(this.context, 'PUT', path, inputData);
+});
+/**
+ * @module Item
+ * @description creates a new major version. item id and version id from context
+ * @exampleFile Example_VLM.feature
+ * @step I want to create a new version for this Item
+ **/
+Then('I want to create a new version for this Item', function () {
+ let path = '/items/' + this.context.item.id + '/versions/' + this.context.item.versionId;
+ let inputData = {description: 'Behave Version', creationMethod: 'major'};
+ return util.request(this.context, 'POST', path, inputData).then(result => {
+ assert.equal(result.data.status, 'Draft');
+ });
+});
+/**
+ * @module Item
+ * @description reverts to a revision with a given saved property. Should be set from the revision list first
+ * @exampleFile Example_VLM.feature
+ * @step I want to commit this Item
+ **/
+Then('I want to revert this Item to the revision with the value from saved property {string}', function (string) {
+ let path = '/items/' + this.context.item.id + '/versions/' + this.context.item.versionId + '/actions';
+ let inputData = {action: 'Revert', revisionRequest: {revisionId: this.context[string]}};
+ return util.request(this.context, 'PUT', path, inputData);
+});
+
+
+/**
+ * @module Item
+ * @exampleFile ArchiveItem.feature
+ * @step I want to archive this item
+ **/
+Then('I want to archive this item', function() {
+ let path = '/items/' + this.context.item.id + '/actions'
+ let inputData = {action: 'ARCHIVE'};
+ return util.request(this.context, 'PUT', path, inputData);
+});
+
+
+/**
+ * @module Item
+ * @exampleFile ArchiveItem.feature
+ * @step I want to restore this item
+ **/
+Then('I want to restore this item', function() {
+ let path = '/items/' + this.context.item.id + '/actions'
+ let inputData = {action: 'RESTORE'};
+ return util.request(this.context, 'PUT', path, inputData);
+});
+
diff --git a/workflow/workflow-bdd/stepDefinitions/REST_Steps.js b/workflow/workflow-bdd/stepDefinitions/REST_Steps.js
new file mode 100644
index 00000000..c3844124
--- /dev/null
+++ b/workflow/workflow-bdd/stepDefinitions/REST_Steps.js
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+const {When} = require('cucumber');
+const _ = require('lodash');
+const util = require('./Utils.js');
+_.templateSettings.interpolate = /{([\s\S]+?)}/g;
+
+function getPath(path, context) {
+ let compiled = _.template(path);
+ return compiled(context);
+}
+/**
+ * @module Rest_Calls
+ * @description makes a GET request to the given path (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to get path {string}
+ **/
+When('I want to get path {string}', function(string) {
+ let path = getPath(string, this.context);
+ return util.request(this.context, 'GET', path);
+});
+
+/**
+ * @module Rest_Calls
+ * @description makes a DELETE request to the given path and appends the saved property (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to delete for path {string} with the value from saved property {string}
+ **/
+When('I want to delete for path {string} with the value from saved property {string}', function(string, string2) {
+ let path = getPath(string, this.context);
+ path += '/' + this.context[string2];
+ return util.request(this.context, 'DELETE', path);
+});
+
+/**
+ * @module Rest_Calls
+ * @description makes a DELETE request to the given path and appends the saved property (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to delete for path {string} with the value from saved property {string}
+ **/
+When('I want to delete for path {string}', function (string) {
+ let path = getPath(string, this.context);
+ //path += '/' + this.context[string2];
+ return util.request(this.context, 'DELETE', path);
+});
+
+/**
+ * @module Rest_Calls
+ * @description makes a PUT request to the given path and sends the input data from the context (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to update for path {string} with the input data from the context
+ **/
+When('I want to update for path {string} with the input data from the context', function(string) {
+ let path = getPath(string, this.context);
+ return util.request(this.context, 'PUT', path, this.context.inputData);
+});
+
+/**
+ * @module Rest_Calls
+ * @description makes a POST request to the given path and sends the input data from the context (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to create for path {string} with the input data from the context
+ **/
+When('I want to create for path {string} with the input data from the context', function(string) {
+ let path = getPath(string, this.context);
+ return util.request(this.context, 'POST', path, this.context.inputData);
+});
diff --git a/workflow/workflow-bdd/stepDefinitions/Utils.js b/workflow/workflow-bdd/stepDefinitions/Utils.js
new file mode 100644
index 00000000..6f8a7a5c
--- /dev/null
+++ b/workflow/workflow-bdd/stepDefinitions/Utils.js
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * 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.
+ */
+const request = require('request');
+const fs = require('fs');
+require('node-zip');
+
+function _request(context, method, path, data, isBinary=false, type='onboarding') {
+ let server = context.getUrlForType(type);
+
+ let options = {
+ method: method,
+ url: server + path,
+ headers: context.headers[type]
+ };
+ console.log('--> Calling REST ' + options.method +' url: ' + options.url);
+
+ return new Promise(function (resolve, reject) {
+ if (method === 'POST' || method === 'PUT') {
+ if (isBinary) {
+ var formData = {
+ upload: fs.createReadStream(data),
+ };
+ options.formData = formData;
+ } else {
+ options.json = data;
+ }
+ }
+ request(options, function (err, result, data) {
+ context.inputData = null;
+ if (err) {
+ console.error('Request URL: ' + result.request.uri.href);
+ console.error('Request Method: ' + result.request.method);
+ console.error('Response Status Code: ' +result.statusCode);
+ console.log(err);
+ reject(err);
+ } else {
+ let isExpected = (context.shouldFail) ? (result.statusCode != 200 && result.statusCode != 201) : (result.statusCode == 200 || result.statusCode == 201);
+ if (!isExpected) {
+ console.error('Request URL: ' + result.request.uri.href);
+ console.error('Request Method: ' + result.request.method);
+ console.error('Response Status Code: ' +result.statusCode);
+ console.error(result.body);
+ reject('Status Code was ' + result.statusCode);
+ }
+ if (context.shouldFail && context.responseStatusCode) {
+ if (result.statusCode !== context.responseStatusCode) {
+ reject('Response Status Code was ' + result.statusCode + ' instead of ' + context.responseStatusCode);
+ }
+ }
+ if (context.shouldFail && context.errorCode) {
+ if (typeof data === 'string' && data) {
+ data = JSON.parse(data);
+ }
+ let errorCode = data.errorCode;
+ let contextErrorCode = context.errorCode;
+ context.errorCode = null;
+ if (errorCode !== contextErrorCode) {
+ reject('Error Code was ' + errorCode + ' instead of ' + contextErrorCode);
+ }
+ }
+ if (context.shouldFail && context.errorMessage) {
+ if (typeof data === 'string' && data) {
+ data = JSON.parse(data);
+ }
+ let errorMessage = data.message;
+ let contextErrorMessage = context.errorMessage;
+ context.errorMessage = null;
+ if (errorMessage !== contextErrorMessage) {
+ reject('Error Message was ' + errorMessage + ' instead of ' + contextErrorMessage);
+ }
+ }
+ if (context.shouldFail) {
+ context.shouldFail = false;
+ resolve({statusCode: result.statusCode, data: {}});
+ return;
+ }
+ if (method === 'GET' && isBinary) {
+ // downloading (NetworkPackage) files
+ return ({
+ blob: blobUtil.createBlob([data], {type: 'text/plain'}),
+ headers: result.headers
+ });
+ } else {
+ if (typeof data === 'string' && data) {
+ data = JSON.parse(data);
+ }
+ context.responseData = data;
+ context.inputData = data;
+ resolve({statusCode: result.statusCode, data: data});
+ }
+ }
+ });
+ });
+}
+
+function download(context, path, filePath, callback, type='onboarding') {
+ let server = context.getUrlForType(type);
+ let options = {
+ method: 'GET',
+ url: server + path,
+ headers: context.headers[type]
+ };
+ console.log('--> Calling REST download url: ' + options.url);
+
+ var file = fs.createWriteStream(filePath);
+ var r = request(options).pipe(file);
+ r.on('error', function (err) {
+ console.log(err);
+ callback(err);
+ });
+ r.on('finish', function () {
+ file.close();
+ let zipFile = fs.readFileSync(filePath, 'binary');
+ let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
+ if (zip.files['MANIFEST.json']) {
+ let manifestData = zip.files['MANIFEST.json']._data;
+ manifestData = manifestData.replace(/\\n/g, '');
+ context.responseData = JSON.parse(manifestData);
+ }
+ callback();
+ });
+
+};
+
+function _random() {
+ let d = new Date();
+ return d.getTime().toString().split('').reverse().join('');
+}
+
+function _getJSONFromFile(file) {
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
+}
+
+
+module.exports = {
+ request: _request,
+ random : _random,
+ getJSONFromFile: _getJSONFromFile,
+ download: download
+};
diff --git a/workflow/workflow-bdd/stepDefinitions/Workflow_Steps.js b/workflow/workflow-bdd/stepDefinitions/Workflow_Steps.js
new file mode 100644
index 00000000..59c95d89
--- /dev/null
+++ b/workflow/workflow-bdd/stepDefinitions/Workflow_Steps.js
@@ -0,0 +1,19 @@
+/**
+ * @module WORKFLOW
+ * @description Creates a new WORKFLOW with a random name and saves the id and versionId on the context item object and the context vlm object<br>
+ * Input data will be taken from the 'resources/json/createWorkflow.json' file.
+ * @step I want to create a Workflow
+ **/
+
+const {Then, When, Given} = require('cucumber');
+const assert = require('assert');
+const util = require('./Utils.js');
+
+When('I want to create a Workflow', function() {
+ let inputData = util.getJSONFromFile('resources/json/createWorkflow.json');
+ inputData.name = util.random();
+ let path = '/workflows';
+ return util.request(this.context, 'POST', path, inputData).then(result => {
+ this.context.item ={id : result.data.id};
+});
+}); \ No newline at end of file
diff --git a/workflow/workflow-bdd/stepDefinitions/world.js b/workflow/workflow-bdd/stepDefinitions/world.js
new file mode 100644
index 00000000..cf749e66
--- /dev/null
+++ b/workflow/workflow-bdd/stepDefinitions/world.js
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * 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.
+ */
+const { setWorldConstructor } = require('cucumber');
+const _ = require('lodash');
+
+let config = require('../config.json');
+let localConfig = {};
+try {
+ localConfig = require('../devConfig.json');
+} catch (e) {
+ try {
+ localConfig = require('../jenkinsConfig.json');
+ } catch (e) {
+ console.error("no env configuration was found!");
+ }
+}
+
+config = _.merge(config, localConfig);
+var {setDefaultTimeout} = require('cucumber');
+
+
+/**
+ * @module Context
+ * @description Context that is used per feature file and can be accessed as 'this.context' in all steps.<Br>
+ *<Br>
+ * Contains the following items:<br>
+ * <li>this.context.server <ul>REST server and onboarding prefix including version. set either in configuration file or from the command line or SERVER environment variable</ul>
+ * <li>this.context <ul>Object with properties that were saved in the steps.</ul>
+ * <li>this.context.inputdata <ul><b>Automatically updated with the last responseData from the Rest call</b><br>Object with properties that were prepares in the steps.</ul>
+ * <li>this.context.responseData <ul>Response from the last REST call.</ul>
+ **/
+class CustomWorld {
+ constructor(options) {
+ this.context = {};
+ this.context.headers = {};
+ let typeName;
+ for (typeName in config) {
+ this.context.headers[typeName] = {};
+ if (config[typeName].user) {
+ this.context.headers[typeName]['USER_ID'] = config[typeName].user;
+ }
+ }
+
+ this.context.item = {id: null, versionId: null, componentId: null};
+
+ this.context.shouldFail = false;
+ this.context.errorCode = null;
+ this.context.inputData = null;
+ this.context.responseData = null;
+
+ this.context.defaultServerType = 'workflow';
+
+ this.config = config;
+
+ let context = this.context;
+ this.context.getUrlForType = (function(type) {
+ var _server = context.server;
+ var _config = config;
+ return function(type) {
+ let typeData = _config["workflow"];
+ let _url = _config.protocol + '://' +
+ typeData.server + ':' +
+ typeData.port + '/' +
+ typeData.prefix;
+ return _url;
+ }
+ })();
+
+ setDefaultTimeout(60 * 1000);
+ }
+}
+
+
+setWorldConstructor(CustomWorld);
diff --git a/workflow/workflow-designer-be/pom.xml b/workflow/workflow-designer-be/pom.xml
new file mode 100644
index 00000000..b76dc467
--- /dev/null
+++ b/workflow/workflow-designer-be/pom.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>workflow-designer-be</artifactId>
+
+ <parent>
+ <groupId>org.onap.sdc.workflow_designer</groupId>
+ <artifactId>workflow-designer-parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </parent>
+
+ <properties>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ <spring.boot.version>2.0.3.RELEASE</spring.boot.version>
+ <mapstruct.version>1.2.0.Final</mapstruct.version>
+ <lombok.version>1.18.0</lombok.version>
+ <springfox.version>2.8.0</springfox.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring.boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <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-devtools</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger-ui</artifactId>
+ <version>${springfox.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger2</artifactId>
+ <version>${springfox.version}</version>
+ </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>
+ <dependency>
+ <groupId>org.mapstruct</groupId>
+ <artifactId>mapstruct-jdk8</artifactId>
+ <version>${mapstruct.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mapstruct</groupId>
+ <artifactId>mapstruct-processor</artifactId>
+ <version>${mapstruct.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>${lombok.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.5.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring.boot.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <configuration>
+ <images>
+ <image>
+ <name>onap/workflow-backend</name>
+ <build>
+ <tags>
+ <tag>${project.version}</tag>
+ </tags>
+ <from>openjdk:8-jdk-alpine</from>
+ <user>root</user>
+ <assembly>
+ <descriptorRef>artifact</descriptorRef>
+ <targetDir>/</targetDir>
+ </assembly>
+ <entryPoint>java ${JAVA_OPTIONS} -jar /${project.build.finalName}.jar</entryPoint>
+ </build>
+ </image>
+ </images>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
+
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java
new file mode 100644
index 00000000..b7e3b345
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java
@@ -0,0 +1,20 @@
+package org.onap.sdc.workflow;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+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() {
+ return new JettyServletWebServerFactory();
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/RestConstants.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/RestConstants.java
new file mode 100644
index 00000000..8f02be0f
--- /dev/null
+++ b/workflow/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/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java
new file mode 100644
index 00000000..b224e84b
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java
@@ -0,0 +1,66 @@
+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.onap.sdc.workflow.services.WorkflowManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+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;
+import org.springframework.web.bind.annotation.RestController;
+
+@RequestMapping("/workflows")
+@Api("Workflows")
+@RestController("workflowController")
+public class WorkflowController {
+
+ private final WorkflowManager workflowManager;
+
+ @Autowired
+ public WorkflowController(@Qualifier("workflowManager") WorkflowManager workflowManager) {
+ this.workflowManager = workflowManager;
+ }
+
+ @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ @ApiOperation("List workflows")
+ public CollectionWrapper<Workflow> list(@RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ return new CollectionWrapper<>(workflowManager.list());
+ }
+
+ @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
+ @ApiOperation("Create workflow")
+ public ResponseEntity<Workflow> create(@RequestBody Workflow workflow,
+ @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ return new ResponseEntity<>(workflowManager.create(workflow), HttpStatus.CREATED);
+ }
+
+ @GetMapping(path = "/{workflowId}")
+ @ApiOperation("Get workflow")
+ public Workflow get(@PathVariable("workflowId") String workflowId,
+ @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ Workflow workflow = new Workflow();
+ workflow.setId(workflowId);
+ return workflowManager.get(workflow);
+ }
+
+ @PutMapping(path = "/{workflowId}", consumes = MediaType.APPLICATION_JSON_VALUE)
+ @ApiOperation("Update workflow")
+ public Workflow update(@RequestBody Workflow workflow, @PathVariable("workflowId") String workflowId,
+ @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ workflow.setId(workflowId);
+ workflowManager.update(workflow);
+ return workflow;
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java
new file mode 100644
index 00000000..6ae8e34d
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java
@@ -0,0 +1,117 @@
+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.api.types.VersionRequestDto;
+import org.onap.sdc.workflow.api.types.VersionStateDto;
+import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersion;
+import org.onap.sdc.workflow.services.WorkflowVersionManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+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;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+@RequestMapping("/workflows/{workflowId}/versions")
+@Api("Workflow versions")
+@RestController("workflowsVersionController")
+public class WorkflowVersionController {
+
+ private final WorkflowVersionManager workflowVersionManager;
+
+ @Autowired
+ public WorkflowVersionController(
+ @Qualifier("workflowVersionManager") WorkflowVersionManager workflowVersionManager) {
+ this.workflowVersionManager = workflowVersionManager;
+ }
+
+ @GetMapping
+ @ApiOperation("List workflow versions")
+ public CollectionWrapper<WorkflowVersion> list(@PathVariable("workflowId") String workflowId,
+ @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ return new CollectionWrapper<>(workflowVersionManager.list(workflowId));
+ }
+
+ @PostMapping
+ @ApiOperation("Create workflow version")
+ public ResponseEntity<WorkflowVersion> create(@RequestBody VersionRequestDto versionRequest,
+ @PathVariable("workflowId") String workflowId, @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+
+ WorkflowVersion createdVersion = workflowVersionManager.create(workflowId, versionRequest);
+ return new ResponseEntity<>(createdVersion, HttpStatus.CREATED);
+ }
+
+ @GetMapping("/{versionId}")
+ @ApiOperation("Get workflow version")
+ public WorkflowVersion get(@PathVariable("workflowId") String workflowId,
+ @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ return workflowVersionManager.get(workflowId, versionId);
+ }
+
+ @PutMapping("/{versionId}")
+ @ApiOperation("Update workflow version")
+ public void update(@RequestBody WorkflowVersion version, @PathVariable("workflowId") String workflowId,
+ @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ version.setId(versionId);
+ workflowVersionManager.update(workflowId, version);
+ }
+
+ @GetMapping("/{versionId}/state")
+ @ApiOperation("Get workflow version state")
+ public VersionStateDto getState(@PathVariable("workflowId") String workflowId,
+ @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ return new VersionStateDto(workflowVersionManager.getState(workflowId, versionId));
+ }
+
+ @PostMapping("/{versionId}/state")
+ @ApiOperation("Update workflow version state")
+ public VersionStateDto updateState(@RequestBody VersionStateDto state,
+ @PathVariable("workflowId") String workflowId, @PathVariable("versionId") String versionId,
+ @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ workflowVersionManager.updateState(workflowId, versionId, state.getName());
+ return new VersionStateDto(state.getName());
+ }
+
+ @PutMapping("/{versionId}/artifact")
+ @ApiOperation("Create/update artifact of a version")
+ public void uploadArtifact(@RequestBody MultipartFile fileToUpload, @PathVariable("workflowId") String workflowId,
+ @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ workflowVersionManager.uploadArtifact(workflowId, versionId, fileToUpload);
+ }
+
+ @GetMapping("/{versionId}/artifact")
+ @ApiOperation("Download workflow version artifact")
+ public ResponseEntity<Resource> getArtifact(@PathVariable("workflowId") String workflowId,
+ @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ ArtifactEntity artifact = workflowVersionManager.getArtifact(workflowId, versionId);
+
+ return ResponseEntity.ok()
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + artifact.getFileName())
+ .contentType(MediaType.APPLICATION_OCTET_STREAM)
+ .body(new InputStreamResource(artifact.getArtifactData()));
+ }
+
+ @DeleteMapping("/{versionId}/artifact")
+ @ApiOperation("Delete workflow version artifact")
+ public void deleteArtifact(@PathVariable("workflowId") String workflowId,
+ @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER_PARAM) String user) {
+ workflowVersionManager.deleteArtifact(workflowId, versionId);
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/exceptionshandlers/CustomizedResponseEntityExceptionHandler.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/exceptionshandlers/CustomizedResponseEntityExceptionHandler.java
new file mode 100644
index 00000000..68fd41a5
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/exceptionshandlers/CustomizedResponseEntityExceptionHandler.java
@@ -0,0 +1,48 @@
+package org.onap.sdc.workflow.api.exceptionshandlers;
+
+import static org.springframework.http.HttpStatus.FORBIDDEN;
+import static org.springframework.http.HttpStatus.NOT_FOUND;
+import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;
+
+import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
+import org.onap.sdc.workflow.services.exceptions.InvalidArtifactException;
+import org.onap.sdc.workflow.services.exceptions.UniqueValueViolationException;
+import org.onap.sdc.workflow.services.exceptions.VersionCreationException;
+import org.onap.sdc.workflow.services.exceptions.VersionModificationException;
+import org.onap.sdc.workflow.services.exceptions.VersionStateModificationException;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+
+@ControllerAdvice
+@RestController
+public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
+
+ @ExceptionHandler(UniqueValueViolationException.class)
+ public final ResponseEntity<String> handleUniqueValueViolationException(
+ UniqueValueViolationException exception) {
+ return new ResponseEntity<>(exception.getMessage(), UNPROCESSABLE_ENTITY);
+ }
+
+ @ExceptionHandler(EntityNotFoundException.class)
+ public final ResponseEntity<String> handleWorkflowNotFoundException(
+ Exception exception) {
+ return new ResponseEntity<>(exception.getMessage(), NOT_FOUND);
+ }
+
+ @ExceptionHandler({InvalidArtifactException.class, VersionModificationException.class,
+ VersionStateModificationException.class})
+ public final ResponseEntity<String> handleInvalidArtifactException(
+ Exception exception) {
+ return new ResponseEntity<>(exception.getMessage(), UNPROCESSABLE_ENTITY);
+ }
+
+
+ @ExceptionHandler(VersionCreationException.class)
+ public final ResponseEntity<String> handleVersioningErrorException(
+ VersionCreationException exception) {
+ return new ResponseEntity<>(exception.getMessage(), FORBIDDEN);
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/CollectionWrapper.java b/workflow/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/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/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionRequestDto.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionRequestDto.java
new file mode 100644
index 00000000..92ac3a73
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionRequestDto.java
@@ -0,0 +1,11 @@
+package org.onap.sdc.workflow.api.types;
+
+import lombok.Data;
+
+@Data
+public class VersionRequestDto {
+
+ private String description;
+ private String baseVersionId;
+
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionStateDto.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionStateDto.java
new file mode 100644
index 00000000..5963a2bf
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionStateDto.java
@@ -0,0 +1,20 @@
+package org.onap.sdc.workflow.api.types;
+
+import java.util.List;
+import lombok.Data;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
+
+@Data
+public class VersionStateDto {
+
+ private WorkflowVersionState name;
+ private List<WorkflowVersionState> nextStates;
+
+ public VersionStateDto() {
+ }
+
+ public VersionStateDto(WorkflowVersionState state) {
+ name = state;
+ nextStates = state.getNextStates();
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/ArtifactRepository.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/ArtifactRepository.java
new file mode 100644
index 00000000..a473f166
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/ArtifactRepository.java
@@ -0,0 +1,18 @@
+package org.onap.sdc.workflow.persistence;
+
+
+import java.util.Optional;
+import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
+
+
+public interface ArtifactRepository {
+
+ void update(String id, String versionId,ArtifactEntity artifactEntity);
+
+ Optional<ArtifactEntity> get(String id, String versionId);
+
+ void createStructure(String id, String versionId);
+
+ void delete(String id, String versionId);
+
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/UniqueValueRepository.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/UniqueValueRepository.java
new file mode 100644
index 00000000..d374a404
--- /dev/null
+++ b/workflow/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/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/impl/ArtifactRepositoryImpl.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/impl/ArtifactRepositoryImpl.java
new file mode 100644
index 00000000..9a449f0d
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/impl/ArtifactRepositoryImpl.java
@@ -0,0 +1,104 @@
+package org.onap.sdc.workflow.persistence.impl;
+
+import static org.openecomp.core.zusammen.api.ZusammenUtil.buildStructuralElement;
+import static org.openecomp.core.zusammen.api.ZusammenUtil.createSessionContext;
+
+import com.amdocs.zusammen.adaptor.inbound.api.types.item.Element;
+import com.amdocs.zusammen.adaptor.inbound.api.types.item.ZusammenElement;
+import com.amdocs.zusammen.datatypes.SessionContext;
+import com.amdocs.zusammen.datatypes.item.Action;
+import com.amdocs.zusammen.datatypes.item.ElementContext;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.commons.io.IOUtils;
+import org.onap.sdc.workflow.persistence.ArtifactRepository;
+import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
+import org.openecomp.core.zusammen.api.ZusammenAdaptor;
+import org.openecomp.core.zusammen.api.ZusammenAdaptorFactory;
+import org.openecomp.sdc.datatypes.model.ElementType;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class ArtifactRepositoryImpl implements ArtifactRepository {
+
+ private static final String FILE_NAME_PROPERTY = "fileName";
+ private static final String EMPTY_DATA = "{}";
+ private ZusammenAdaptor zusammenAdaptor = ZusammenAdaptorFactory.getInstance().createInterface();
+
+
+ @Override
+ public void update(String id, String versionId, ArtifactEntity artifactEntity) {
+
+ ZusammenElement artifactElement = buildStructuralElement(ElementType.Artifact, Action.UPDATE);
+ artifactElement.setData(artifactEntity.getArtifactData());
+ artifactElement.getInfo().addProperty(FILE_NAME_PROPERTY, artifactEntity.getFileName());
+
+ SessionContext context = createSessionContext();
+ ElementContext elementContext = new ElementContext(id, versionId);
+
+ zusammenAdaptor
+ .saveElement(context, elementContext, artifactElement, "Update WorkflowVersion Artifact Element");
+ }
+
+ @Override
+ public Optional<ArtifactEntity> get(String id, String versionId) {
+ SessionContext context = createSessionContext();
+ ElementContext elementContext = new ElementContext(id, versionId);
+
+ Optional<Element> elementOptional =
+ zusammenAdaptor.getElementByName(context, elementContext, null, ElementType.Artifact.name());
+
+ if (!elementOptional.isPresent() || hasEmptyData(elementOptional.get().getData())) {
+ return Optional.empty();
+ }
+
+ Element artifactElement = elementOptional.get();
+
+ ArtifactEntity artifact = new ArtifactEntity(artifactElement.getInfo().getProperty(FILE_NAME_PROPERTY),
+ artifactElement.getData());
+
+ return Optional.of(artifact);
+ }
+
+ @Override
+ public void createStructure(String id, String versionId) {
+ SessionContext context = createSessionContext();
+ ElementContext elementContext = new ElementContext(id, versionId);
+
+ ZusammenElement artifactElement = buildStructuralElement(ElementType.Artifact, Action.CREATE);
+ artifactElement.setData(new ByteArrayInputStream(EMPTY_DATA.getBytes()));
+
+ zusammenAdaptor
+ .saveElement(context, elementContext, artifactElement, "Create WorkflowVersion Artifact Element");
+
+ }
+
+ @Override
+ public void delete(String id, String versionId) {
+ SessionContext context = createSessionContext();
+ ElementContext elementContext = new ElementContext(id, versionId);
+
+ ZusammenElement artifactElement = buildStructuralElement(ElementType.Artifact, Action.UPDATE);
+ artifactElement.setData(new ByteArrayInputStream(EMPTY_DATA.getBytes()));
+ artifactElement.getInfo().getProperties().remove(FILE_NAME_PROPERTY);
+
+ zusammenAdaptor
+ .saveElement(context, elementContext, artifactElement, "Update WorkflowVersion Artifact Element");
+
+ }
+
+ private boolean hasEmptyData(InputStream elementData) {
+
+ byte[] byteElementData;
+ try {
+ byteElementData = IOUtils.toByteArray(elementData);
+ } catch (IOException ex) {
+ return false;
+ }
+ return Arrays.equals(EMPTY_DATA.getBytes(), byteElementData);
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/ArtifactEntity.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/ArtifactEntity.java
new file mode 100644
index 00000000..8f24ecc9
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/ArtifactEntity.java
@@ -0,0 +1,16 @@
+package org.onap.sdc.workflow.persistence.types;
+
+import java.io.InputStream;
+import lombok.Data;
+
+@Data
+public class ArtifactEntity {
+
+ private String fileName;
+ private InputStream artifactData;
+
+ public ArtifactEntity(String fileName, InputStream artifactData) {
+ this.fileName = fileName;
+ this.artifactData = artifactData;
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/UniqueValueEntity.java b/workflow/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/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/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java
new file mode 100644
index 00000000..8c66d820
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java
@@ -0,0 +1,12 @@
+package org.onap.sdc.workflow.persistence.types;
+
+
+import lombok.Data;
+
+@Data
+public class Workflow {
+
+ private String id;
+ private String name;
+ private String description;
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowProperty.java b/workflow/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/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/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowVersion.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowVersion.java
new file mode 100644
index 00000000..db0999b6
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowVersion.java
@@ -0,0 +1,26 @@
+package org.onap.sdc.workflow.persistence.types;
+
+import java.util.Date;
+import lombok.Data;
+
+
+@Data
+public class WorkflowVersion {
+
+ private String id;
+ private String name;
+ private String description;
+ private String baseId;
+ private Date creationTime;
+ private Date modificationTime;
+ private WorkflowVersionState state;
+
+
+ public WorkflowVersion(String id) {
+ this.id = id;
+ this.state = WorkflowVersionState.DRAFT;
+ }
+
+ public WorkflowVersion() {
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowVersionState.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowVersionState.java
new file mode 100644
index 00000000..9414fa17
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/WorkflowVersionState.java
@@ -0,0 +1,20 @@
+package org.onap.sdc.workflow.persistence.types;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public enum WorkflowVersionState {
+
+ CERTIFIED, DRAFT(CERTIFIED);
+
+ private final List<WorkflowVersionState> nextStates;
+
+ WorkflowVersionState(WorkflowVersionState... nextStates) {
+ this.nextStates = Collections.unmodifiableList(Arrays.asList(nextStates));
+ }
+
+ public List<WorkflowVersionState> getNextStates() {
+ return nextStates;
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/SwaggerConfig.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/SwaggerConfig.java
new file mode 100644
index 00000000..5105114f
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/SwaggerConfig.java
@@ -0,0 +1,24 @@
+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 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 api() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("org.onap.sdc.workflow.api"))
+ .paths(regex("/workflows.*"))
+ .build();
+ }
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ZusammenConfig.java b/workflow/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/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/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/filters/SessionContextFilter.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/filters/SessionContextFilter.java
new file mode 100644
index 00000000..07d8eee7
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/filters/SessionContextFilter.java
@@ -0,0 +1,64 @@
+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 "GLOBAL_USER";
+ // TODO: 7/11/2018 get user from header when collaboration will be supported
+ //((HttpServletRequest) servletRequest).getHeader(USER_ID_HEADER_PARAM);
+ }
+
+ private String getTenant() {
+ return zusammenConfig.getTenant();
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/UniqueValueService.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/UniqueValueService.java
new file mode 100644
index 00000000..a9acb816
--- /dev/null
+++ b/workflow/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.apache.commons.lang.ArrayUtils;
+import org.onap.sdc.workflow.persistence.UniqueValueRepository;
+import org.onap.sdc.workflow.persistence.types.UniqueValueEntity;
+import org.onap.sdc.workflow.services.exceptions.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 Optional<String> formatValue(String[] uniqueCombination) {
+ if (ArrayUtils.isEmpty(uniqueCombination) || getValueWithoutContext(uniqueCombination) == null) {
+ return Optional.empty();
+ }
+
+ uniqueCombination[uniqueCombination.length - 1] = getValueWithoutContext(uniqueCombination).toLowerCase();
+ return Optional.of(CommonMethods.arrayToSeparatedString(uniqueCombination, FORMATTED_UNIQUE_VALUE_SEPARATOR));
+ }
+
+ private String getValueWithoutContext(String[] uniqueCombination) {
+ return uniqueCombination[uniqueCombination.length - 1];
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowManager.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowManager.java
new file mode 100644
index 00000000..01c0b053
--- /dev/null
+++ b/workflow/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);
+
+ Workflow create(Workflow workflow);
+
+ void update(Workflow workflow);
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowVersionManager.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowVersionManager.java
new file mode 100644
index 00000000..8b4b8949
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowVersionManager.java
@@ -0,0 +1,30 @@
+package org.onap.sdc.workflow.services;
+
+import java.util.Collection;
+import org.onap.sdc.workflow.api.types.VersionRequestDto;
+import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersion;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
+import org.springframework.web.multipart.MultipartFile;
+
+
+public interface WorkflowVersionManager {
+
+ Collection<WorkflowVersion> list(String workflowId);
+
+ WorkflowVersion create(String workflowId, VersionRequestDto versionRequest);
+
+ void update(String id, WorkflowVersion version);
+
+ WorkflowVersion get(String workflowId, String versionId);
+
+ WorkflowVersionState getState(String workflowId, String versionId);
+
+ void updateState(String workflowId, String versionId, WorkflowVersionState state);
+
+ ArtifactEntity getArtifact(String workflowId, String versionId);
+
+ void deleteArtifact(String workflowId, String versionId);
+
+ void uploadArtifact(String workflowId, String versionId, MultipartFile artifact);
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/EntityNotFoundException.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/EntityNotFoundException.java
new file mode 100644
index 00000000..1ed3df5a
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/EntityNotFoundException.java
@@ -0,0 +1,8 @@
+package org.onap.sdc.workflow.services.exceptions;
+
+public class EntityNotFoundException extends RuntimeException {
+
+ public EntityNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/InvalidArtifactException.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/InvalidArtifactException.java
new file mode 100644
index 00000000..89c5fd5f
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/InvalidArtifactException.java
@@ -0,0 +1,8 @@
+package org.onap.sdc.workflow.services.exceptions;
+
+public class InvalidArtifactException extends RuntimeException {
+
+ public InvalidArtifactException(String message) {
+ super("Invalid artifact file can not be processed. Error: " + message);
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/UniqueValueViolationException.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/UniqueValueViolationException.java
new file mode 100644
index 00000000..82c97f94
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/UniqueValueViolationException.java
@@ -0,0 +1,11 @@
+package org.onap.sdc.workflow.services.exceptions;
+
+
+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/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionCreationException.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionCreationException.java
new file mode 100644
index 00000000..af01c68f
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionCreationException.java
@@ -0,0 +1,15 @@
+package org.onap.sdc.workflow.services.exceptions;
+
+public class VersionCreationException extends RuntimeException {
+
+ private static final String MSG = "Error creating a new version for workflow with id %s";
+ private static final String MSG_WITH_BASE_ID = MSG + " based on version %s";
+
+ public VersionCreationException(String workflowId, String baseVersionId) {
+ super(String.format(MSG_WITH_BASE_ID, workflowId, baseVersionId));
+ }
+
+ public VersionCreationException(String workflowId) {
+ super(String.format(MSG, workflowId));
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionModificationException.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionModificationException.java
new file mode 100644
index 00000000..ff1bf89b
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionModificationException.java
@@ -0,0 +1,10 @@
+package org.onap.sdc.workflow.services.exceptions;
+
+public class VersionModificationException extends RuntimeException {
+
+ public VersionModificationException(String workflowId, String versionId) {
+ super(String.format(
+ "Error while trying to modify version %s of workflow %s: Version is CERTIFIED and can not be edited",
+ versionId, workflowId));
+ }
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionStateModificationException.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionStateModificationException.java
new file mode 100644
index 00000000..6c4606db
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionStateModificationException.java
@@ -0,0 +1,12 @@
+package org.onap.sdc.workflow.services.exceptions;
+
+import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
+
+public class VersionStateModificationException extends RuntimeException {
+
+ public VersionStateModificationException(String workflowId, String versionId, WorkflowVersionState sourceState,
+ WorkflowVersionState targetState) {
+ super(String.format("Workflow %s, version %s: state can not be changed from %s to %s", workflowId, versionId,
+ sourceState.name(), targetState.name()));
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/CollaborationConfiguration.java b/workflow/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/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/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java
new file mode 100644
index 00000000..8ac5025a
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java
@@ -0,0 +1,79 @@
+package org.onap.sdc.workflow.services.impl;
+
+import java.util.Collection;
+import java.util.function.Predicate;
+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.exceptions.EntityNotFoundException;
+import org.onap.sdc.workflow.services.impl.mappers.WorkflowMapper;
+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_NOT_FOUND_ERROR_MSG = "Workflow with id '%s' does not exist";
+ private static final String WORKFLOW_NAME_UNIQUE_TYPE = "WORKFLOW_NAME";
+ static final Predicate<Item> ITEM_PREDICATE = item -> WORKFLOW_TYPE.equals(item.getType());
+
+ private final ItemManager itemManager;
+ private final UniqueValueService uniqueValueService;
+ private final WorkflowMapper workflowMapper;
+
+ @Autowired
+ public WorkflowManagerImpl(ItemManager itemManager,
+ @Qualifier("uniqueValueService") UniqueValueService uniqueValueService, WorkflowMapper workflowMapper) {
+ this.itemManager = itemManager;
+ this.uniqueValueService = uniqueValueService;
+ this.workflowMapper = workflowMapper;
+ }
+
+ @Override
+ public Collection<Workflow> list() {
+ return itemManager.list(ITEM_PREDICATE).stream().map(workflowMapper::itemToWorkflow)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Workflow get(Workflow workflow) {
+ Item retrievedItem = itemManager.get(workflow.getId());
+ if (retrievedItem == null) {
+ throw new EntityNotFoundException(String.format(WORKFLOW_NOT_FOUND_ERROR_MSG, workflow.getId()));
+ }
+ return this.workflowMapper.itemToWorkflow(retrievedItem);
+ }
+
+ @Override
+ public Workflow create(Workflow workflow) {
+ Item item = workflowMapper.workflowToItem(workflow);
+ item.setStatus(ItemStatus.ACTIVE);
+
+ uniqueValueService.validateUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, new String[] {workflow.getName()});
+ workflow.setId(itemManager.create(item).getId());
+ uniqueValueService.createUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, new String[] {workflow.getName()});
+ return workflow;
+ }
+
+ @Override
+ public void update(Workflow workflow) {
+ Item retrievedItem = itemManager.get(workflow.getId());
+ if (retrievedItem == null) {
+ throw new EntityNotFoundException(String.format(WORKFLOW_NOT_FOUND_ERROR_MSG, workflow.getId()));
+ }
+
+ uniqueValueService.updateUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, retrievedItem.getName(), workflow.getName());
+
+ Item item = workflowMapper.workflowToItem(workflow);
+ item.setId(workflow.getId());
+ item.setStatus(retrievedItem.getStatus());
+ item.setVersionStatusCounters(retrievedItem.getVersionStatusCounters());
+ itemManager.update(item);
+ }
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImpl.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImpl.java
new file mode 100644
index 00000000..cdfddf34
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImpl.java
@@ -0,0 +1,186 @@
+package org.onap.sdc.workflow.services.impl;
+
+import static org.openecomp.sdc.versioning.dao.types.VersionStatus.Certified;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.onap.sdc.workflow.api.types.VersionRequestDto;
+import org.onap.sdc.workflow.persistence.ArtifactRepository;
+import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersion;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
+import org.onap.sdc.workflow.services.WorkflowVersionManager;
+import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
+import org.onap.sdc.workflow.services.exceptions.InvalidArtifactException;
+import org.onap.sdc.workflow.services.exceptions.VersionCreationException;
+import org.onap.sdc.workflow.services.exceptions.VersionModificationException;
+import org.onap.sdc.workflow.services.exceptions.VersionStateModificationException;
+import org.onap.sdc.workflow.services.impl.mappers.VersionMapper;
+import org.onap.sdc.workflow.services.impl.mappers.VersionStateMapper;
+import org.openecomp.sdc.versioning.VersioningManager;
+import org.openecomp.sdc.versioning.dao.types.Version;
+import org.openecomp.sdc.versioning.types.VersionCreationMethod;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+@Service("workflowVersionManager")
+public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
+
+ private static final String VERSION_NOT_EXIST_MSG = "version with id '%s' does not exist for workflow with id '%s'";
+ private final VersioningManager versioningManager;
+ private final ArtifactRepository artifactRepository;
+ private final VersionMapper versionMapper;
+ private final VersionStateMapper versionStateMapper;
+
+
+ @Autowired
+ public WorkflowVersionManagerImpl(VersioningManager versioningManager, ArtifactRepository artifactRepository,
+ VersionMapper versionMapper, VersionStateMapper versionStateMapper) {
+ this.versioningManager = versioningManager;
+ this.artifactRepository = artifactRepository;
+ this.versionMapper = versionMapper;
+ this.versionStateMapper = versionStateMapper;
+ }
+
+ @Override
+ public Collection<WorkflowVersion> list(String workflowId) {
+ return versioningManager.list(workflowId).stream().map(versionMapper::versionToWorkflowVersion)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public WorkflowVersion get(String workflowId, String versionId) {
+ return versionMapper.versionToWorkflowVersion(getVersion(workflowId, versionId));
+ }
+
+ @Override
+ public WorkflowVersion create(String workflowId, VersionRequestDto versionRequest) {
+ List<Version> versions = versioningManager.list(workflowId);
+
+ if (versionRequest.getBaseVersionId() != null) {
+ validateVersionExistAndCertified(workflowId, versions, versionRequest.getBaseVersionId());
+ } else if (!versions.isEmpty()) {
+ throw new VersionCreationException(workflowId);
+ }
+
+ Version version = new Version();
+ version.setDescription(versionRequest.getDescription());
+ version.setBaseId(versionRequest.getBaseVersionId());
+ Version createdVersion = versioningManager.create(workflowId, version, VersionCreationMethod.major);
+
+ if (versions.isEmpty()) { // only for first version
+ artifactRepository.createStructure(workflowId, createdVersion.getId());
+ versioningManager.publish(workflowId, createdVersion, "Add workflow structure");
+ }
+
+ return versionMapper.versionToWorkflowVersion(createdVersion);
+ }
+
+ @Override
+ public void update(String workflowId, WorkflowVersion workflowVersion) {
+ Version retrievedVersion = getVersion(workflowId, workflowVersion.getId());
+ if (WorkflowVersionState.CERTIFIED
+ .equals(versionStateMapper.versionStatusToWorkflowVersionState(retrievedVersion.getStatus()))) {
+ throw new VersionModificationException(workflowId, workflowVersion.getId());
+ }
+
+ Version version = versionMapper.workflowVersionToVersion(workflowVersion);
+ version.setName(retrievedVersion.getName());
+ version.setStatus(retrievedVersion.getStatus());
+
+ versioningManager.updateVersion(workflowId, version);
+ versioningManager.publish(workflowId, version, "Update version");
+ }
+
+ @Override
+ public WorkflowVersionState getState(String workflowId, String versionId) {
+ return versionStateMapper.versionStatusToWorkflowVersionState(getVersion(workflowId, versionId).getStatus());
+ }
+
+ @Override
+ public void updateState(String workflowId, String versionId, WorkflowVersionState state) {
+ Version retrievedVersion = getVersion(workflowId, versionId);
+ WorkflowVersionState retrievedState =
+ versionStateMapper.versionStatusToWorkflowVersionState(retrievedVersion.getStatus());
+ if (WorkflowVersionState.CERTIFIED.equals(retrievedState) || retrievedState.equals(state)) {
+ throw new VersionStateModificationException(workflowId, versionId, retrievedState, state);
+ }
+
+ retrievedVersion.setStatus(versionStateMapper.workflowVersionStateToVersionStatus(state));
+ versioningManager.updateVersion(workflowId, retrievedVersion);
+ versioningManager.publish(workflowId, retrievedVersion,
+ String.format("Update version state from %s to %s", retrievedState.name(), state.name()));
+ }
+
+ @Override
+ public void uploadArtifact(String workflowId, String versionId, MultipartFile artifact) {
+ Version retrievedVersion = getVersion(workflowId, versionId);
+ if (WorkflowVersionState.CERTIFIED
+ .equals(versionStateMapper.versionStatusToWorkflowVersionState(retrievedVersion.getStatus()))) {
+ throw new VersionModificationException(workflowId, versionId);
+ }
+
+ try (InputStream artifactData = artifact.getInputStream()) {
+ ArtifactEntity artifactEntity =
+ new ArtifactEntity(StringUtils.cleanPath(artifact.getOriginalFilename()), artifactData);
+ artifactRepository.update(workflowId, versionId, artifactEntity);
+ versioningManager.publish(workflowId, new Version(versionId), "Update Artifact");
+
+ } catch (IOException e) {
+ throw new InvalidArtifactException(e.getMessage());
+ }
+ }
+
+ @Override
+ public ArtifactEntity getArtifact(String workflowId, String versionId) {
+ getVersion(workflowId, versionId);
+ Optional<ArtifactEntity> artifactOptional = artifactRepository.get(workflowId, versionId);
+ if (!artifactOptional.isPresent()) {
+ throw new EntityNotFoundException(
+ String.format("Artifact for workflow id %S version id %S was not found", workflowId, versionId));
+ }
+ return artifactOptional.get();
+ }
+
+ @Override
+ public void deleteArtifact(String workflowId, String versionId) {
+ WorkflowVersion retrievedVersion = get(workflowId, versionId);
+ if (WorkflowVersionState.CERTIFIED.equals(retrievedVersion.getState())) {
+ throw new VersionModificationException(workflowId, versionId);
+ }
+
+ artifactRepository.delete(workflowId, versionId);
+ versioningManager.publish(workflowId, new Version(versionId), "Delete Artifact");
+ }
+
+ private void validateVersionExistAndCertified(String workflowId, List<Version> versions, String versionId) {
+ Version baseVersion = findVersion(versions, versionId).orElseThrow(
+ () -> new EntityNotFoundException(String.format(VERSION_NOT_EXIST_MSG, versionId, workflowId)));
+
+ if (!Certified.equals(baseVersion.getStatus())) {
+ throw new VersionCreationException(workflowId, versionId);
+ }
+ }
+
+ private Version getVersion(String workflowId, String versionId) {
+ try {
+ Version version = versioningManager.get(workflowId, new Version(versionId));
+ if (version == null) {
+ throw new EntityNotFoundException(String.format(VERSION_NOT_EXIST_MSG, versionId, workflowId));
+ }
+ return version;
+ } catch (Exception e) {
+ throw new EntityNotFoundException(String.format(VERSION_NOT_EXIST_MSG, versionId, workflowId));
+ }
+ }
+
+ private static Optional<Version> findVersion(List<Version> versions, String versionId) {
+ return versions.stream().filter(version -> versionId.equals(version.getId())).findFirst();
+ }
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/VersionMapper.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/VersionMapper.java
new file mode 100644
index 00000000..bcf89661
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/VersionMapper.java
@@ -0,0 +1,19 @@
+package org.onap.sdc.workflow.services.impl.mappers;
+
+import org.mapstruct.InheritInverseConfiguration;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersion;
+import org.openecomp.sdc.versioning.dao.types.Version;
+
+@Mapper(componentModel = "spring", uses = VersionStateMapper.class)
+public interface VersionMapper {
+
+
+ @Mapping(source = "status", target = "state")
+ WorkflowVersion versionToWorkflowVersion(Version version);
+
+ @InheritInverseConfiguration
+ Version workflowVersionToVersion(WorkflowVersion workflowVersion);
+
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/VersionStateMapper.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/VersionStateMapper.java
new file mode 100644
index 00000000..0c2f5391
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/VersionStateMapper.java
@@ -0,0 +1,22 @@
+package org.onap.sdc.workflow.services.impl.mappers;
+
+import org.mapstruct.InheritInverseConfiguration;
+import org.mapstruct.Mapper;
+import org.mapstruct.ValueMapping;
+import org.mapstruct.ValueMappings;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
+import org.openecomp.sdc.versioning.dao.types.VersionStatus;
+
+@Mapper(componentModel = "spring")
+public interface VersionStateMapper {
+
+ @ValueMappings({@ValueMapping(source = "Certified", target = "CERTIFIED"),
+ @ValueMapping(source = "Draft", target = "DRAFT"),
+ @ValueMapping(source = "<ANY_REMAINING>", target = "DRAFT")})
+ WorkflowVersionState versionStatusToWorkflowVersionState(VersionStatus status);
+
+ @InheritInverseConfiguration
+ VersionStatus workflowVersionStateToVersionStatus(WorkflowVersionState status);
+
+
+}
diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowMapper.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowMapper.java
new file mode 100644
index 00000000..34327ce7
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowMapper.java
@@ -0,0 +1,19 @@
+package org.onap.sdc.workflow.services.impl.mappers;
+
+import org.mapstruct.InheritInverseConfiguration;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.onap.sdc.workflow.persistence.types.Workflow;
+import org.onap.sdc.workflow.services.impl.WorkflowManagerImpl;
+import org.openecomp.sdc.versioning.types.Item;
+
+@Mapper(componentModel = "spring", imports = WorkflowManagerImpl.class)
+public interface WorkflowMapper {
+
+ Workflow itemToWorkflow(Item item);
+
+ @InheritInverseConfiguration
+ @Mapping(expression = "java(WorkflowManagerImpl.WORKFLOW_TYPE)", target = "type")
+ Item workflowToItem(Workflow workflow);
+
+}
diff --git a/workflow/workflow-designer-be/src/main/resources/application.properties b/workflow/workflow-designer-be/src/main/resources/application.properties
new file mode 100644
index 00000000..ab4930b5
--- /dev/null
+++ b/workflow/workflow-designer-be/src/main/resources/application.properties
@@ -0,0 +1,10 @@
+server.servlet.context-path=/wf
+server.port=${SERVER_PORT:8080}
+
+#CASSANDRA
+spring.data.cassandra.contact-points=${CS_HOSTS}
+spring.data.cassandra.keyspace-name=workflow
+spring.data.cassandra.port=${CS_PORT:9042}
+spring.data.cassandra.username=${CS_USER:}
+spring.data.cassandra.password=${CS_PASSWORD:}
+zusammen.cassandra.isAuthenticate=${CS_AUTHENTICATE:true} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/RestPath.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/RestPath.java
new file mode 100644
index 00000000..266ca91b
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/RestPath.java
@@ -0,0 +1,24 @@
+package org.onap.sdc.workflow;
+
+public class RestPath {
+ private static final String WORKFLOWS_URL = "/workflows";
+ private static final String WORKFLOW_URL_FORMATTER = WORKFLOWS_URL + "/%s";
+ private static final String VERSIONS_URL_FORMATTER = WORKFLOWS_URL + "/%s/versions";
+ private static final String VERSION_URL_FORMATTER = WORKFLOWS_URL + "/%s/versions/%s";
+
+ public static String getWorkflowsPath(){
+ return WORKFLOWS_URL;
+ }
+
+ public static String getWorkflowPath(String workflowId){
+ return String.format(WORKFLOW_URL_FORMATTER, workflowId);
+ }
+
+ public static String getWorkflowVersions(String workflowId){
+ return String.format(VERSIONS_URL_FORMATTER, workflowId);
+ }
+
+ public static String getWorkflowVersion(String workflowId, String versionId){
+ return String.format(VERSION_URL_FORMATTER, workflowId, versionId);
+ }
+}
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/TestUtil.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/TestUtil.java
new file mode 100644
index 00000000..47ce060b
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/TestUtil.java
@@ -0,0 +1,38 @@
+package org.onap.sdc.workflow;
+
+import org.onap.sdc.workflow.persistence.types.Workflow;
+import org.openecomp.sdc.versioning.types.Item;
+
+public class TestUtil {
+
+ private static final String WORKFLOW_TYPE = "WORKFLOW";
+
+ public static Workflow createWorkflow(int workflowPropertySuffix, boolean createId) {
+ Workflow workflow = new Workflow();
+ if (createId) {
+ workflow.setId("workflowId" + workflowPropertySuffix);
+ }
+ workflow.setName("workflowName" + workflowPropertySuffix);
+ workflow.setDescription("workflowDesc" + workflowPropertySuffix);
+
+ return workflow;
+ }
+
+ public static Item createItem(int itemNum,boolean setType, boolean setId){
+ Item item = new Item();
+ if(setId) {
+ item.setId("workflowId" + itemNum);
+ }
+ item.addProperty("category","category_" + itemNum);
+ item.setName("Workflow_" + itemNum);
+ item.setDescription("Description_" + itemNum);
+ if(setType) {
+ item.setType(WORKFLOW_TYPE);
+ }
+
+ return item;
+ }
+
+
+
+}
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowControllerTest.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowControllerTest.java
new file mode 100644
index 00000000..69b25b01
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowControllerTest.java
@@ -0,0 +1,121 @@
+package org.onap.sdc.workflow.api;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.onap.sdc.workflow.TestUtil.createWorkflow;
+import static org.onap.sdc.workflow.api.RestConstants.USER_ID_HEADER_PARAM;
+import static org.springframework.http.MediaType.APPLICATION_JSON;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import com.google.gson.Gson;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.onap.sdc.workflow.RestPath;
+import org.onap.sdc.workflow.persistence.types.Workflow;
+import org.onap.sdc.workflow.services.WorkflowManager;
+import org.openecomp.sdc.versioning.types.Item;
+import org.springframework.http.MediaType;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+@RunWith(MockitoJUnitRunner.class)
+public class WorkflowControllerTest {
+
+ private static final String MISSING_REQUEST_HEADER_ERRROR_FORMAT =
+ "Missing request header '%s' for method parameter of type String";
+ private static final String USER_ID = "userId";
+ private static final Gson GSON = new Gson();
+
+ private MockMvc mockMvc;
+
+
+ @InjectMocks
+ private WorkflowController workflowController;
+
+ @Mock
+ private WorkflowManager workflowManagerMock;
+
+ @Before
+ public void setUp() {
+ mockMvc = MockMvcBuilders.standaloneSetup(workflowController).build();
+ }
+
+ @Test
+ public void shouldReturnErrorWhenMissingUserIdInGetReqHeader() throws Exception {
+ Workflow workflowMock = createWorkflow(1, true);
+ MockHttpServletResponse response =
+ mockMvc.perform(get(RestPath.getWorkflowPath(workflowMock.getId())).contentType(APPLICATION_JSON))
+ .andDo(print()).andExpect(status().isBadRequest()).andExpect(status().is(400)).andReturn()
+ .getResponse();
+ assertEquals(String.format(MISSING_REQUEST_HEADER_ERRROR_FORMAT, "USER_ID"), response.getErrorMessage());
+ }
+
+ @Test
+ public void shouldReturnWorkflowDataWhenRequestPathIsOk() throws Exception {
+ Workflow workflowMock = createWorkflow(1, true);
+ doReturn(workflowMock).when(workflowManagerMock).get(any(Workflow.class));
+ mockMvc.perform(
+ get(RestPath.getWorkflowPath(workflowMock.getId())).header(USER_ID_HEADER_PARAM, USER_ID)
+ .contentType(APPLICATION_JSON)).andDo(print())
+ .andExpect(status().isOk()).andExpect(jsonPath("$.id", is(workflowMock.getId())))
+ .andExpect(jsonPath("$.name", is(workflowMock.getName())));
+ }
+
+ @Test
+ public void shouldReturnErrorWhenMissingUserIdInListReqHeader() throws Exception {
+ MockHttpServletResponse response =
+ mockMvc.perform(get(RestPath.getWorkflowsPath()).contentType(APPLICATION_JSON)).andDo(print())
+ .andExpect(status().isBadRequest()).andExpect(status().is(400)).andReturn().getResponse();
+ assertEquals(String.format(MISSING_REQUEST_HEADER_ERRROR_FORMAT, USER_ID_HEADER_PARAM), response.getErrorMessage());
+ }
+
+ @Test
+ public void shouldReturn5WorkflowWhen5WorkflowsExists() throws Exception {
+ int numOfWorkflows = 5;
+ List<Workflow> workflowMocks = createWorkflows(numOfWorkflows);
+ doReturn(workflowMocks).when(workflowManagerMock).list();
+ mockMvc.perform(
+ get(RestPath.getWorkflowsPath()).header(USER_ID_HEADER_PARAM, USER_ID).contentType(APPLICATION_JSON))
+ .andDo(print()).andExpect(status().isOk()).andExpect(jsonPath("$.results", hasSize(numOfWorkflows)));
+ }
+
+ @Test
+ public void shouldCreateWorkflowWhenCallingPostRESTRequest() throws Exception {
+ Item item = new Item();
+ item.setId("abc");
+ Workflow reqWorkflow = createWorkflow(1, false);
+ mockMvc.perform(
+ post(RestPath.getWorkflowsPath()).header(USER_ID_HEADER_PARAM, USER_ID).contentType(APPLICATION_JSON)
+ .content(GSON.toJson(reqWorkflow))).andDo(print()).andExpect(status().isCreated())
+ .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE));
+ verify(workflowManagerMock, times(1)).create(reqWorkflow);
+ }
+
+ private List<Workflow> createWorkflows(int numOfWorkflows) {
+ List<Workflow> workflowList = new ArrayList<>(numOfWorkflows);
+ for (int i = 0; i < numOfWorkflows; i++) {
+ workflowList.add(createWorkflow(i, true));
+ }
+
+ return workflowList;
+ }
+
+
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowVersionControllerTest.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowVersionControllerTest.java
new file mode 100644
index 00000000..75b132ad
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowVersionControllerTest.java
@@ -0,0 +1,118 @@
+package org.onap.sdc.workflow.api;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.springframework.http.MediaType.APPLICATION_JSON;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import com.google.gson.Gson;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.onap.sdc.workflow.RestPath;
+import org.onap.sdc.workflow.api.types.VersionRequestDto;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersion;
+import org.onap.sdc.workflow.services.WorkflowVersionManager;
+import org.openecomp.sdc.versioning.dao.types.Version;
+import org.springframework.http.HttpStatus;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+@RunWith(MockitoJUnitRunner.class)
+public class WorkflowVersionControllerTest {
+
+ private static final String USER_ID = "cs0008";
+ private static final String ITEM1_ID = "item_id_1";
+ private static final String VERSION1_ID = "version_id_1";
+ private static final String VERSION2_ID = "version_id_2";
+ private List<Version> versionList;
+
+ private static final Gson GSON = new Gson();
+
+ private MockMvc mockMvc;
+
+ @Mock
+ private WorkflowVersionManager workflowVersionManagerMock;
+
+ @InjectMocks
+ private WorkflowVersionController workflowVersionController;
+
+ @Before
+ public void setUp() {
+ versionList = Arrays.asList( new Version(VERSION1_ID),new Version(VERSION2_ID));
+ mockMvc = MockMvcBuilders.standaloneSetup(workflowVersionController).build();
+ }
+
+ @Test
+ public void shouldReturnWorkflowVersionListWhenCallingVersionGetREST() throws Exception {
+
+ doReturn(versionList).when(workflowVersionManagerMock).list(ITEM1_ID);
+ mockMvc.perform(get(RestPath.getWorkflowVersions(ITEM1_ID)).header(RestConstants.USER_ID_HEADER_PARAM, USER_ID)
+ .contentType(APPLICATION_JSON)).andExpect(status().isOk())
+ .andExpect(jsonPath("$.results", hasSize(2)))
+ .andExpect(jsonPath("$.results[0].id", equalTo(VERSION1_ID)))
+ .andExpect(jsonPath("$.results[1].id", equalTo(VERSION2_ID)));
+
+ verify(workflowVersionManagerMock, times(1)).list(ITEM1_ID);
+ }
+
+
+ @Test
+ public void shouldCreateWorkflowVersionWhenCallingVersionsPostREST() throws Exception {
+
+ VersionRequestDto version = new VersionRequestDto();
+ version.setDescription("VersionDescription");
+ mockMvc.perform(post(RestPath.getWorkflowVersions(ITEM1_ID)).header(RestConstants.USER_ID_HEADER_PARAM, USER_ID)
+ .contentType(APPLICATION_JSON)
+ .content(GSON.toJson(version)))
+ .andExpect(status().isCreated());
+
+ verify(workflowVersionManagerMock, times(1)).create(ITEM1_ID, version);
+ }
+
+
+ @Test
+ public void shouldReturnWorkflowVersionWhenExists() throws Exception {
+ WorkflowVersion version = new WorkflowVersion(VERSION1_ID);
+ doReturn(version).when(workflowVersionManagerMock).get(ITEM1_ID, VERSION1_ID);
+ mockMvc.perform(
+ get(RestPath.getWorkflowVersion(ITEM1_ID, VERSION1_ID)).header(RestConstants.USER_ID_HEADER_PARAM, USER_ID)
+ .contentType(APPLICATION_JSON)).andDo(print())
+ .andExpect(status().isOk()).andExpect(jsonPath("$.id", is(version.getId())));
+ verify(workflowVersionManagerMock, times(1)).get(ITEM1_ID, VERSION1_ID);
+ }
+
+ @Test
+ public void shouldUpdateWorkflowVersionWhenCallingPutREST() throws Exception {
+ WorkflowVersion version = new WorkflowVersion();
+ version.setDescription("Updated");
+
+ MockHttpServletResponse result = mockMvc.perform(
+ put(RestPath.getWorkflowVersion(ITEM1_ID, VERSION1_ID)).header(RestConstants.USER_ID_HEADER_PARAM, USER_ID)
+ .contentType(APPLICATION_JSON)
+ .content(GSON.toJson(version))).andReturn()
+ .getResponse();
+
+ assertEquals(HttpStatus.OK.value(), result.getStatus());
+ version.setId(VERSION1_ID);
+ verify(workflowVersionManagerMock, times(1)).update(ITEM1_ID, version);
+
+ }
+
+}
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/persistence/impl/ArtifactRepositoryTest.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/persistence/impl/ArtifactRepositoryTest.java
new file mode 100644
index 00000000..4bec8b97
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/persistence/impl/ArtifactRepositoryTest.java
@@ -0,0 +1,29 @@
+package org.onap.sdc.workflow.persistence.impl;
+
+import java.io.IOException;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.openecomp.core.zusammen.api.ZusammenAdaptor;
+
+public class ArtifactRepositoryTest {
+
+ private static final String FILE_NAME_PROPERTY = "fileName";
+ private static final String EMPTY_DATA = "{}";
+ private static final String ITEM1_ID = "item_id_1";
+ private static final String VERSION1_ID = "version_id_1";
+
+
+ @Mock
+ private ZusammenAdaptor zusammenAdaptorMock;
+
+ @InjectMocks
+ private ArtifactRepositoryImpl artifactRepository;
+
+ @Test
+ public void shouldUpdateArtifact() throws IOException {
+
+ }
+
+
+}
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/UniqueValueServiceTest.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/UniqueValueServiceTest.java
new file mode 100644
index 00000000..4911060a
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/UniqueValueServiceTest.java
@@ -0,0 +1,98 @@
+package org.onap.sdc.workflow.services;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.onap.sdc.workflow.persistence.UniqueValueRepository;
+import org.onap.sdc.workflow.persistence.types.UniqueValueEntity;
+import org.onap.sdc.workflow.services.exceptions.UniqueValueViolationException;
+
+public class UniqueValueServiceTest {
+
+ private static final String TYPE = "ss";
+ private static final String DUMMY_COMBINATION = "dummy";
+
+ @Mock
+ private UniqueValueRepository uniqueValueRepositoryMock;
+
+ @Spy
+ @InjectMocks
+ private UniqueValueService uniqueValueService;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void shouldCallRepositoryInsertIfValueUnique(){
+ doReturn(Optional.empty()).when(uniqueValueRepositoryMock).findById(any());
+ uniqueValueService.createUniqueValue(TYPE, new String[]{DUMMY_COMBINATION});
+ verify(uniqueValueRepositoryMock, times(1)).insert(any(UniqueValueEntity.class));
+ }
+
+ @Test
+ public void shouldNotCheckValueIfNoUniqueCombination(){
+ uniqueValueService.createUniqueValue(TYPE, null);
+ verify(uniqueValueRepositoryMock, never()).findById(any(UniqueValueEntity.class));
+ }
+
+ @Test(expected = UniqueValueViolationException.class)
+ public void shouldThrowExceptionIfValueIsNotUnique(){
+ doReturn(Optional.of("xxx")).when(uniqueValueRepositoryMock).findById(any());
+ uniqueValueService.createUniqueValue(TYPE, new String[]{DUMMY_COMBINATION});
+ }
+
+ @Test
+ public void shouldCallRepositoryDeleteIfValueValid(){
+ uniqueValueService.deleteUniqueValue(TYPE, new String[]{DUMMY_COMBINATION});
+ verify(uniqueValueRepositoryMock, times(1)).delete(any(UniqueValueEntity.class));
+ }
+
+ @Test
+ public void shouldNotCallRepositoryDeleteIfValueNouniqueCombination(){
+ uniqueValueService.deleteUniqueValue(TYPE, new String[]{});
+ verify(uniqueValueRepositoryMock, never()).delete(any(UniqueValueEntity.class));
+ }
+
+ @Test
+ public void shouldNotUpdateIfNewAndOldValueAreEqualsCaseIgnore(){
+ String value = "value";
+ uniqueValueService.updateUniqueValue(TYPE, value, value.toUpperCase());
+ verify(uniqueValueService, never()).createUniqueValue(anyString(), any());
+ }
+
+ @Test
+ public void shouldUpdateIfNewAndOldValueAreNotEqualsCaseIgnore(){
+ String oldValue = "oldValue";
+ String newValue = "newValue";
+ uniqueValueService.updateUniqueValue(TYPE, oldValue, newValue);
+ verify(uniqueValueService, times(1)).createUniqueValue(anyString(), any());
+ verify(uniqueValueService, times(1)).deleteUniqueValue(anyString(), any());
+ }
+
+ @Test
+ public void shouldReturnTrueIfValueExist() {
+ doReturn(Optional.of("xxx")).when(uniqueValueRepositoryMock).findById(any());
+ assertTrue(uniqueValueService.isUniqueValueOccupied(TYPE, new String[]{DUMMY_COMBINATION}));
+ }
+
+ @Test
+ public void shouldReturnFalseIfValueNotExist() {
+ doReturn(Optional.empty()).when(uniqueValueRepositoryMock).findById(any());
+ assertFalse(uniqueValueService.isUniqueValueOccupied(TYPE, new String[]{DUMMY_COMBINATION}));
+ }
+}
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImplTest.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImplTest.java
new file mode 100644
index 00000000..17037d9b
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImplTest.java
@@ -0,0 +1,119 @@
+package org.onap.sdc.workflow.services.impl;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.onap.sdc.workflow.TestUtil.createItem;
+import static org.onap.sdc.workflow.TestUtil.createWorkflow;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.onap.sdc.workflow.persistence.types.Workflow;
+import org.onap.sdc.workflow.services.UniqueValueService;
+import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
+import org.onap.sdc.workflow.services.impl.mappers.WorkflowMapper;
+import org.openecomp.sdc.versioning.ItemManager;
+import org.openecomp.sdc.versioning.types.Item;
+import org.openecomp.sdc.versioning.types.ItemStatus;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class WorkflowManagerImplTest {
+
+ private static final String ITEM1_ID = "workflowId1";
+ private static final String WORKFLOW_TYPE = "WORKFLOW";
+ private static final String WORKFLOW_NAME_UNIQUE_TYPE = "WORKFLOW_NAME";
+ private List<Item> itemList;
+
+ @Mock
+ private WorkflowMapper workflowMapperMock;
+
+ @Mock
+ private ItemManager itemManagerMock;
+
+ @Mock
+ private UniqueValueService uniqueValueServiceMock;
+
+ @InjectMocks
+ private WorkflowManagerImpl workflowManager;
+
+
+ @Before
+ public void setUp() {
+ itemList = Arrays.asList(createItem(1, true, true), createItem(2, true, true), createItem(3, true, true));
+
+ }
+
+
+ @Test
+ public void shouldReturnWorkflowVersionList() {
+
+ doReturn(itemList).when(itemManagerMock).list(WorkflowManagerImpl.ITEM_PREDICATE);
+ workflowManager.list();
+ verify(itemManagerMock).list(WorkflowManagerImpl.ITEM_PREDICATE);
+ }
+
+ @Test(expected = EntityNotFoundException.class)
+ public void shouldThrowExceptionWhenWorkflowDontExist() {
+ Workflow nonExistingWorkflow = new Workflow();
+ nonExistingWorkflow.setId(ITEM1_ID);
+ doReturn(null).when(itemManagerMock).get(ITEM1_ID);
+ workflowManager.get(nonExistingWorkflow);
+ verify(workflowMapperMock, times(3)).itemToWorkflow(any(Item.class));
+ }
+
+ @Test
+ public void shouldReturnWorkflow() {
+ Item retrievedItem = createItem(1, true, true);
+ doReturn(retrievedItem).when(itemManagerMock).get(ITEM1_ID);
+ Workflow workflow = createWorkflow(1, true);
+ workflowManager.get(workflow);
+ verify(itemManagerMock).get(ITEM1_ID);
+ verify(workflowMapperMock).itemToWorkflow(retrievedItem);
+
+
+ }
+
+ @Test
+ public void shouldCreateWorkflowItemFromWorkflow() {
+ Workflow workflowToBeCreated = createWorkflow(1, false);
+ Item createdWorkflowItem = createItem(1, false, true);
+ doReturn(createdWorkflowItem).when(workflowMapperMock).workflowToItem(workflowToBeCreated);
+ doReturn(createdWorkflowItem).when(itemManagerMock).create(createdWorkflowItem);
+ workflowManager.create(workflowToBeCreated);
+ verify(uniqueValueServiceMock)
+ .validateUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, new String[] {workflowToBeCreated.getName()});
+
+ createdWorkflowItem.setStatus(ItemStatus.ACTIVE);
+ createdWorkflowItem.setType(WORKFLOW_TYPE);
+ verify(itemManagerMock).create(createdWorkflowItem);
+ verify(uniqueValueServiceMock)
+ .createUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, new String[] {workflowToBeCreated.getName()});
+ }
+
+ @Test
+ public void shouldUpdateWorkflow() {
+ Item workflowItem = createItem(1, true, true);
+ doReturn(workflowItem).when(itemManagerMock).get(ITEM1_ID);
+ Workflow workflowToBeUpdated = createWorkflow(1, true);
+ doReturn(workflowItem).when(workflowMapperMock).workflowToItem(workflowToBeUpdated);
+ workflowManager.update(workflowToBeUpdated);
+ verify(itemManagerMock).update(workflowItem);
+ verify(uniqueValueServiceMock)
+ .updateUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, workflowItem.getName(), workflowToBeUpdated.getName());
+
+ }
+
+ @Test(expected = EntityNotFoundException.class)
+ public void shouldThrowExceptionWhenWorkflowToUpdateNotFound() {
+ doReturn(null).when(itemManagerMock).get(ITEM1_ID);
+ workflowManager.update(createWorkflow(1, true));
+ }
+
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImplTest.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImplTest.java
new file mode 100644
index 00000000..144db81e
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImplTest.java
@@ -0,0 +1,258 @@
+package org.onap.sdc.workflow.services.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.onap.sdc.workflow.persistence.types.WorkflowVersionState.CERTIFIED;
+import static org.onap.sdc.workflow.persistence.types.WorkflowVersionState.DRAFT;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.onap.sdc.workflow.api.types.VersionRequestDto;
+import org.onap.sdc.workflow.persistence.ArtifactRepository;
+import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersion;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
+import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
+import org.onap.sdc.workflow.services.exceptions.VersionCreationException;
+import org.onap.sdc.workflow.services.exceptions.VersionStateModificationException;
+import org.onap.sdc.workflow.services.impl.mappers.VersionMapper;
+import org.onap.sdc.workflow.services.impl.mappers.VersionStateMapper;
+import org.openecomp.sdc.versioning.VersioningManager;
+import org.openecomp.sdc.versioning.dao.types.Version;
+import org.openecomp.sdc.versioning.dao.types.VersionStatus;
+import org.openecomp.sdc.versioning.types.VersionCreationMethod;
+import org.springframework.mock.web.MockMultipartFile;
+
+@RunWith(MockitoJUnitRunner.class)
+public class WorkflowVersionManagerImplTest {
+
+ private static final String ITEM1_ID = "item_id_1";
+ private static final String VERSION1_ID = "version_id_1";
+ private static final String VERSION2_ID = "version_id_2";
+
+ @Mock
+ private VersioningManager versioningManagerMock;
+ @Mock
+ private ArtifactRepository artifactRepositoryMock;
+ @Mock
+ private VersionMapper versionMapperMock;
+ @Mock
+ private VersionStateMapper versionStateMapperMock;
+ @InjectMocks
+ private WorkflowVersionManagerImpl workflowVersionManager;
+
+ @Test(expected = EntityNotFoundException.class)
+ public void shouldThrowExceptionWhenVersionDontExist() {
+ Version nonExistingVersion = new Version(VERSION1_ID);
+ doThrow(new RuntimeException()).when(versioningManagerMock).get(ITEM1_ID, nonExistingVersion);
+ workflowVersionManager.get(ITEM1_ID, VERSION1_ID);
+ }
+
+ @Test
+ public void shouldReturnWorkflowVersionWhenExist() {
+ Version version = new Version(VERSION1_ID);
+ doReturn(version).when(versioningManagerMock).get(ITEM1_ID, version);
+ workflowVersionManager.get(ITEM1_ID, VERSION1_ID);
+ verify(versioningManagerMock).get(ITEM1_ID, version);
+ }
+
+ @Test
+ public void shouldReturnWorkflowVersionList() {
+ List<Version> versionList = Arrays.asList(new Version(VERSION1_ID), new Version(VERSION2_ID));
+ versionList.forEach(version -> {
+ version.setBaseId("baseVersionId");
+ version.setDescription("Version description");
+ version.setName("name");
+ version.setCreationTime(new Date());
+ version.setModificationTime(new Date());
+ });
+ doReturn(versionList).when(versioningManagerMock).list(ITEM1_ID);
+ workflowVersionManager.list(ITEM1_ID);
+ verify(versioningManagerMock).list(ITEM1_ID);
+ verify(versionMapperMock, times(2)).versionToWorkflowVersion(any(Version.class));
+ }
+
+ @Test
+ public void shouldUpdateWorkflowVersion() {
+ Version retrievedVersion = new Version(VERSION1_ID);
+ retrievedVersion.setName("1.0");
+ retrievedVersion.setDescription("WorkflowVersion description");
+ retrievedVersion.setStatus(VersionStatus.Draft);
+ doReturn(retrievedVersion).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+ doReturn(DRAFT).when(versionStateMapperMock).versionStatusToWorkflowVersionState(retrievedVersion.getStatus());
+
+ WorkflowVersion inputVersion = new WorkflowVersion(VERSION1_ID);
+ inputVersion.setName("1.0");
+ inputVersion.setDescription("WorkflowVersion description updated");
+
+ Version mappedInputVersion = new Version(VERSION1_ID);
+ mappedInputVersion.setName("1.0");
+ mappedInputVersion.setDescription("WorkflowVersion description updated");
+ doReturn(mappedInputVersion).when(versionMapperMock).workflowVersionToVersion(inputVersion);
+
+ ArgumentCaptor<Version> versionArgCaptor = ArgumentCaptor.forClass(Version.class);
+ workflowVersionManager.update(ITEM1_ID, inputVersion);
+
+ verify(versioningManagerMock).updateVersion(eq(ITEM1_ID), versionArgCaptor.capture());
+ Version captorVersion = versionArgCaptor.getValue();
+ assertEquals("1.0", captorVersion.getName());
+ assertEquals("WorkflowVersion description updated", captorVersion.getDescription());
+ assertEquals(VersionStatus.Draft, captorVersion.getStatus());
+ verify(versioningManagerMock).publish(ITEM1_ID, mappedInputVersion, "Update version");
+ }
+
+ @Test
+ public void shouldCreateWorkflowVersion() {
+ Version version = new Version(VERSION1_ID);
+ version.setDescription("version desc");
+ doReturn(version).when(versioningManagerMock).create(ITEM1_ID, version, VersionCreationMethod.major);
+ VersionRequestDto workflowVersion = new VersionRequestDto();
+ workflowVersion.setDescription("version desc");
+ workflowVersionManager.create(ITEM1_ID, workflowVersion);
+ verify(versioningManagerMock).create(ITEM1_ID, version, VersionCreationMethod.major);
+
+ }
+
+ @Test(expected = VersionCreationException.class)
+ public void shouldTrowExceptionWhenDraftVersionExists() {
+ VersionRequestDto versionRequestDto = new VersionRequestDto();
+ versionRequestDto.setBaseVersionId(VERSION2_ID);
+
+ Version baseVersion = new Version(VERSION2_ID);
+ baseVersion.setStatus(VersionStatus.Draft);
+ List<Version> versions = Collections.singletonList(baseVersion);
+ doReturn(versions).when(versioningManagerMock).list(ITEM1_ID);
+
+ workflowVersionManager.create(ITEM1_ID, versionRequestDto);
+ }
+
+ @Test(expected = EntityNotFoundException.class)
+ public void getStateOfNonExisting() {
+ doThrow(new RuntimeException()).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+ workflowVersionManager.getState(ITEM1_ID, VERSION1_ID);
+ }
+
+ @Test
+ public void getState() {
+ Version version = new Version(VERSION1_ID);
+ version.setStatus(VersionStatus.Certified);
+ doReturn(version).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+ doReturn(CERTIFIED).when(versionStateMapperMock).versionStatusToWorkflowVersionState(version.getStatus());
+
+ WorkflowVersionState state = workflowVersionManager.getState(ITEM1_ID, VERSION1_ID);
+ assertEquals(CERTIFIED, state);
+ }
+
+ @Test(expected = EntityNotFoundException.class)
+ public void updateStateOfNonExisting() {
+ doThrow(new RuntimeException()).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+ workflowVersionManager.updateState(ITEM1_ID, VERSION1_ID, CERTIFIED);
+ }
+
+ @Test(expected = VersionStateModificationException.class)
+ public void updateStateToCurrentState() {
+ Version version = new Version(VERSION1_ID);
+ version.setStatus(VersionStatus.Draft);
+ doReturn(version).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+ doReturn(DRAFT).when(versionStateMapperMock).versionStatusToWorkflowVersionState(version.getStatus());
+
+ workflowVersionManager.updateState(ITEM1_ID, VERSION1_ID, DRAFT);
+ }
+
+ @Test(expected = VersionStateModificationException.class)
+ public void updateStateWhenCertified() {
+ Version version = new Version(VERSION1_ID);
+ version.setStatus(VersionStatus.Certified);
+ doReturn(version).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+ doReturn(CERTIFIED).when(versionStateMapperMock).versionStatusToWorkflowVersionState(version.getStatus());
+
+ workflowVersionManager.updateState(ITEM1_ID, VERSION1_ID, CERTIFIED);
+ }
+
+ @Test
+ public void updateState() {
+ Version retrievedVersion = new Version(VERSION1_ID);
+ retrievedVersion.setStatus(VersionStatus.Draft);
+ doReturn(retrievedVersion).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+ doReturn(DRAFT).when(versionStateMapperMock).versionStatusToWorkflowVersionState(VersionStatus.Draft);
+ doReturn(VersionStatus.Certified).when(versionStateMapperMock).workflowVersionStateToVersionStatus(CERTIFIED);
+
+ ArgumentCaptor<Version> versionArgCaptor = ArgumentCaptor.forClass(Version.class);
+ workflowVersionManager.updateState(ITEM1_ID, VERSION1_ID, CERTIFIED);
+
+ verify(versioningManagerMock).updateVersion(eq(ITEM1_ID), versionArgCaptor.capture());
+ assertEquals(VersionStatus.Certified, versionArgCaptor.getValue().getStatus());
+ verify(versioningManagerMock)
+ .publish(eq(ITEM1_ID), eqVersion(VERSION1_ID), eq("Update version state from DRAFT to CERTIFIED"));
+ }
+
+ @Test
+ public void shouldUploadArtifact() {
+ Version version = new Version(VERSION1_ID);
+ version.setStatus(VersionStatus.Draft);
+ doReturn(version).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+ doReturn(DRAFT).when(versionStateMapperMock).versionStatusToWorkflowVersionState(version.getStatus());
+
+ MockMultipartFile mockFile = new MockMultipartFile("data", "filename.txt", "text/plain", "some xml".getBytes());
+ workflowVersionManager.uploadArtifact(ITEM1_ID, VERSION1_ID, mockFile);
+
+ verify(artifactRepositoryMock).update(eq(ITEM1_ID), eq(VERSION1_ID), any(ArtifactEntity.class));
+ }
+
+ @Test(expected = EntityNotFoundException.class)
+ public void shouldThrowExceptionWhenArtifactNotFound() {
+ doReturn(new Version(VERSION1_ID)).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+
+ doReturn(Optional.empty()).when(artifactRepositoryMock).get(ITEM1_ID, VERSION1_ID);
+ workflowVersionManager.getArtifact(ITEM1_ID, VERSION1_ID);
+ }
+
+ @Test
+ public void shouldReturnArtifact() throws IOException {
+ doReturn(new Version(VERSION1_ID)).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+
+ InputStream inputStreamMock = IOUtils.toInputStream("some test data for my input stream", "UTF-8");
+ ArtifactEntity artifactMock = new ArtifactEntity("fileName.txt", inputStreamMock);
+ doReturn(Optional.of(artifactMock)).when(artifactRepositoryMock).get(ITEM1_ID, VERSION1_ID);
+ ArtifactEntity returnedArtifact = workflowVersionManager.getArtifact(ITEM1_ID, VERSION1_ID);
+ assertEquals(artifactMock, returnedArtifact);
+ }
+
+ private static Version eqVersion(String versionId) {
+ return argThat(new EqVersion(versionId));
+ }
+
+ private static class EqVersion implements ArgumentMatcher<Version> {
+
+ private final String versionId;
+
+ EqVersion(String versionId) {
+ this.versionId = versionId;
+ }
+
+ @Override
+ public boolean matches(Version version) {
+ return versionId.equals(version.getId());
+ }
+ }
+
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/VersionMapperTest.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/VersionMapperTest.java
new file mode 100644
index 00000000..d9790355
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/VersionMapperTest.java
@@ -0,0 +1,80 @@
+package org.onap.sdc.workflow.services.impl.mappers;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Date;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersion;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
+import org.openecomp.sdc.versioning.dao.types.Version;
+import org.openecomp.sdc.versioning.dao.types.VersionStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@ContextConfiguration(classes = VersionMapperTest.VersionMapperSpringTestConfig.class)
+@RunWith(SpringJUnit4ClassRunner.class)
+public class VersionMapperTest {
+
+ @Configuration
+ @ComponentScan(basePackageClasses = {VersionMapper.class, VersionStateMapper.class})
+ public static class VersionMapperSpringTestConfig { }
+
+ @Autowired
+ VersionMapper versionMapper;
+
+
+ @Test
+ public void shouldMapVersionToWorkflowVersion() {
+ Version version = createVersion();
+ WorkflowVersion mappedWorkflowVersion = versionMapper.versionToWorkflowVersion(version);
+ assertEquals(mappedWorkflowVersion.getId(), version.getId());
+ assertEquals(mappedWorkflowVersion.getBaseId(), version.getBaseId());
+ assertEquals(mappedWorkflowVersion.getDescription(), version.getDescription());
+ assertEquals(mappedWorkflowVersion.getName(), version.getName());
+ assertEquals(mappedWorkflowVersion.getCreationTime(), version.getCreationTime());
+ assertEquals(mappedWorkflowVersion.getModificationTime(), version.getModificationTime());
+ }
+
+ @Test
+ public void shouldMapWorkflowVersionToVersion() {
+ WorkflowVersion workflowVersion = createWorkflowVersion();
+ Version mappedVersion = versionMapper.workflowVersionToVersion(workflowVersion);
+ assertEquals(mappedVersion.getId(), workflowVersion.getId());
+ assertEquals(mappedVersion.getBaseId(), workflowVersion.getBaseId());
+ assertEquals(mappedVersion.getDescription(), workflowVersion.getDescription());
+ assertEquals(mappedVersion.getName(), workflowVersion.getName());
+ assertEquals(mappedVersion.getCreationTime(), workflowVersion.getCreationTime());
+ assertEquals(mappedVersion.getModificationTime(), workflowVersion.getModificationTime());
+
+ }
+
+ private Version createVersion() {
+ Version version = new Version("version_id");
+ version.setBaseId("base_version_id");
+ version.setName("1.0");
+ version.setCreationTime(new Date());
+ version.setModificationTime(new Date());
+ version.setDescription("version_description");
+ version.setStatus(VersionStatus.Draft);
+
+ return version;
+
+ }
+
+ private WorkflowVersion createWorkflowVersion() {
+ WorkflowVersion workflowVersion = new WorkflowVersion();
+ workflowVersion.setId("wf_version_id");
+ workflowVersion.setBaseId("wf_base_version_id");
+ workflowVersion.setName("1.0");
+ workflowVersion.setCreationTime(new Date());
+ workflowVersion.setModificationTime(new Date());
+ workflowVersion.setDescription("version_description");
+ workflowVersion.setState(WorkflowVersionState.CERTIFIED);
+
+ return workflowVersion;
+ }
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/VersionStateMapperTest.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/VersionStateMapperTest.java
new file mode 100644
index 00000000..070c433e
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/VersionStateMapperTest.java
@@ -0,0 +1,75 @@
+package org.onap.sdc.workflow.services.impl.mappers;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
+import org.openecomp.sdc.versioning.dao.types.VersionStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@ContextConfiguration(classes = VersionStateMapperTest.VersionStatusMapperSpringTestConfig.class)
+@RunWith(SpringJUnit4ClassRunner.class)
+public class VersionStateMapperTest {
+
+ @Configuration
+ @ComponentScan(basePackageClasses = {VersionStateMapper.class})
+ public static class VersionStatusMapperSpringTestConfig { }
+
+
+ @Autowired
+ VersionStateMapper versionStateMapper;
+
+ @Test
+ public void shouldMapCertifiedVersionStatusToWorkflowVersionStatus() {
+ WorkflowVersionState mappedVersionStatus =
+ versionStateMapper.versionStatusToWorkflowVersionState(VersionStatus.Certified);
+ assertEquals(WorkflowVersionState.CERTIFIED, mappedVersionStatus);
+ }
+
+ @Test
+ public void shouldMapDraftVersionStatusToWorkflowVersionStatus() {
+ WorkflowVersionState mappedVersionStatus =
+ versionStateMapper.versionStatusToWorkflowVersionState(VersionStatus.Draft);
+ assertEquals(WorkflowVersionState.DRAFT, mappedVersionStatus);
+ }
+
+ @Test
+ public void shouldMapDeletedVersionStatusToWorkflowVersionStatus() {
+ WorkflowVersionState mappedVersionStatus =
+ versionStateMapper.versionStatusToWorkflowVersionState(VersionStatus.Deleted);
+ assertEquals(WorkflowVersionState.DRAFT, mappedVersionStatus);
+ }
+
+ @Test
+ public void shouldMapLockedVersionStatusToWorkflowVersionStatus() {
+ WorkflowVersionState mappedVersionStatus =
+ versionStateMapper.versionStatusToWorkflowVersionState(VersionStatus.Locked);
+ assertEquals(WorkflowVersionState.DRAFT, mappedVersionStatus);
+ }
+
+ @Test
+ public void shouldMapDeprecatedVersionStatusToWorkflowVersionStatus() {
+ WorkflowVersionState mappedVersionStatus =
+ versionStateMapper.versionStatusToWorkflowVersionState(VersionStatus.Deprecated);
+ assertEquals(WorkflowVersionState.DRAFT, mappedVersionStatus);
+ }
+
+ @Test
+ public void shouldMapCertifiedWorkflowVersionStatusToVersionStatus() {
+ VersionStatus mappedVersionStatus =
+ versionStateMapper.workflowVersionStateToVersionStatus(WorkflowVersionState.CERTIFIED);
+ assertEquals(VersionStatus.Certified, mappedVersionStatus);
+ }
+
+ @Test
+ public void shouldMapDraftWorkflowVersionStatusToVersionStatus() {
+ VersionStatus mappedVersionStatus =
+ versionStateMapper.workflowVersionStateToVersionStatus(WorkflowVersionState.DRAFT);
+ assertEquals(VersionStatus.Draft, mappedVersionStatus);
+ }
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowMapperTest.java b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowMapperTest.java
new file mode 100644
index 00000000..55802cc0
--- /dev/null
+++ b/workflow/workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/mappers/WorkflowMapperTest.java
@@ -0,0 +1,50 @@
+package org.onap.sdc.workflow.services.impl.mappers;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.onap.sdc.workflow.TestUtil.createItem;
+import static org.onap.sdc.workflow.TestUtil.createWorkflow;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.sdc.workflow.persistence.types.Workflow;
+import org.openecomp.sdc.versioning.types.Item;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@ContextConfiguration(classes = WorkflowMapperTest.WorkflowMapperSpringTestConfig.class)
+@RunWith(SpringJUnit4ClassRunner.class)
+public class WorkflowMapperTest {
+
+ @Configuration
+ @ComponentScan(basePackageClasses = {WorkflowMapper.class})
+ public static class WorkflowMapperSpringTestConfig { }
+
+ @Autowired
+ WorkflowMapper workflowMapper;
+
+ @Test
+ public void shouldMapItemToWorkflow() {
+
+ Item item = createItem(1,false,true);
+ Workflow mappedWorkflow = workflowMapper.itemToWorkflow(item);
+ assertEquals(mappedWorkflow.getId(), item.getId());
+ assertEquals(mappedWorkflow.getDescription(), item.getDescription());
+ assertEquals(mappedWorkflow.getName(), item.getName());
+ }
+
+ @Test
+ public void shouldMapWorkflowToItem(){
+
+ Workflow workflow = createWorkflow(1,true);
+ Item mappedItem = workflowMapper.workflowToItem(workflow);
+ assertEquals(mappedItem.getId(), workflow.getId());
+ assertEquals(mappedItem.getDescription(), workflow.getDescription());
+ assertEquals(mappedItem.getName(), workflow.getName());
+ }
+
+} \ No newline at end of file
diff --git a/workflow/workflow-designer-init/pom.xml b/workflow/workflow-designer-init/pom.xml
new file mode 100644
index 00000000..7f926e86
--- /dev/null
+++ b/workflow/workflow-designer-init/pom.xml
@@ -0,0 +1,45 @@
+<project
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>workflow-designer-init</artifactId>
+ <packaging>pom</packaging>
+
+ <parent>
+ <groupId>org.onap.sdc.workflow_designer</groupId>
+ <artifactId>workflow-designer-parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </parent>
+
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <configuration>
+ <images>
+ <image>
+ <name>onap/workflow-init</name>
+ <build>
+ <tags>
+ <tag>${project.version}</tag>
+ </tags>
+ <dockerFile>Dockerfile</dockerFile>
+ </build>
+ </image>
+ </images>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project> \ No newline at end of file
diff --git a/workflow/workflow-designer-init/src/main/docker/Dockerfile b/workflow/workflow-designer-init/src/main/docker/Dockerfile
new file mode 100644
index 00000000..75e7efdc
--- /dev/null
+++ b/workflow/workflow-designer-init/src/main/docker/Dockerfile
@@ -0,0 +1,10 @@
+FROM alpine:3.7
+
+RUN apk add --no-cache 'python<3' py-pip && pip install cqlsh==4.0.1
+
+COPY create_workflow_db.cql .
+COPY start.sh .
+
+RUN chmod 744 start.sh
+
+ENTRYPOINT ["./start.sh"] \ No newline at end of file
diff --git a/workflow/workflow-designer-init/src/main/docker/create_workflow_db.cql b/workflow/workflow-designer-init/src/main/docker/create_workflow_db.cql
new file mode 100644
index 00000000..c6c1f15e
--- /dev/null
+++ b/workflow/workflow-designer-init/src/main/docker/create_workflow_db.cql
@@ -0,0 +1,125 @@
+CREATE KEYSPACE IF NOT EXISTS WORKFLOW
+WITH DURABLE_WRITES = TRUE
+AND REPLICATION = {
+ 'class' : 'SimpleStrategy',
+ 'replication_factor' : 1
+};
+
+USE WORKFLOW;
+
+CREATE TABLE IF NOT EXISTS UNIQUE_VALUE (
+ TYPE TEXT,
+ VALUE TEXT,
+ PRIMARY KEY (( TYPE, VALUE ))
+);
+
+CREATE KEYSPACE IF NOT EXISTS ZUSAMMEN_WORKFLOW
+WITH REPLICATION = {
+ 'class' : 'SimpleStrategy',
+ 'replication_factor' : 1
+};
+
+USE ZUSAMMEN_WORKFLOW;
+
+CREATE TABLE IF NOT EXISTS ITEM (
+ ITEM_ID TEXT PRIMARY KEY,
+ ITEM_INFO TEXT,
+ CREATION_TIME TIMESTAMP,
+ MODIFICATION_TIME TIMESTAMP
+);
+
+CREATE TABLE IF NOT EXISTS VERSION (
+ SPACE TEXT,
+ ITEM_ID TEXT,
+ VERSION_ID TEXT,
+ BASE_VERSION_ID TEXT,
+ INFO TEXT,
+ RELATIONS TEXT,
+ CREATION_TIME TIMESTAMP,
+ MODIFICATION_TIME TIMESTAMP,
+ PRIMARY KEY (( SPACE, ITEM_ID ), VERSION_ID)
+);
+
+CREATE TABLE IF NOT EXISTS VERSION_ELEMENTS (
+ SPACE TEXT,
+ ITEM_ID TEXT,
+ VERSION_ID TEXT,
+ REVISION_ID TEXT,
+ ELEMENT_IDS MAP<TEXT, TEXT>,
+ DIRTY_ELEMENT_IDS SET<TEXT>,
+ STAGE_ELEMENT_IDS SET<TEXT>,
+ CONFLICT_ELEMENT_IDS SET<TEXT>,
+ PUBLISH_TIME TIMESTAMP,
+ USER TEXT,
+ MESSAGE TEXT,
+ PRIMARY KEY (( SPACE, ITEM_ID, VERSION_ID ), REVISION_ID)
+);
+
+CREATE TABLE IF NOT EXISTS ELEMENT_NAMESPACE (
+ ITEM_ID TEXT,
+ ELEMENT_ID TEXT,
+ NAMESPACE TEXT,
+ PRIMARY KEY (( ITEM_ID, ELEMENT_ID ))
+);
+
+CREATE TABLE IF NOT EXISTS ELEMENT (
+ SPACE TEXT,
+ ITEM_ID TEXT,
+ VERSION_ID TEXT,
+ ELEMENT_ID TEXT,
+ REVISION_ID TEXT,
+ PARENT_ID TEXT,
+ NAMESPACE TEXT,
+ INFO TEXT,
+ RELATIONS TEXT,
+ DATA BLOB,
+ SEARCHABLE_DATA BLOB,
+ VISUALIZATION BLOB,
+ SUB_ELEMENT_IDS SET<TEXT>,
+ ELEMENT_HASH TEXT,
+ PRIMARY KEY (( SPACE, ITEM_ID, VERSION_ID, ELEMENT_ID ), REVISION_ID)
+);
+
+CREATE TABLE IF NOT EXISTS ELEMENT_SYNCHRONIZATION_STATE (
+ SPACE TEXT,
+ ITEM_ID TEXT,
+ VERSION_ID TEXT,
+ ELEMENT_ID TEXT,
+ REVISION_ID TEXT,
+ PUBLISH_TIME TIMESTAMP,
+ DIRTY BOOLEAN,
+ PRIMARY KEY (( SPACE, ITEM_ID, VERSION_ID ), ELEMENT_ID, REVISION_ID)
+);
+
+CREATE TABLE IF NOT EXISTS ELEMENT_STAGE (
+ SPACE TEXT,
+ ITEM_ID TEXT,
+ VERSION_ID TEXT,
+ ELEMENT_ID TEXT,
+ PARENT_ID TEXT,
+ NAMESPACE TEXT,
+ INFO TEXT,
+ RELATIONS TEXT,
+ DATA BLOB,
+ SEARCHABLE_DATA BLOB,
+ VISUALIZATION BLOB,
+ SUB_ELEMENT_IDS SET<TEXT>,
+ ELEMENT_HASH TEXT,
+ PUBLISH_TIME TIMESTAMP,
+ ACTION TEXT,
+ CONFLICTED BOOLEAN,
+ CONFLICT_DEPENDENT_IDS SET<TEXT>,
+ PRIMARY KEY (( SPACE, ITEM_ID, VERSION_ID, ELEMENT_ID ))
+);
+
+CREATE TABLE IF NOT EXISTS VERSION_STAGE (
+ SPACE TEXT,
+ ITEM_ID TEXT,
+ VERSION_ID TEXT,
+ BASE_VERSION_ID TEXT,
+ CREATION_TIME TIMESTAMP,
+ MODIFICATION_TIME TIMESTAMP,
+ PUBLISH_TIME TIMESTAMP,
+ ACTION TEXT,
+ PRIMARY KEY (( SPACE, ITEM_ID ), VERSION_ID)
+); \ No newline at end of file
diff --git a/workflow/workflow-designer-init/src/main/docker/start.sh b/workflow/workflow-designer-init/src/main/docker/start.sh
new file mode 100644
index 00000000..ac89d6c0
--- /dev/null
+++ b/workflow/workflow-designer-init/src/main/docker/start.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+if [[ -z "${CS_USER}" ]]; then
+ echo "CS_USER environment variable must be set"
+ exit 1
+fi
+
+if [[ -z "${CS_PASSWORD}" ]]; then
+ echo "CS_PASSWORD environment variable must be set"
+ exit 1
+fi
+
+if [[ -z "${CS_HOST}" ]]; then
+ echo "CS_HOST environment variable must be set"
+ exit 1
+fi
+
+cqlsh -u ${CS_USER} -p ${CS_PASSWORD} -f /create_workflow_db.cql ${CS_HOST} ${CS_PORT}
diff --git a/workflow/workflow-designer-ui/pom.xml b/workflow/workflow-designer-ui/pom.xml
new file mode 100644
index 00000000..652aec65
--- /dev/null
+++ b/workflow/workflow-designer-ui/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright © 2016-2018 European Support Limited
+ ~
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>workflow-designer-ui</artifactId>
+ <packaging>pom</packaging>
+
+ <parent>
+ <groupId>org.onap.sdc.workflow_designer</groupId>
+ <artifactId>workflow-designer-parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </parent>
+
+</project>
+