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.services.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.common.versioning.services.ItemManager;
33 import org.onap.sdc.common.versioning.services.VersioningManager;
34 import org.onap.sdc.common.versioning.services.types.Item;
35 import org.onap.sdc.common.versioning.services.types.ItemStatus;
36 import org.onap.sdc.common.versioning.services.types.Version;
37 import org.onap.sdc.common.versioning.services.types.VersionCreationMethod;
38 import org.onap.sdc.common.versioning.services.types.VersionStatus;
39 import org.onap.sdc.workflow.persistence.ArtifactRepository;
40 import org.onap.sdc.workflow.persistence.ParameterRepository;
41 import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
42 import org.onap.sdc.workflow.persistence.types.ParameterEntity;
43 import org.onap.sdc.workflow.persistence.types.ParameterRole;
44 import org.onap.sdc.workflow.services.WorkflowVersionManager;
45 import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
46 import org.onap.sdc.workflow.services.exceptions.InvalidArtifactException;
47 import org.onap.sdc.workflow.services.exceptions.VersionCreationException;
48 import org.onap.sdc.workflow.services.exceptions.VersionModificationException;
49 import org.onap.sdc.workflow.services.exceptions.VersionStateModificationException;
50 import org.onap.sdc.workflow.services.exceptions.VersionStateModificationMissingArtifactException;
51 import org.onap.sdc.workflow.services.exceptions.WorkflowModificationException;
52 import org.onap.sdc.workflow.services.impl.mappers.VersionMapper;
53 import org.onap.sdc.workflow.services.impl.mappers.VersionStateMapper;
54 import org.onap.sdc.workflow.services.types.WorkflowVersion;
55 import org.onap.sdc.workflow.services.types.WorkflowVersionState;
56 import org.openecomp.sdc.logging.api.Logger;
57 import org.openecomp.sdc.logging.api.LoggerFactory;
58 import org.springframework.beans.factory.annotation.Autowired;
59 import org.springframework.stereotype.Service;
60 import org.springframework.util.StringUtils;
61 import org.springframework.web.multipart.MultipartFile;
63 @Service("workflowVersionManager")
64 public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
66 private static final String VERSION_NOT_EXIST_MSG = "version with id '%s' does not exist for workflow with id '%s'";
67 private final VersioningManager versioningManager;
68 private final ItemManager itemManager;
69 private final ArtifactRepository artifactRepository;
70 private final ParameterRepository parameterRepository;
71 private final VersionMapper versionMapper;
72 private final VersionStateMapper versionStateMapper;
73 private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowVersionManagerImpl.class);
76 public WorkflowVersionManagerImpl(VersioningManager versioningManager, ArtifactRepository artifactRepository,
77 VersionMapper versionMapper, VersionStateMapper versionStateMapper, ItemManager itemManager,
78 ParameterRepository parameterRepository) {
79 this.itemManager = itemManager;
80 this.versioningManager = versioningManager;
81 this.artifactRepository = artifactRepository;
82 this.parameterRepository = parameterRepository;
83 this.versionMapper = versionMapper;
84 this.versionStateMapper = versionStateMapper;
88 public Collection<WorkflowVersion> list(String workflowId, Set<WorkflowVersionState> stateFilter) {
89 Set<VersionStatus> versionStatusFilter =
90 stateFilter == null ? null :
91 stateFilter.stream().map(versionStateMapper::workflowVersionStateToVersionStatus)
92 .collect(Collectors.toSet());
94 return versioningManager.list(workflowId).stream()
95 .filter(version -> versionStatusFilter == null || versionStatusFilter.contains(
97 .map(versionMapper::fromVersion)
98 .sorted(Comparator.comparing(WorkflowVersion::getName).reversed())
99 .peek(workflowVersion -> loadAndAddParameters(workflowId, workflowVersion))
100 .collect(Collectors.toList());
104 public WorkflowVersion get(String workflowId, String versionId) {
105 WorkflowVersion workflowVersion = versionMapper.fromVersion(getVersion(workflowId, versionId));
106 loadAndAddParameters(workflowId, workflowVersion);
107 workflowVersion.setHasArtifact(artifactRepository.isExist(workflowId,versionId));
108 return workflowVersion;
112 public WorkflowVersion create(String workflowId, String baseVersionId, WorkflowVersion workflowVersion) {
113 validateWorkflowStatus(workflowId);
114 List<Version> versions = versioningManager.list(workflowId);
116 if (baseVersionId != null) {
117 if (!workflowVersion.getInputs().isEmpty() || !workflowVersion.getOutputs().isEmpty()) {
118 throw new VersionCreationException(workflowId, baseVersionId, "Inputs/Outputs should not be supplied");
120 validateVersionExistAndCertified(workflowId, versions, baseVersionId);
121 } else if (!versions.isEmpty()) {
122 throw new VersionCreationException(workflowId);
125 Version version = new Version();
126 version.setDescription(workflowVersion.getDescription());
127 Version createdVersion = versioningManager.create(workflowId, baseVersionId, version, VersionCreationMethod.major);
129 if (versions.isEmpty()) { // only for first versionId
130 artifactRepository.createStructure(workflowId, createdVersion.getId());
131 parameterRepository.createStructure(workflowId, createdVersion.getId());
132 updateParameters(workflowId, createdVersion.getId(), workflowVersion.getInputs(), workflowVersion.getOutputs());
133 versioningManager.publish(workflowId, createdVersion.getId(), "Add initial data");
136 return get(workflowId, createdVersion.getId());
140 public void update(String workflowId, WorkflowVersion workflowVersion) {
141 validateWorkflowStatus(workflowId);
142 Version version = getVersion(workflowId, workflowVersion.getId());
143 if (CERTIFIED.equals(versionStateMapper.versionStatusToWorkflowVersionState(version.getStatus()))) {
144 throw new VersionModificationException(workflowId, workflowVersion.getId());
147 versionMapper.toVersion(workflowVersion, version);
149 updateParameters(workflowId, version.getId(), workflowVersion.getInputs(), workflowVersion.getOutputs());
151 versioningManager.update(workflowId, version.getId(), version);
153 Version updatedVersion = versioningManager.get(workflowId, version.getId());
154 if (updatedVersion.getState().isDirty()) {
155 versioningManager.publish(workflowId, version.getId(), "Update version");
161 public WorkflowVersionState getState(String workflowId, String versionId) {
162 return versionStateMapper.versionStatusToWorkflowVersionState(getVersion(workflowId, versionId).getStatus());
166 public void updateState(String workflowId, String versionId, WorkflowVersionState newState) {
167 WorkflowVersionState currentState = getState(workflowId, versionId);
168 if (newState == CERTIFIED) {
169 if(!artifactRepository.isExist(workflowId,versionId)){
170 throw new VersionStateModificationMissingArtifactException(workflowId, versionId, currentState,
174 versioningManager.updateStatus(workflowId, versionId, VersionStatus.Certified,
175 String.format("Update version state to %s", newState.name()));
176 } catch (Exception submitException) {
177 throw new VersionStateModificationException(workflowId, versionId, currentState, newState,
181 throw new VersionStateModificationException(workflowId, versionId, currentState, newState);
186 public void uploadArtifact(String workflowId, String versionId, MultipartFile artifact) {
187 validateWorkflowStatus(workflowId);
188 Version retrievedVersion = getVersion(workflowId, versionId);
189 if (CERTIFIED.equals(versionStateMapper.versionStatusToWorkflowVersionState(retrievedVersion.getStatus()))) {
190 throw new VersionModificationException(workflowId, versionId);
193 try (InputStream artifactData = artifact.getInputStream()) {
194 ArtifactEntity artifactEntity =
195 new ArtifactEntity(StringUtils.cleanPath(artifact.getOriginalFilename()), artifactData);
196 artifactRepository.update(workflowId, versionId, artifactEntity);
197 Version updatedVersion = versioningManager.get(workflowId, versionId);
198 if(updatedVersion.getState().isDirty()) {
199 versioningManager.publish(workflowId, updatedVersion.getId(), "Update artifact");
202 } catch (IOException e) {
203 LOGGER.error(String.format("Upload Artifact failed for workflow id %s and version id %s",
204 workflowId, versionId),e);
205 throw new InvalidArtifactException(e.getMessage());
210 public ArtifactEntity getArtifact(String workflowId, String versionId) {
211 getVersion(workflowId, versionId);
212 Optional<ArtifactEntity> artifactOptional = artifactRepository.get(workflowId, versionId);
213 if (!artifactOptional.isPresent()) {
214 LOGGER.error("Workflow Version Artifact was not found for workflow id {} and version id {}",
215 workflowId, versionId);
216 throw new EntityNotFoundException(
217 String.format("Artifact for workflow id %s version id %s was not found", workflowId, versionId));
219 return artifactOptional.get();
223 public void deleteArtifact(String workflowId, String versionId) {
224 validateWorkflowStatus(workflowId);
225 WorkflowVersion retrievedVersion = get(workflowId, versionId);
226 if (CERTIFIED.equals(retrievedVersion.getState())) {
227 LOGGER.error("Workflow Version is certified and can not be edited.Workflow id {} and version id {}",
228 workflowId, versionId);
229 throw new VersionModificationException(workflowId, versionId);
231 if(retrievedVersion.isHasArtifact()) {
232 artifactRepository.delete(workflowId, versionId);
233 versioningManager.publish(workflowId, versionId, "Delete Artifact");
237 private void validateVersionExistAndCertified(String workflowId, List<Version> versions, String versionId) {
238 Version baseVersion = findVersion(versions, versionId).orElseThrow(
239 () -> new EntityNotFoundException(String.format(VERSION_NOT_EXIST_MSG, versionId, workflowId)));
241 if (CERTIFIED != versionStateMapper.versionStatusToWorkflowVersionState(baseVersion.getStatus())) {
242 throw new VersionCreationException(workflowId, versionId, "base version must be CERTIFIED");
246 private Version getVersion(String workflowId, String versionId) {
248 Version version = versioningManager.get(workflowId, versionId);
249 if (version == null) {
250 throw new EntityNotFoundException(String.format(VERSION_NOT_EXIST_MSG, versionId, workflowId));
253 } catch (Exception e) {
254 LOGGER.error(String.format(
255 "Workflow Version was not found.Workflow id %s and version id %s", workflowId,
257 throw new EntityNotFoundException(String.format(VERSION_NOT_EXIST_MSG, versionId, workflowId));
261 private void updateParameters(String workflowId, String versionId, Collection<ParameterEntity> inputs,
262 Collection<ParameterEntity> outputs) {
263 updateVersionParameters(workflowId, versionId, ParameterRole.INPUT, inputs);
264 updateVersionParameters(workflowId, versionId, ParameterRole.OUTPUT, outputs);
267 private void updateVersionParameters(String workflowId, String versionId, ParameterRole role,
268 Collection<ParameterEntity> parameters) {
270 Collection<ParameterEntity> retrievedParams = parameterRepository.list(workflowId, versionId, role);
271 Map<String, ParameterEntity> retrievedParamsByName =
272 retrievedParams.stream().collect(Collectors.toMap(ParameterEntity::getName, Function.identity()));
274 Set<String> namesOfParamsToKeep = new HashSet<>();
275 for (ParameterEntity parameter : parameters) {
277 ParameterEntity retrievedParam = retrievedParamsByName.get(parameter.getName());
278 if (retrievedParam == null) {
279 parameterRepository.create(workflowId, versionId, role, parameter);
281 parameter.setId(retrievedParam.getId());
282 parameterRepository.update(workflowId, versionId, role, parameter);
283 namesOfParamsToKeep.add(parameter.getName());
287 retrievedParams.stream().filter(retrievedParam -> !namesOfParamsToKeep.contains(retrievedParam.getName()))
288 .forEach(retrievedParam -> parameterRepository
289 .delete(workflowId, versionId, retrievedParam.getId()));
292 private void loadAndAddParameters(String workflowId, WorkflowVersion workflowVersion) {
293 workflowVersion.setInputs(parameterRepository.list(workflowId, workflowVersion.getId(), ParameterRole.INPUT));
294 workflowVersion.setOutputs(parameterRepository.list(workflowId, workflowVersion.getId(), ParameterRole.OUTPUT));
297 private static Optional<Version> findVersion(List<Version> versions, String versionId) {
298 return versions.stream().filter(version -> versionId.equals(version.getId())).findFirst();
301 void validateWorkflowStatus(String workflowId) {
302 Item workflowItem = itemManager.get(workflowId);
303 if (ItemStatus.ARCHIVED.equals(workflowItem.getStatus())) {
304 throw new WorkflowModificationException(workflowId);