summaryrefslogtreecommitdiffstats
path: root/README.md
blob: 8465dbefd3449fba6292643b27a30e8ba0f9badd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# ONAP SDC

## Introduction

SDC is the ONAP visual modeling and design tool. It creates internal metadata that describes assets used by all ONAP components, both at design time and run time.

The SDC manages the content of a catalog and logical assemblies of selected catalog items to completely define how and when VNFs are realized in a target environment.
A complete virtual assembly of specific catalog items, together with selected workflows and instance configuration data, completely defines how the deployment, activation, and life-cycle management of VNFs are accomplished.

SDC manages four levels of assets:

* Resource - A fundamental capability, implemented either entirely in software, or as software that interacts with a hardware device.
Each Resource is a combination of one or more Virtual Function Components (VFCs), along with all the information necessary to instantiate, update, delete and manage the Resource.
* Service - A well-formed object comprising one or more Resources. Service Designers create Services from Resources, and include all of the information about the Service needed to instantiate, update, delete and manage the Service.

The key output of SDC is a set of models containing descriptions of asset capabilities and instructions to manage them. These models are stored in the SDC Master Reference Catalog for the entire enterprise to use.

There are four major components of SDC:

* Catalog - The repository for assets at the Resource, Service and Product levels. Assets are added to the Catalog using the Design Studio.
* Design Studio - Used to create, modify and add Resource, Service and Product definitions in the Catalog.
* Certification Studio - Available in a future release, is used to test new assets at all levels. It will be used for sandbox experimentation, and will include support for automated testing.
* Distribution Studio - Used to deploy certified assets. From the Distribution studio, new Product assets, including their underlying Resources and Services, are deployed into lab environments for testing purposes, and into production after certification is complete. In a future release, there will be a way to export Product information to external Business Support Systems for customer ordering and billing.

## Git Configuration

Note that if you're working on Windows, it's important to enable long paths for your machine; otherwise git won't be able to handle some files.

In order to do so just add this section to your global git.config file under the `[core]` key:

    longpaths = true

## Compiling the Project

SDC is built from several projects while the parent "sdc" contains the main pom.xml for all of them:
- asdctool		- set of utilities used for scheme creation and data migration in SDC
- catalog-be		- backend code
- catalog-fe		- frontend java code (servlet, proxy)
- catalog-dao		- database layer
- catalog-model		- data model of the application
- catalog-ui		- front end code (javascript, html, css)
- common		- set of utilities used by the onboarding project
- common-app-api	- common code for frontend and backend
- common-be		- utilities, datatypes and enums
- security-utils	- handle encryption/decryption of passwords
- onboarding-be		- onboarding backend code
- onboarding-ui		- onboarding frontend code
- test-apis-ci		- the automation framework used by SDC for API based testing
- ui-ci			- the automation framework used by SDC for UI based testing, based on Selenium
- sdc-os-chef		- chefs scripts used for docker creation and startup
- utils			- set of dev utils used for working with the project locally


In order to build all the projects, as mentioned in the onap wiki https://wiki.onap.org/display/DW/Setting+Up+Your+Development+Environment, the settings.xml (https://git.onap.org/oparent/plain/settings.xml) from the oparent project must be installed in your ~/.m2 folder and referenced by your IDE.
Once maven is set up properly, go to sdc project and run the command: `mvn clean install`

Currently SDC build process also supports docker building.
Note that if you're working on Windows, you'll need to define an environment variable on your machine with key `DOCKER_HOST` and value: `tcp://<ip_address>:2375` in order to build and upload local dockers to a local environment.

For the dockers to be built during the build process use the "docker" profile by adding `-P docker` to the `mvn clean install` command

More flags to use in the build process are:
* -DskipTests - Skips unit tests execution
* -DskipUICleanup=true - Skips deleting the UI folders
* -Djacoco.skip=true - Skips running jacoco tests
* -DskipPMD - Skips creating a PMD report

**using those flags will speed up the building process of the project**

## Accessing SDC

In order to access the sdc from your local vagrant environment you'll need to run the webseal_simulator docker.
This can be achieved by using the command: `/data/scripts/simulator_docker_run.sh`

To access the simulator just go to this url: `http://<ip_address>:8285/login`

For more information regarding using the webseal_simulator please refer to the following guide: [SDC Simulator](https://wiki.onap.org/display/DW/SDC+Simulator)

## Accessing SDC UI in Dev Mode

In order to access the SDC UI from your dev environment you need to do the following:

1. Go to file `webpack.server.js` found under the catalog-ui folder in the main sdc project and update the "localhost" variable to be the ip of your local vagrant machine.
2. Navigate to the catalog-ui folder and run the command: `npm start -- --env.role <wanted_role>` with the wanted role to login to SDC as.

## SDC Containers

The following table shows the SDC containers found on the vagrant after a successful build:

| Name                | Description                                                                                                                                   |
|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
| sdc-cs              | The Docker contains our Cassandra server. On docker startup the Cassandra server is started.                                                  |
| sdc-cs-init         | The docker contains the logic for creating the needed schemas for SDC catalog server,  On docker startup, the schemes are created.            |
| sdc-cs-onboard-init | The docker contains the logic for creating the needed schemas for SDC onboarding server, On docker startup, the schemes are created.          |
| sdc-es              | The Docker contains Elastic Search server. On docker startup, Elastic Search server is started.                                               |
| sdc-init-es         | The Docker contains the logic for creating the needed mapping for SDC and the views for kibana. On docker startup, the mapping is created.    |
| sdc-onboard-BE      | The Docker contains the onboarding Backend Jetty server. On docker startup, the Jetty server is started with the application.                 |
| sdc-BE              | The Docker contains the catalog Backend Jetty server. On docker startup, the Jetty server is started with the application.                    |
| sdc-BE-init         | The docker contains the logic for importing the SDC Tosca normative types and the logic for configuring external users for SDC external APIs. |
|                     | On startup, the docker executes the rest calls to the catalog server.                                                                         |
| sdc-FE              | The Docker contains the SDC Fronted Jetty server. On docker startup, the Jetty server is started with our application.                        |

For further information and an image explaining the containers dependency map please refer to the following page: [SDC Docker Diagram](https://wiki.onap.org/display/DW/SDC+Troubleshooting)

## Testing the Project

The dockers that are responsible for running automation tests in the local environment are built as part of SDC docker profile build.

In order to run the automation tests when starting the dockers on the machine, there are 2 flags to use:

* -tad - Use this flag to run the default suite of API tests
* -tud - Use this flag to run the default suite of UI tests 

This link lists all the commands in the vagrant-onap: [Vagrant Common Commands](https://wiki.onap.org/display/DW/SDC+Vagrant+Common+Commands)

SDC docker_run script is documented here: [SDC docker_run Script Usage](https://wiki.onap.org/display/DW/SDC+docker_run+Script+Usage)

For more information regarding testing the project please refer to the following guide: [SDC Sanity](https://wiki.onap.org/display/DW/SDC+Sanity)

## SDC on OOM

For more information regarding SDC on OOM please refer to the following page: [SDC on OOM](https://wiki.onap.org/display/DW/SDC+on+OOM)

## Frontend Local Env - onboarding

### Steps:

Install nodejs & gulp
1. download nodejs from here: https://nodejs.org/en/ (take the "current" version with latest features) & install it.
2. install gulp by running the following command: npm install --global gulp-cli

### Install DOX-UI a:

1. pull for latest changes
2. go to folder dox-sequence-diagram-ui
3. run npm install
4. wait for it...
5. go to folder dox-ui
6. run npm install
7. create a copy of devConfig.defaults.json file and name it devConfig.json (we already configured git to ignore it so it will not be pushed)
8. in that file, populate the fields of the IP addresses of your BE machine you'd like to connect (pay attention, it is a JSON file): For example http://<host>:<port>
9. after everything is successful, run gulp
10. after server is up, your favorite UI will wait for you at: http://localhost:9000/sdc1/proxy-designer1#/onboardVendor

### Troubleshooting:

| Problem                       |   Why is this happening | Solution                                                                                   |
|-------------------------------|-------------------------|--------------------------------------------------------------------------------------------|
| npm cannot reach destination  | onboarding proxy        | When within onboarding network, you should set onboarding proxy to NPM as the following:   |
|                               |                         | npm config set proxy http://genproxy:8080                                                  |
|                               |                         | npm config set https-proxy http://genproxy:8080                                            |
|                               |                         |                                                                                            |
| git protocol is blocked       | onboarding network      | When within onboarding network, you should set globally that when git                      |
| and cannot connect            | rules for protocols     | protocol is used, it will be replaced with "https"                                         |
|                               |                         | git config --global url."https://".insteadOf git://                                        |
--------------------------------------------------------------------------------------------------------------------------------------------------------

## SDC Troubleshooting

In order to check the life state of SDC you can run the command `health` from inside the vagrant.
Alternatively you can run the following commands to check the FE and BE status:

FE - `curl http://<ip_address>:8181/sdc1/rest/healthCheck`

BE - `curl http://<ip_address>:8080/sdc2/rest/healthCheck`

Another method to check about problems in SDC is to look at the log files.
The log files of the SDC can be found in the `/data/logs` folder

The docker logs are found under the directory `/docker_logs`.

The jetty(Applicative) are found in the respective folder according to the wanted section
For example, the BE logs will found under the directory `/BE`.

For more information regarding SDC Troubleshooting please refer to the following guide: [SDC Troubleshooting](https://wiki.onap.org/display/DW/SDC+Troubleshooting)

## Getting Help

#####  [Mailing list](mailto:onap-sdc@lists.onap.org)

##### [JIRA](http://jira.onap.org)

##### [WIKI](https://wiki.onap.org/display/DW/Service+Design+and+Creation+%28SDC%29+Portal)
lor: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * 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.
 */

package org.openecomp.sdcrests.vsp.rest.services;

import static javax.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION;
import static org.openecomp.sdc.itempermissions.notifications.NotificationConstants.PERMISSION_USER;
import static org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductConstants.UniqueValues.VENDOR_SOFTWARE_PRODUCT_NAME;
import static org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductConstants.VALIDATION_VSP_NAME;
import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_ID;
import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_NAME;
import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.SUBMIT_DESCRIPTION;
import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.VERSION_ID;
import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.VERSION_NAME;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.inject.Named;
import javax.ws.rs.core.Response;
import org.apache.commons.collections4.MapUtils;
import org.openecomp.core.dao.UniqueValueDaoFactory;
import org.openecomp.core.util.UniqueValueUtil;
import org.openecomp.sdc.activitylog.ActivityLogManager;
import org.openecomp.sdc.activitylog.ActivityLogManagerFactory;
import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
import org.openecomp.sdc.activitylog.dao.type.ActivityType;
import org.openecomp.sdc.common.errors.CoreException;
import org.openecomp.sdc.common.errors.ErrorCode;
import org.openecomp.sdc.common.errors.Messages;
import org.openecomp.sdc.datatypes.error.ErrorMessage;
import org.openecomp.sdc.datatypes.model.ItemType;
import org.openecomp.sdc.healing.factory.HealingManagerFactory;
import org.openecomp.sdc.itempermissions.ItemPermissionsManager;
import org.openecomp.sdc.itempermissions.ItemPermissionsManagerFactory;
import org.openecomp.sdc.itempermissions.impl.types.PermissionTypes;
import org.openecomp.sdc.logging.api.Logger;
import org.openecomp.sdc.logging.api.LoggerFactory;
import org.openecomp.sdc.notification.dtos.Event;
import org.openecomp.sdc.notification.factories.NotificationPropagationManagerFactory;
import org.openecomp.sdc.notification.services.NotificationPropagationManager;
import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory;
import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager;
import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory;
import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComputeEntity;
import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OnboardingMethod;
import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateEntity;
import org.openecomp.sdc.vendorsoftwareproduct.dao.type.PackageInfo;
import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
import org.openecomp.sdc.vendorsoftwareproduct.errors.CreatePackageForNonFinalVendorSoftwareProductErrorBuilder;
import org.openecomp.sdc.vendorsoftwareproduct.errors.OnboardingMethodErrorBuilder;
import org.openecomp.sdc.vendorsoftwareproduct.errors.PackageNotFoundErrorBuilder;
import org.openecomp.sdc.vendorsoftwareproduct.types.QuestionnaireResponse;
import org.openecomp.sdc.vendorsoftwareproduct.types.ValidationResponse;
import org.openecomp.sdc.versioning.AsdcItemManager;
import org.openecomp.sdc.versioning.AsdcItemManagerFactory;
import org.openecomp.sdc.versioning.VersioningManager;
import org.openecomp.sdc.versioning.VersioningManagerFactory;
import org.openecomp.sdc.versioning.dao.types.Version;
import org.openecomp.sdc.versioning.dao.types.VersionStatus;
import org.openecomp.sdc.versioning.errors.RequestedVersionInvalidErrorBuilder;
import org.openecomp.sdc.versioning.types.Item;
import org.openecomp.sdc.versioning.types.NotificationEventTypes;
import org.openecomp.sdcrests.item.rest.mapping.MapVersionToDto;
import org.openecomp.sdcrests.item.types.ItemCreationDto;
import org.openecomp.sdc.versioning.types.ItemStatus;
import org.openecomp.sdcrests.item.types.VersionDto;
import org.openecomp.sdcrests.vendorsoftwareproducts.types.PackageInfoDto;
import org.openecomp.sdcrests.vendorsoftwareproducts.types.QuestionnaireResponseDto;
import org.openecomp.sdcrests.vendorsoftwareproducts.types.ValidationResponseDto;
import org.openecomp.sdcrests.vendorsoftwareproducts.types.VendorSoftwareProductAction;
import org.openecomp.sdcrests.vendorsoftwareproducts.types.VersionSoftwareProductActionRequestDto;
import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspComputeDto;
import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspDescriptionDto;
import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspDetailsDto;
import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspRequestDto;
import org.openecomp.sdcrests.vsp.rest.VendorSoftwareProducts;
import org.openecomp.sdcrests.vsp.rest.mapping.MapComputeEntityToVspComputeDto;
import org.openecomp.sdcrests.vsp.rest.mapping.MapItemToVspDetailsDto;
import org.openecomp.sdcrests.vsp.rest.mapping.MapPackageInfoToPackageInfoDto;
import org.openecomp.sdcrests.vsp.rest.mapping.MapQuestionnaireResponseToQuestionnaireResponseDto;
import org.openecomp.sdcrests.vsp.rest.mapping.MapValidationResponseToDto;
import org.openecomp.sdcrests.vsp.rest.mapping.MapVspDescriptionDtoToItem;
import org.openecomp.sdcrests.vsp.rest.mapping.MapVspDescriptionDtoToVspDetails;
import org.openecomp.sdcrests.vsp.rest.mapping.MapVspDetailsToDto;
import org.openecomp.sdcrests.wrappers.GenericCollectionWrapper;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Named
@Service("vendorSoftwareProducts")
@Scope(value = "prototype")
public class VendorSoftwareProductsImpl implements VendorSoftwareProducts {

  private static final String SUBMIT_ITEM_ACTION = "Submit_Item";
  private static final String ATTACHMENT_FILENAME = "attachment; filename=";
  private static final String SUBMIT_HEALED_VERSION_ERROR =
      "VSP Id %s: Error while submitting version %s created based on Certified version %s for healing purpose.";
  private static final Logger LOGGER = LoggerFactory.getLogger(VendorSoftwareProductsImpl.class);

  private static ItemCreationDto validationVsp;

  private final AsdcItemManager itemManager = AsdcItemManagerFactory.getInstance()
      .createInterface();
  private final ItemPermissionsManager permissionsManager =
      ItemPermissionsManagerFactory.getInstance().createInterface();
  private final VersioningManager versioningManager =
      VersioningManagerFactory.getInstance().createInterface();
  private final VendorSoftwareProductManager vendorSoftwareProductManager =
      VspManagerFactory.getInstance().createInterface();
  private final ActivityLogManager activityLogManager =
      ActivityLogManagerFactory.getInstance().createInterface();
  private final NotificationPropagationManager notifier =
      NotificationPropagationManagerFactory.getInstance().createInterface();
  private final UniqueValueUtil uniqueValueUtil = new UniqueValueUtil(UniqueValueDaoFactory
      .getInstance().createInterface());

  @Override
  public Response createVsp(VspRequestDto vspRequestDto, String user) {

    OnboardingMethod onboardingMethod = null;
    try {
      onboardingMethod = OnboardingMethod.valueOf(vspRequestDto.getOnboardingMethod());
    } catch (IllegalArgumentException e) {
      LOGGER.error("Error while creating VSP. Message: " + e.getMessage());
      throwUnknownOnboardingMethodException(e);
    }
    ItemCreationDto itemCreationDto = null;
    if (onboardingMethod == OnboardingMethod.NetworkPackage
        || onboardingMethod == OnboardingMethod.Manual) {
      itemCreationDto = getItemCreationDto(vspRequestDto, user, onboardingMethod);

    } else {
      throwUnknownOnboardingMethodException(
          new IllegalArgumentException("Wrong parameter Onboarding Method"));
    }

    return Response.ok(itemCreationDto).build();
  }

  private ItemCreationDto getItemCreationDto(VspRequestDto vspRequestDto,
                                             String user,
                                             OnboardingMethod onboardingMethod) {

    Item item = new MapVspDescriptionDtoToItem().applyMapping(vspRequestDto, Item.class);
    item.setType(ItemType.vsp.name());
    item.setOwner(user);
    item.setStatus(ItemStatus.ACTIVE);
    item.addProperty(VspItemProperty.ONBOARDING_METHOD, onboardingMethod.name());

    uniqueValueUtil.validateUniqueValue(VENDOR_SOFTWARE_PRODUCT_NAME, item.getName());
    item = itemManager.create(item);
    uniqueValueUtil.createUniqueValue(VENDOR_SOFTWARE_PRODUCT_NAME, item.getName());

    Version version = versioningManager.create(item.getId(), new Version(), null);

    VspDetails vspDetails =
        new MapVspDescriptionDtoToVspDetails().applyMapping(vspRequestDto, VspDetails.class);
    vspDetails.setId(item.getId());
    vspDetails.setVersion(version);
    vspDetails.setOnboardingMethod(vspRequestDto.getOnboardingMethod());

    vendorSoftwareProductManager.createVsp(vspDetails);
    versioningManager.publish(item.getId(), version, "Initial vsp:" + vspDetails.getName());
    ItemCreationDto itemCreationDto = new ItemCreationDto();
    itemCreationDto.setItemId(item.getId());
    itemCreationDto.setVersion(new MapVersionToDto().applyMapping(version, VersionDto.class));

    activityLogManager.logActivity(new ActivityLogEntity(vspDetails.getId(), version,
        ActivityType.Create, user, true, "", ""));
    return itemCreationDto;
  }

  private void throwUnknownOnboardingMethodException(IllegalArgumentException e) {
    ErrorCode onboardingMethodUpdateErrorCode = OnboardingMethodErrorBuilder
        .getInvalidOnboardingMethodErrorBuilder();
    throw new CoreException(onboardingMethodUpdateErrorCode, e);
  }

    @Override
    public Response listVsps(String versionStatus, String itemStatus, String user) {

      GenericCollectionWrapper<VspDetailsDto> results = new GenericCollectionWrapper<>();
      MapItemToVspDetailsDto mapper = new MapItemToVspDetailsDto();

      getVspList(versionStatus,itemStatus,user)
              .forEach(vspItem -> results.add(mapper.applyMapping(vspItem, VspDetailsDto.class)));

    return Response.ok(results).build();
  }

  @Override
  public Response getVsp(String vspId, String versionId, String user) {
    Version version = versioningManager.get(vspId, new Version(versionId));
    VspDetails vspDetails = vendorSoftwareProductManager.getVsp(vspId, version);
    vspDetails.setWritetimeMicroSeconds(version.getModificationTime().getTime());

    try {
      Optional<Version> healedVersion = HealingManagerFactory.getInstance().createInterface()
          .healItemVersion(vspId, version, ItemType.vsp, false);

      healedVersion.ifPresent(version1 -> {
        vspDetails.setVersion(version1);
        if (version.getStatus() == VersionStatus.Certified) {
          submitHealedVersion(vspId, version1, versionId, user);
        }
      });
    } catch (Exception e) {
      LOGGER.error(
          String.format("Error while auto healing VSP with Id %s and version %s", vspId, versionId),
          e);
    }

    VspDetailsDto vspDetailsDto =
        new MapVspDetailsToDto().applyMapping(vspDetails, VspDetailsDto.class);
    addNetworkPackageInfo(vspId, version, vspDetailsDto);

    return Response.ok(vspDetailsDto).build();
  }

  private void submitHealedVersion(String vspId, Version healedVersion, String baseVersionId,
                                   String user) {
    try {
      Optional<ValidationResponse>
          validationResponse = submit(vspId, healedVersion, "Submit healed Vsp", user);
      // TODO: 8/9/2017 before collaboration checkout was done at this scenario (equivalent
      // to new version in collaboration). need to decide what should be done now.
      validationResponse.ifPresent(validationResponse1 -> {
        throw new IllegalStateException("Certified vsp after healing failed on validation");
      });
      vendorSoftwareProductManager.createPackage(vspId, healedVersion);
    } catch (Exception ex) {
      LOGGER.error(
          String.format(SUBMIT_HEALED_VERSION_ERROR, vspId, healedVersion.getId(), baseVersionId),
          ex);
    }
  }

  @Override
  public Response updateVsp(String vspId, String versionId, VspDescriptionDto vspDescriptionDto,
                            String user) {
    VspDetails vspDetails =
        new MapVspDescriptionDtoToVspDetails().applyMapping(vspDescriptionDto, VspDetails.class);
    vspDetails.setId(vspId);
    vspDetails.setVersion(new Version(versionId));

    vendorSoftwareProductManager.updateVsp(vspDetails);

    return Response.ok().build();
  }

  @Override
  public Response deleteVsp(String vspId, String user) {
    Item vsp = itemManager.get(vspId);

    if (!vsp.getType().equals(ItemType.vsp.name())) {
      throw new CoreException((new ErrorCode.ErrorCodeBuilder()
          .withMessage(String.format("Vsp with id %s does not exist.",
              vspId)).build()));
    }

    Integer certifiedVersionsCounter = vsp.getVersionStatusCounters().get(VersionStatus.Certified);
    if (Objects.isNull(certifiedVersionsCounter) || certifiedVersionsCounter == 0) {
      versioningManager.list(vspId)
          .forEach(version -> vendorSoftwareProductManager.deleteVsp(vspId, version));
      itemManager.delete(vsp);
      permissionsManager.deleteItemPermissions(vspId);
      uniqueValueUtil.deleteUniqueValue(VENDOR_SOFTWARE_PRODUCT_NAME, vsp.getName());
      notifyUsers(vspId, vsp.getName(), null, null, user,
          NotificationEventTypes.DELETE);

      return Response.ok().build();
    } else {
      return Response.status(Response.Status.FORBIDDEN)
          .entity(new Exception(Messages.DELETE_VSP_ERROR.getErrorMessage())).build();
    }
  }

  @Override
  public Response actOnVendorSoftwareProduct(VersionSoftwareProductActionRequestDto request,
                                             String vspId, String versionId,
                                             String user) throws IOException {
    Version version = new Version(versionId);

    if (request.getAction() == VendorSoftwareProductAction.Submit) {
      if (!permissionsManager.isAllowed(vspId, user, SUBMIT_ITEM_ACTION)) {
        return Response.status(Response.Status.FORBIDDEN)
            .entity(new Exception(Messages.PERMISSIONS_ERROR.getErrorMessage())).build();
      }
      String message = request.getSubmitRequest() == null ? "Submit"
          : request.getSubmitRequest().getMessage();
      Optional<ValidationResponse> validationResponse = submit(vspId, version, message, user);

      if (validationResponse.isPresent()) {
        ValidationResponseDto validationResponseDto = new MapValidationResponseToDto()
            .applyMapping(validationResponse.get(), ValidationResponseDto.class);
        return Response.status(Response.Status.EXPECTATION_FAILED).entity(validationResponseDto)
            .build();
      }

      notifyUsers(vspId, null, version, message, user, NotificationEventTypes.SUBMIT);

    } else if (request.getAction() == VendorSoftwareProductAction.Create_Package) {
      return createPackage(vspId, version);
    }

    return Response.ok().build();
  }

  @Override
  public Response getValidationVsp(String user) {
    if (validationVsp != null) {
      return Response.ok(validationVsp).build();
    }

    VspRequestDto validationVspRequest = new VspRequestDto();
    validationVspRequest.setOnboardingMethod("HEAT");
    validationVspRequest.setName(VALIDATION_VSP_NAME);

    try {
      validationVsp = (ItemCreationDto) createVsp(validationVspRequest, user).getEntity();
      return Response.ok(validationVsp).build();

    } catch (CoreException validationVspAlreadyExistException) {
      // find validationVsp
      String validationVspId = itemManager.list(item ->
          ItemType.vsp.name().equals(item.getType()) && VALIDATION_VSP_NAME.equals(item.getName()))
          .stream().findFirst().orElseThrow(() -> new IllegalStateException("Vsp with name %s "
              + "does not exist even though the name exists according to unique value util"))
          .getId();
      Version validationVspVersion = versioningManager.list(validationVspId).iterator().next();

      validationVsp = new ItemCreationDto();
      validationVsp.setItemId(validationVspId);
      validationVsp
          .setVersion(new MapVersionToDto().applyMapping(validationVspVersion, VersionDto.class));

      return Response.ok(validationVsp).build();
    }
  }

  @Override
  public Response getOrchestrationTemplate(String vspId, String versionId, String user) {
    byte[] orchestrationTemplateFile =
        vendorSoftwareProductManager.getOrchestrationTemplateFile(vspId, new Version(versionId));

    if (orchestrationTemplateFile == null) {
      return Response.status(Response.Status.NOT_FOUND).build();
    }
    Response.ResponseBuilder response = Response.ok(orchestrationTemplateFile);
    response.header(CONTENT_DISPOSITION, ATTACHMENT_FILENAME + "LatestHeatPackage.zip");
    return response.build();
  }

  @Override
  public Response listPackages(String status, String category, String subCategory, String user) {

    List<String> VspsIds =
            getVspList(null, status != null ? ItemStatus.valueOf(status).name(): null, user)
            .stream().map(Item::getId).collect(Collectors.toList());

    List<PackageInfo> packageInfoList =
        vendorSoftwareProductManager.listPackages(category, subCategory);

    packageInfoList = packageInfoList.stream().
            filter(packageInfo -> VspsIds.contains(packageInfo.getVspId()))
            .collect(Collectors.toList());

    GenericCollectionWrapper<PackageInfoDto> results = new GenericCollectionWrapper<>();
    MapPackageInfoToPackageInfoDto mapper = new MapPackageInfoToPackageInfoDto();

    if (packageInfoList != null) {
      for (PackageInfo packageInfo : packageInfoList) {
        results.add(mapper.applyMapping(packageInfo, PackageInfoDto.class));
      }
    }
    return Response.ok(results).build();
  }

  @Override
  public Response getTranslatedFile(String vspId, String versionName, String user) {
    List<Version> versions = versioningManager.list(vspId);
    Version version;
    if (versionName == null) {
      version = versions.stream().filter(ver -> VersionStatus.Certified == ver.getStatus())
          .max(Comparator.comparingDouble(o -> Double.parseDouble(o.getName())))
          .orElseThrow(() -> new CoreException(new PackageNotFoundErrorBuilder(vspId).build()));
    } else {
      version = versions.stream().filter(ver -> versionName.equals(ver.getName()))
          .findFirst()
          .orElseThrow(() -> new CoreException(new PackageNotFoundErrorBuilder(vspId).build()));

      if (version.getStatus() != VersionStatus.Certified) {
        throw new CoreException(new RequestedVersionInvalidErrorBuilder().build());
      }
    }

    File zipFile = vendorSoftwareProductManager.getTranslatedFile(vspId, version);

    Response.ResponseBuilder response = Response.ok(zipFile);
    if (zipFile == null) {
      return Response.status(Response.Status.NOT_FOUND).build();
    }
    response.header(CONTENT_DISPOSITION, ATTACHMENT_FILENAME + zipFile.getName());

    return response.build();
  }

  @Override
  public Response getQuestionnaire(String vspId, String versionId, String user) {
    QuestionnaireResponse questionnaireResponse =
        vendorSoftwareProductManager.getVspQuestionnaire(vspId, new Version(versionId));

    if (questionnaireResponse.getErrorMessage() != null) {
      return Response.status(Response.Status.EXPECTATION_FAILED).entity(
          new MapQuestionnaireResponseToQuestionnaireResponseDto()
              .applyMapping(questionnaireResponse, QuestionnaireResponseDto.class)).build();
    }

    QuestionnaireResponseDto result = new MapQuestionnaireResponseToQuestionnaireResponseDto()
        .applyMapping(questionnaireResponse, QuestionnaireResponseDto.class);
    return Response.ok(result).build();
  }

  @Override
  public Response updateQuestionnaire(String questionnaireData, String vspId, String
      versionId, String user) {
    vendorSoftwareProductManager
        .updateVspQuestionnaire(vspId, new Version(versionId), questionnaireData);
    return Response.ok().build();
  }

  @Override
  public Response heal(String vspId, String versionId, String user) {
    HealingManagerFactory.getInstance().createInterface()
        .healItemVersion(vspId, new Version(versionId), ItemType.vsp, true);
    return Response.ok().build();
  }

  @Override
  public Response getVspInformationArtifact(String vspId, String versionId, String user) {
    File textInformationArtifact =
        vendorSoftwareProductManager.getInformationArtifact(vspId, new Version(versionId));

    Response.ResponseBuilder response = Response.ok(textInformationArtifact);
    if (textInformationArtifact == null) {
      return Response.status(Response.Status.NOT_FOUND).build();
    }
    response
        .header(CONTENT_DISPOSITION, ATTACHMENT_FILENAME + textInformationArtifact.getName());
    return response.build();
  }

  @Override
  public Response listComputes(String vspId, String version, String user) {

    Collection<ComputeEntity> computes =
        vendorSoftwareProductManager.getComputeByVsp(vspId, new Version(version));

    MapComputeEntityToVspComputeDto mapper = new MapComputeEntityToVspComputeDto();
    GenericCollectionWrapper<VspComputeDto> results = new GenericCollectionWrapper<>();
    for (ComputeEntity compute : computes) {
      results.add(mapper.applyMapping(compute, VspComputeDto.class));
    }

    return Response.ok(results).build();
  }

  private Optional<ValidationResponse> submit(String vspId, Version version, String message,
                                              String user) throws IOException {

    ValidationResponse validationResponse = vendorSoftwareProductManager.validate(vspId, version);
    Map<String, List<ErrorMessage>> compilationErrors =
        vendorSoftwareProductManager.compile(vspId, version);
    if (!validationResponse.isValid() || MapUtils.isNotEmpty(compilationErrors)) {

      activityLogManager.logActivity(
          new ActivityLogEntity(vspId, version, ActivityType.Submit, user, false,
              "Failed on validation before submit", ""));
      return Optional.of(validationResponse);
    }

    versioningManager.submit(vspId, version, message);

    activityLogManager.logActivity(
        new ActivityLogEntity(vspId, version, ActivityType.Submit, user, true, "", message));
    return Optional.empty();
  }

  private void notifyUsers(String itemId, String itemName, Version version, String message,
                           String userName, NotificationEventTypes eventType) {
    Map<String, Object> eventProperties = new HashMap<>();
    eventProperties
        .put(ITEM_NAME, itemName == null ? itemManager.get(itemId).getName() : itemName);
    eventProperties.put(ITEM_ID, itemId);

    if (version != null) {
      eventProperties.put(VERSION_NAME, version.getName() == null
          ? versioningManager.get(itemId, version).getName()
          : version.getName());
      eventProperties.put(VERSION_ID, version.getId());
    }

    eventProperties.put(SUBMIT_DESCRIPTION, message);
    eventProperties.put(PERMISSION_USER, userName);

    Event syncEvent = new SyncEvent(eventType.getEventName(), itemId, eventProperties, itemId);
    try {
      notifier.notifySubscribers(syncEvent, userName);
    } catch (Exception e) {
      LOGGER.error("Failed to send sync notification to users subscribed o item '" + itemId);
    }
  }

  private class SyncEvent implements Event {

    private final String eventType;
    private final String originatorId;
    private final Map<String, Object> attributes;
    private final String entityId;

    SyncEvent(String eventType, String originatorId,
              Map<String, Object> attributes, String entityId) {
      this.eventType = eventType;
      this.originatorId = originatorId;
      this.attributes = attributes;
      this.entityId = entityId;
    }

    @Override
    public String getEventType() {
      return eventType;
    }

    @Override
    public String getOriginatorId() {
      return originatorId;
    }

    @Override
    public Map<String, Object> getAttributes() {
      return attributes;
    }

    @Override
    public String getEntityId() {
      return entityId;
    }
  }

  private Response createPackage(String vspId, Version version) throws IOException {
    Version retrievedVersion = versioningManager.get(vspId, version);
    if (retrievedVersion.getStatus() != VersionStatus.Certified) {
      throw new CoreException(
          new CreatePackageForNonFinalVendorSoftwareProductErrorBuilder(vspId, version)
              .build());
    }
    PackageInfo packageInfo =
        vendorSoftwareProductManager.createPackage(vspId, retrievedVersion);
    return Response.ok(packageInfo == null
        ? null
        : new MapPackageInfoToPackageInfoDto().applyMapping(packageInfo, PackageInfoDto.class))
        .build();
  }

  private void addNetworkPackageInfo(String vspId, Version version, VspDetailsDto vspDetailsDto) {
    OrchestrationTemplateCandidateData candidateInfo =
        OrchestrationTemplateCandidateManagerFactory.getInstance().createInterface()
            .getInfo(vspId, version);
    if (Objects.nonNull(candidateInfo) && Objects.nonNull(candidateInfo.getFileSuffix())) {
      vspDetailsDto.setValidationData(candidateInfo.getValidationDataStructure());
      vspDetailsDto.setNetworkPackageName(candidateInfo.getFileName());
      vspDetailsDto.setCandidateOnboardingOrigin(candidateInfo.getFileSuffix());
    } else {
      OrchestrationTemplateEntity orchestrationTemplateInfo =
          vendorSoftwareProductManager.getOrchestrationTemplateInfo(vspId, version);
      if (Objects.nonNull(orchestrationTemplateInfo)) {
        vspDetailsDto.setValidationData(orchestrationTemplateInfo.getValidationDataStructure());
        vspDetailsDto.setNetworkPackageName(orchestrationTemplateInfo.getFileName());
        vspDetailsDto.setOnboardingOrigin(orchestrationTemplateInfo.getFileSuffix());
      }
    }
  }

  private boolean userHasPermission(String itemId, String userId) {
    String permission = permissionsManager.getUserItemPermiission(itemId, userId);
    return permission != null && permission
        .matches(PermissionTypes.Contributor.name() + "|" + PermissionTypes.Owner.name());
  }


  private Predicate<Item> createItemPredicate(String versionStatus,
                                              String itemStatus,
                                              String user) {
    Predicate<Item> itemPredicate = item -> ItemType.vsp.name().equals(item.getType());

    if (ItemStatus.ARCHIVED.name().equals(itemStatus)) {
      itemPredicate = itemPredicate.and(item -> ItemStatus.ARCHIVED.equals(item.getStatus()));
    } else {
      itemPredicate = itemPredicate.and(item -> ItemStatus.ACTIVE.equals(item.getStatus()));

      if (VersionStatus.Certified.name().equals(versionStatus)) {
        itemPredicate = itemPredicate
                .and(item -> item.getVersionStatusCounters().containsKey(VersionStatus.Certified));

      } else if (VersionStatus.Draft.name().equals(versionStatus)) {
        itemPredicate = itemPredicate.and(
                item -> item.getVersionStatusCounters().containsKey(VersionStatus.Draft)
                        && userHasPermission(item.getId(), user));
      }
    }
    return itemPredicate;
  }

  private List<Item> getVspList(String versionStatus, String itemStatus, String user) {

    Predicate<Item> itemPredicate = createItemPredicate(versionStatus, itemStatus, user);

    return itemManager.list(itemPredicate).stream()
            .sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime())).
            collect(Collectors.toList());

  }
}