2  * Copyright © 2018 European Support Limited
 
   4  * Licensed under the Apache License, Version 2.0 (the "License");
 
   5  * you may not use this file except in compliance with the License.
 
   6  * You may obtain a copy of the License at
 
   8  *      http://www.apache.org/licenses/LICENSE-2.0
 
  10  * Unless required by applicable law or agreed to in writing, software
 
  11  * distributed under the License is distributed on an "AS IS" BASIS,
 
  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  13  * See the License for the specific language governing permissions and
 
  14  * limitations under the License.
 
  17 package org.onap.sdc.workflow.services.impl;
 
  19 import static org.onap.sdc.workflow.persistence.types.WorkflowVersionState.CERTIFIED;
 
  21 import java.io.IOException;
 
  22 import java.io.InputStream;
 
  23 import java.util.Collection;
 
  24 import java.util.Comparator;
 
  25 import java.util.HashSet;
 
  26 import java.util.List;
 
  28 import java.util.Optional;
 
  30 import java.util.function.Function;
 
  31 import java.util.stream.Collectors;
 
  32 import org.onap.sdc.workflow.persistence.ArtifactRepository;
 
  33 import org.onap.sdc.workflow.persistence.ParameterRepository;
 
  34 import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
 
  35 import org.onap.sdc.workflow.persistence.types.ParameterEntity;
 
  36 import org.onap.sdc.workflow.persistence.types.ParameterRole;
 
  37 import org.onap.sdc.workflow.persistence.types.WorkflowVersion;
 
  38 import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
 
  39 import org.onap.sdc.workflow.services.WorkflowVersionManager;
 
  40 import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
 
  41 import org.onap.sdc.workflow.services.exceptions.InvalidArtifactException;
 
  42 import org.onap.sdc.workflow.services.exceptions.VersionCreationException;
 
  43 import org.onap.sdc.workflow.services.exceptions.VersionModificationException;
 
  44 import org.onap.sdc.workflow.services.exceptions.VersionStateModificationException;
 
  45 import org.onap.sdc.workflow.services.impl.mappers.VersionMapper;
 
  46 import org.onap.sdc.workflow.services.impl.mappers.VersionStateMapper;
 
  47 import org.openecomp.sdc.logging.api.Logger;
 
  48 import org.openecomp.sdc.logging.api.LoggerFactory;
 
  49 import org.openecomp.sdc.versioning.VersioningManager;
 
  50 import org.openecomp.sdc.versioning.dao.types.Version;
 
  51 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
 
  52 import org.openecomp.sdc.versioning.types.VersionCreationMethod;
 
  53 import org.springframework.beans.factory.annotation.Autowired;
 
  54 import org.springframework.stereotype.Service;
 
  55 import org.springframework.util.StringUtils;
 
  56 import org.springframework.web.multipart.MultipartFile;
 
  58 @Service("workflowVersionManager")
 
  59 public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
 
  61     private static final String VERSION_NOT_EXIST_MSG = "version with id '%s' does not exist for workflow with id '%s'";
 
  62     private final VersioningManager versioningManager;
 
  63     private final ArtifactRepository artifactRepository;
 
  64     private final ParameterRepository parameterRepository;
 
  65     private final VersionMapper versionMapper;
 
  66     private final VersionStateMapper versionStateMapper;
 
  67     private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowVersionManagerImpl.class);
 
  70     public WorkflowVersionManagerImpl(VersioningManager versioningManager, ArtifactRepository artifactRepository,
 
  71             VersionMapper versionMapper, VersionStateMapper versionStateMapper,
 
  72             ParameterRepository parameterRepository) {
 
  73         this.versioningManager = versioningManager;
 
  74         this.artifactRepository = artifactRepository;
 
  75         this.parameterRepository = parameterRepository;
 
  76         this.versionMapper = versionMapper;
 
  77         this.versionStateMapper = versionStateMapper;
 
  81     public Collection<WorkflowVersion> list(String workflowId, Set<WorkflowVersionState> stateFilter) {
 
  82         Set<VersionStatus> versionStatusFilter =
 
  83                 stateFilter == null ? null :
 
  84                         stateFilter.stream().map(versionStateMapper::workflowVersionStateToVersionStatus)
 
  85                                            .collect(Collectors.toSet());
 
  87         return versioningManager.list(workflowId).stream()
 
  88                                 .filter(version -> versionStatusFilter == null || versionStatusFilter.contains(
 
  90                                 .map(versionMapper::versionToWorkflowVersion)
 
  91                                 .sorted(Comparator.comparing(WorkflowVersion::getName).reversed())
 
  92                                 .peek(workflowVersion -> loadAndAddParameters(workflowId, workflowVersion))
 
  93                                 .collect(Collectors.toList());
 
  97     public WorkflowVersion get(String workflowId, String versionId) {
 
  98         WorkflowVersion workflowVersion = versionMapper.versionToWorkflowVersion(getVersion(workflowId, versionId));
 
  99         loadAndAddParameters(workflowId, workflowVersion);
 
 100         workflowVersion.setHasArtifact(artifactRepository.isExist(workflowId,versionId));
 
 101         return workflowVersion;
 
 105     public WorkflowVersion create(String workflowId, String baseVersionId, WorkflowVersion workflowVersion) {
 
 106         List<Version> versions = versioningManager.list(workflowId);
 
 108         if (baseVersionId != null) {
 
 109             if (!workflowVersion.getInputs().isEmpty() || !workflowVersion.getOutputs().isEmpty()) {
 
 110                 throw new VersionCreationException(workflowId, baseVersionId, "Inputs/Outputs should not be supplied");
 
 112             validateVersionExistAndCertified(workflowId, versions, baseVersionId);
 
 113         } else if (!versions.isEmpty()) {
 
 114             throw new VersionCreationException(workflowId);
 
 117         Version version = new Version();
 
 118         version.setDescription(workflowVersion.getDescription());
 
 119         version.setBaseId(baseVersionId);
 
 120         Version createdVersion = versioningManager.create(workflowId, version, VersionCreationMethod.major);
 
 122         if (versions.isEmpty()) { // only for first version
 
 123             artifactRepository.createStructure(workflowId, createdVersion.getId());
 
 124             parameterRepository.createStructure(workflowId, createdVersion.getId());
 
 125             updateParameters(workflowId, createdVersion.getId(), workflowVersion.getInputs(), workflowVersion.getOutputs());
 
 126             versioningManager.publish(workflowId, createdVersion, "Add initial data");
 
 129         return get(workflowId, createdVersion.getId());
 
 133     public void update(String workflowId, WorkflowVersion workflowVersion) {
 
 134         Version retrievedVersion = getVersion(workflowId, workflowVersion.getId());
 
 135         if (CERTIFIED.equals(versionStateMapper.versionStatusToWorkflowVersionState(retrievedVersion.getStatus()))) {
 
 136             throw new VersionModificationException(workflowId, workflowVersion.getId());
 
 139         Version version = versionMapper.workflowVersionToVersion(workflowVersion);
 
 140         version.setName(retrievedVersion.getName());
 
 141         version.setStatus(retrievedVersion.getStatus());
 
 143         updateParameters(workflowId, version.getId(), workflowVersion.getInputs(), workflowVersion.getOutputs());
 
 145         versioningManager.updateVersion(workflowId, version);
 
 147         Version updatedVersion = versioningManager.get(workflowId, version);
 
 148         if(updatedVersion.getState().isDirty()) {
 
 149             versioningManager.publish(workflowId, version, "Update version");
 
 155     public WorkflowVersionState getState(String workflowId, String versionId) {
 
 156         return versionStateMapper.versionStatusToWorkflowVersionState(getVersion(workflowId, versionId).getStatus());
 
 160     public void updateState(String workflowId, String versionId, WorkflowVersionState state) {
 
 161         WorkflowVersionState retrievedState =
 
 162                 versionStateMapper.versionStatusToWorkflowVersionState(getVersion(workflowId, versionId).getStatus());
 
 164         if (state == CERTIFIED) {
 
 166                 versioningManager.submit(workflowId, new Version(versionId),
 
 167                         String.format("Update version state to %s", state.name()));
 
 168             } catch (Exception e) {
 
 169                 throw new VersionStateModificationException(workflowId, versionId, retrievedState, state);
 
 172             throw new VersionStateModificationException(workflowId, versionId, retrievedState, state);
 
 177     public void uploadArtifact(String workflowId, String versionId, MultipartFile artifact) {
 
 178         Version retrievedVersion = getVersion(workflowId, versionId);
 
 179         if (CERTIFIED.equals(versionStateMapper.versionStatusToWorkflowVersionState(retrievedVersion.getStatus()))) {
 
 180             throw new VersionModificationException(workflowId, versionId);
 
 183         try (InputStream artifactData = artifact.getInputStream()) {
 
 184             ArtifactEntity artifactEntity =
 
 185                     new ArtifactEntity(StringUtils.cleanPath(artifact.getOriginalFilename()), artifactData);
 
 186             artifactRepository.update(workflowId, versionId, artifactEntity);
 
 187             Version updatedVersion = versioningManager.get(workflowId, new Version(versionId));
 
 188             if(updatedVersion.getState().isDirty()) {
 
 189                 versioningManager.publish(workflowId, updatedVersion, "Update artifact");
 
 192         } catch (IOException e) {
 
 193             LOGGER.error(String.format("Upload Artifact failed for workflow id %s and version id %s",
 
 194                     workflowId, versionId),e);
 
 195             throw new InvalidArtifactException(e.getMessage());
 
 200     public ArtifactEntity getArtifact(String workflowId, String versionId) {
 
 201         getVersion(workflowId, versionId);
 
 202         Optional<ArtifactEntity> artifactOptional = artifactRepository.get(workflowId, versionId);
 
 203         if (!artifactOptional.isPresent()) {
 
 204             LOGGER.error(String.format("Workflow Version Artifact was not found for workflow id %s and version id %s",
 
 205                     workflowId, versionId));
 
 206             throw new EntityNotFoundException(
 
 207                     String.format("Artifact for workflow id %S version id %S was not found", workflowId, versionId));
 
 209         return artifactOptional.get();
 
 213     public void deleteArtifact(String workflowId, String versionId) {
 
 214         WorkflowVersion retrievedVersion = get(workflowId, versionId);
 
 215         if (CERTIFIED.equals(retrievedVersion.getState())) {
 
 216             LOGGER.error(String.format(
 
 217                     "Workflow Version is certified and can not be edited.Workflow id %s and version id %s", workflowId,
 
 219             throw new VersionModificationException(workflowId, versionId);
 
 222         artifactRepository.delete(workflowId, versionId);
 
 223         versioningManager.publish(workflowId, new Version(versionId), "Delete Artifact");
 
 226     private void validateVersionExistAndCertified(String workflowId, List<Version> versions, String versionId) {
 
 227         Version baseVersion = findVersion(versions, versionId).orElseThrow(
 
 228                 () -> new EntityNotFoundException(String.format(VERSION_NOT_EXIST_MSG, versionId, workflowId)));
 
 230         if (CERTIFIED != versionStateMapper.versionStatusToWorkflowVersionState(baseVersion.getStatus())) {
 
 231             throw new VersionCreationException(workflowId, versionId, "base version must be CERTIFIED");
 
 235     private Version getVersion(String workflowId, String versionId) {
 
 237             Version version = versioningManager.get(workflowId, new Version(versionId));
 
 238             if (version == null) {
 
 239                 throw new EntityNotFoundException(String.format(VERSION_NOT_EXIST_MSG, versionId, workflowId));
 
 242         } catch (Exception e) {
 
 243             LOGGER.error(String.format(
 
 244                     "Workflow Version was not found.Workflow id %s and version id %s", workflowId,
 
 246             throw new EntityNotFoundException(String.format(VERSION_NOT_EXIST_MSG, versionId, workflowId));
 
 250     private void updateParameters(String workflowId, String versionId, Collection<ParameterEntity> inputs,
 
 251             Collection<ParameterEntity> outputs) {
 
 252         updateVersionParameters(workflowId, versionId, ParameterRole.INPUT, inputs);
 
 253         updateVersionParameters(workflowId, versionId, ParameterRole.OUTPUT, outputs);
 
 256     private void updateVersionParameters(String workflowId, String versionId, ParameterRole role,
 
 257             Collection<ParameterEntity> parameters) {
 
 259         Collection<ParameterEntity> retrievedParams = parameterRepository.list(workflowId, versionId, role);
 
 260         Map<String, ParameterEntity> retrievedParamsByName =
 
 261                 retrievedParams.stream().collect(Collectors.toMap(ParameterEntity::getName, Function.identity()));
 
 263         Set<String> namesOfParamsToKeep = new HashSet<>();
 
 264         for (ParameterEntity parameter : parameters) {
 
 266             ParameterEntity retrievedParam = retrievedParamsByName.get(parameter.getName());
 
 267             if (retrievedParam == null) {
 
 268                 parameterRepository.create(workflowId, versionId, role, parameter);
 
 270                 parameterRepository.update(workflowId, versionId, role, parameter);
 
 271                 namesOfParamsToKeep.add(parameter.getName());
 
 275         retrievedParams.stream().filter(retrievedParam -> !namesOfParamsToKeep.contains(retrievedParam.getName()))
 
 276                        .forEach(retrievedParam -> parameterRepository
 
 277                                                           .delete(workflowId, versionId, retrievedParam.getId()));
 
 280     private void loadAndAddParameters(String workflowId, WorkflowVersion workflowVersion) {
 
 281         workflowVersion.setInputs(parameterRepository.list(workflowId, workflowVersion.getId(), ParameterRole.INPUT));
 
 282         workflowVersion.setOutputs(parameterRepository.list(workflowId, workflowVersion.getId(), ParameterRole.OUTPUT));
 
 285     private static Optional<Version> findVersion(List<Version> versions, String versionId) {
 
 286         return versions.stream().filter(version -> versionId.equals(version.getId())).findFirst();