Support for adding artifact types
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ArtifactsBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2020 Nokia
20  * ================================================================================
21  */
22 package org.openecomp.sdc.be.components.impl;
23
24 import static org.openecomp.sdc.be.dao.api.ActionStatus.MISMATCH_BETWEEN_ARTIFACT_TYPE_AND_COMPONENT_TYPE;
25
26 import com.google.common.annotations.VisibleForTesting;
27 import com.google.gson.Gson;
28 import com.google.gson.GsonBuilder;
29 import fj.data.Either;
30 import io.vavr.control.Option;
31 import java.math.BigDecimal;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.Comparator;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Map.Entry;
40 import java.util.Objects;
41 import java.util.Optional;
42 import java.util.Set;
43 import java.util.function.Consumer;
44 import java.util.function.Function;
45 import java.util.function.Predicate;
46 import java.util.function.Supplier;
47 import java.util.stream.Collectors;
48 import javax.servlet.http.HttpServletRequest;
49 import org.apache.commons.codec.binary.Base64;
50 import org.apache.commons.collections.CollectionUtils;
51 import org.apache.commons.collections.MapUtils;
52 import org.apache.commons.io.FilenameUtils;
53 import org.apache.commons.lang3.ArrayUtils;
54 import org.apache.commons.lang3.StringUtils;
55 import org.apache.commons.lang3.tuple.ImmutablePair;
56 import org.openecomp.sdc.be.components.ArtifactsResolver;
57 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
58 import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo;
59 import org.openecomp.sdc.be.components.impl.artifact.ArtifactTypeToPayloadTypeSelector;
60 import org.openecomp.sdc.be.components.impl.artifact.PayloadTypeEnum;
61 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
62 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
63 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
64 import org.openecomp.sdc.be.components.impl.utils.ComponentUtils;
65 import org.openecomp.sdc.be.components.impl.validation.PMDictionaryValidator;
66 import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
67 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
68 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction.LifecycleChanceActionEnum;
69 import org.openecomp.sdc.be.components.utils.ArtifactUtils;
70 import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
71 import org.openecomp.sdc.be.config.ArtifactConfiguration;
72 import org.openecomp.sdc.be.config.BeEcompErrorManager;
73 import org.openecomp.sdc.be.config.Configuration;
74 import org.openecomp.sdc.be.config.Configuration.ArtifactTypeConfig;
75 import org.openecomp.sdc.be.config.ConfigurationManager;
76 import org.openecomp.sdc.be.dao.api.ActionStatus;
77 import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
78 import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
79 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
80 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
81 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
82 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
83 import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition;
84 import org.openecomp.sdc.be.datatypes.elements.HeatParameterDataDefinition;
85 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
86 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
87 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
88 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
89 import org.openecomp.sdc.be.info.ArtifactTemplateInfo;
90 import org.openecomp.sdc.be.model.ArtifactDefinition;
91 import org.openecomp.sdc.be.model.ArtifactTypeDefinition;
92 import org.openecomp.sdc.be.model.Component;
93 import org.openecomp.sdc.be.model.ComponentInstance;
94 import org.openecomp.sdc.be.model.ComponentParametersView;
95 import org.openecomp.sdc.be.model.GroupDefinition;
96 import org.openecomp.sdc.be.model.GroupInstance;
97 import org.openecomp.sdc.be.model.HeatParameterDefinition;
98 import org.openecomp.sdc.be.model.InterfaceDefinition;
99 import org.openecomp.sdc.be.model.LifeCycleTransitionEnum;
100 import org.openecomp.sdc.be.model.LifecycleStateEnum;
101 import org.openecomp.sdc.be.model.Operation;
102 import org.openecomp.sdc.be.model.Resource;
103 import org.openecomp.sdc.be.model.Service;
104 import org.openecomp.sdc.be.model.User;
105 import org.openecomp.sdc.be.model.heat.HeatParameterType;
106 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
107 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
108 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeTemplateOperation;
109 import org.openecomp.sdc.be.model.operations.StorageException;
110 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
111 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
112 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
113 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
114 import org.openecomp.sdc.be.model.operations.api.IHeatParametersOperation;
115 import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation;
116 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
117 import org.openecomp.sdc.be.model.operations.impl.ArtifactTypeOperation;
118 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
119 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
120 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
121 import org.openecomp.sdc.be.model.operations.impl.UserAdminOperation;
122 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
123 import org.openecomp.sdc.be.resources.data.DAOArtifactData;
124 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
125 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo;
126 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo;
127 import org.openecomp.sdc.be.servlets.RepresentationUtils;
128 import org.openecomp.sdc.be.tosca.CsarUtils;
129 import org.openecomp.sdc.be.tosca.ToscaExportHandler;
130 import org.openecomp.sdc.be.user.Role;
131 import org.openecomp.sdc.be.user.UserBusinessLogic;
132 import org.openecomp.sdc.be.utils.TypeUtils;
133 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
134 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
135 import org.openecomp.sdc.common.api.Constants;
136 import org.openecomp.sdc.common.datastructure.Wrapper;
137 import org.openecomp.sdc.common.log.wrappers.Logger;
138 import org.openecomp.sdc.common.util.GeneralUtility;
139 import org.openecomp.sdc.common.util.ValidationUtils;
140 import org.openecomp.sdc.common.util.YamlToObjectConverter;
141 import org.openecomp.sdc.exception.ResponseFormat;
142 import org.springframework.beans.factory.annotation.Autowired;
143 import org.yaml.snakeyaml.Yaml;
144
145 @org.springframework.stereotype.Component("artifactBusinessLogic")
146 public class ArtifactsBusinessLogic extends BaseBusinessLogic {
147
148     public static final String HEAT_ENV_NAME = "heatEnv";
149     public static final String HEAT_VF_ENV_NAME = "VfHeatEnv";
150     public static final String HEAT_ENV_SUFFIX = "env";
151     public static final String ARTIFACT_ACTION_LOCK = "Artifact action - lock ";
152     public static final String FAILED_UPLOAD_ARTIFACT_TO_COMPONENT = "Failed to upload artifact to component with type {} and uuid {}. Status is {}. ";
153     public static final String COMPONENT_INSTANCE_NOT_FOUND = "Component instance {} was not found for component {}";
154     private static final String RESOURCE_INSTANCE = "resource instance";
155     private static final String ARTIFACT_TYPE_OTHER = "OTHER";
156     private static final String ARTIFACT_DESCRIPTION = "artifact description";
157     private static final String ARTIFACT_LABEL = "artifact label";
158     private static final String ARTIFACT_URL = "artifact url";
159     private static final String ARTIFACT_NAME = "artifact name";
160     private static final String ARTIFACT_PAYLOAD = "artifact payload";
161     private static final String ARTIFACT_PLACEHOLDER_TYPE = "type";
162     private static final String ARTIFACT_PLACEHOLDER_DISPLAY_NAME = "displayName";
163     private static final Object ARTIFACT_PLACEHOLDER_DESCRIPTION = "description";
164     private static final String ARTIFACT_PLACEHOLDER_FILE_EXTENSION = "fileExtension";
165     private static final Logger log = Logger.getLogger(ArtifactsBusinessLogic.class.getName());
166     private static final String FAILED_UPDATE_GROUPS = "Failed to update groups of the component {}. ";
167     private static final String FAILED_SAVE_ARTIFACT = "Failed to save the artifact.";
168     private static final String FAILED_FETCH_COMPONENT = "Could not fetch component with type {} and uuid {}. Status is {}. ";
169     private static final String NULL_PARAMETER = "One of the function parameteres is null";
170     private static final String ROLLBACK = "all changes rollback";
171     private static final String COMMIT = "all changes committed";
172     private static final String UPDATE_ARTIFACT = "Update Artifact";
173     private static final String FOUND_DEPLOYMENT_ARTIFACT = "Found deployment artifact {}";
174     private static final String VALID_ARTIFACT_LABEL_NAME = "'A-Z', 'a-z', '0-9', '-', '@', '+' and space.";
175     private Gson gson = new GsonBuilder().setPrettyPrinting().create();
176     @javax.annotation.Resource
177     private IInterfaceLifecycleOperation interfaceLifecycleOperation;
178     @javax.annotation.Resource
179     private UserAdminOperation userOperaton;
180     @javax.annotation.Resource
181     private IElementOperation elementOperation;
182     @javax.annotation.Resource
183     private IHeatParametersOperation heatParametersOperation;
184     private final ArtifactTypeOperation artifactTypeOperation;
185     private ArtifactCassandraDao artifactCassandraDao;
186     private ToscaExportHandler toscaExportUtils;
187     private CsarUtils csarUtils;
188     private LifecycleBusinessLogic lifecycleBusinessLogic;
189     private UserBusinessLogic userBusinessLogic;
190     private ArtifactsResolver artifactsResolver;
191     private NodeTemplateOperation nodeTemplateOperation;
192
193     @Autowired
194     public ArtifactsBusinessLogic(ArtifactCassandraDao artifactCassandraDao, ToscaExportHandler toscaExportUtils, CsarUtils csarUtils,
195                                   LifecycleBusinessLogic lifecycleBusinessLogic, UserBusinessLogic userBusinessLogic,
196                                   ArtifactsResolver artifactsResolver, IElementOperation elementDao, IGroupOperation groupOperation,
197                                   IGroupInstanceOperation groupInstanceOperation, IGroupTypeOperation groupTypeOperation,
198                                   InterfaceOperation interfaceOperation, InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
199                                   ArtifactsOperations artifactToscaOperation,
200                                   ArtifactTypeOperation artifactTypeOperation) {
201         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
202             artifactToscaOperation);
203         this.artifactCassandraDao = artifactCassandraDao;
204         this.toscaExportUtils = toscaExportUtils;
205         this.csarUtils = csarUtils;
206         this.lifecycleBusinessLogic = lifecycleBusinessLogic;
207         this.userBusinessLogic = userBusinessLogic;
208         this.artifactsResolver = artifactsResolver;
209         this.artifactTypeOperation = artifactTypeOperation;
210     }
211
212     public static <R> Either<Boolean, R> ifTrue(boolean predicate, Supplier<Either<Boolean, R>> ifTrue) {
213         return predicate ? ifTrue.get() : Either.left(false);
214     }
215
216     public static <L, R> Either<L, R> forEach(Either<L, R> e, Consumer<L> c) {
217         return e.left().map(l -> {
218             c.accept(l);
219             return l;
220         });
221     }
222
223     private static Option<ComponentInstance> findFirstMatching(Component component, Predicate<ComponentInstance> filter) {
224         return Option.ofOptional(component.getComponentInstances().stream().filter(filter).findFirst());
225     }
226
227     // new flow US556184
228     public Either<ArtifactDefinition, Operation> handleArtifactRequest(String componentId, String userId, ComponentTypeEnum componentType,
229                                                                        ArtifactOperationInfo operation, String artifactId,
230                                                                        ArtifactDefinition artifactInfo, String origMd5, String originData,
231                                                                        String interfaceName, String operationName, String parentId,
232                                                                        String containerComponentType, boolean shouldLock, boolean inTransaction) {
233         // step 1 - detect auditing type
234         AuditingActionEnum auditingAction = detectAuditingType(operation, origMd5);
235         // step 2 - check header
236         if (userId == null) {
237             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
238             log.debug("handleArtifactRequest - no HTTP_CSP_HEADER , component id {}", componentId);
239             handleAuditing(auditingAction, null, componentId, null, null, null, artifactId, responseFormat, componentType, null);
240             throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
241         }
242         // step 3 - check user existence
243
244         // step 4 - check user's role
245         User user = validateUserExists(userId, auditingAction, componentId, artifactId, componentType, inTransaction);
246         validateUserRole(user, auditingAction, componentId, artifactId, componentType, operation);
247         // steps 5 - 6 - 7
248
249         // 5. check service/resource existence
250
251         // 6. check service/resource check out
252
253         // 7. user is owner of checkout state
254         Component component = null;
255         String realComponentId = componentType == ComponentTypeEnum.RESOURCE_INSTANCE ? parentId : componentId;
256         component = validateComponentExists(realComponentId, auditingAction, user, artifactId, componentType, containerComponentType);
257         validateWorkOnComponent(component, userId, auditingAction, user, artifactId, operation);
258         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
259             validateResourceInstanceById(component, componentId);
260         }
261         // step 8
262         return validateAndHandleArtifact(componentId, componentType, operation, artifactId, artifactInfo, origMd5, originData, interfaceName,
263             operationName, user, component, shouldLock, inTransaction, true);
264     }
265
266     public Either<ArtifactDefinition, Operation> handleArtifactRequest(String componentId, String userId, ComponentTypeEnum componentType,
267                                                                        ArtifactOperationInfo operation, String artifactId,
268                                                                        ArtifactDefinition artifactInfo, String origMd5, String originData,
269                                                                        String interfaceName, String operationName, String parentId,
270                                                                        String containerComponentType) {
271         return handleArtifactRequest(componentId, userId, componentType, operation, artifactId, artifactInfo, origMd5, originData, interfaceName,
272             operationName, parentId, containerComponentType, true, false);
273     }
274
275     /**
276      * This Method validates only the Artifact and does not validate user / role / component ect...<br> For regular usage use <br> {@link
277      * #handleArtifactRequest(String, String, ComponentTypeEnum, ArtifactOperationInfo, String, ArtifactDefinition, String, String, String, String,
278      * String, String)}
279      *
280      * @return
281      */
282     public Either<ArtifactDefinition, Operation> validateAndHandleArtifact(String componentUniqueId, ComponentTypeEnum componentType,
283                                                                            ArtifactOperationInfo operation, String artifactUniqueId,
284                                                                            ArtifactDefinition artifactDefinition, String origMd5, String originData,
285                                                                            String interfaceName, String operationName, User user, Component component,
286                                                                            boolean shouldLock, boolean inTransaction, boolean needUpdateGroup) {
287         AuditingActionEnum auditingAction = detectAuditingType(operation, origMd5);
288         artifactDefinition = validateArtifact(componentUniqueId, componentType, operation, artifactUniqueId, artifactDefinition, auditingAction, user,
289             component, shouldLock, inTransaction);
290         // step 10
291         Either<ArtifactDefinition, Operation> result = doAction(componentUniqueId, componentType, operation, artifactUniqueId, artifactDefinition,
292             origMd5, originData, interfaceName, operationName, auditingAction, user, component, shouldLock, inTransaction, needUpdateGroup);
293         //TODO: audit positive action
294         return result;
295     }
296
297     @VisibleForTesting
298     ArtifactDefinition validateArtifact(String componentId, ComponentTypeEnum componentType, ArtifactOperationInfo operation, String artifactId,
299                                         ArtifactDefinition artifactInfo, AuditingActionEnum auditingAction, User user, Component component,
300                                         boolean shouldLock, boolean inTransaction) {
301         ArtifactDefinition artifactInfoToReturn = artifactInfo;
302         ArtifactOperationEnum operationEnum = operation.getArtifactOperationEnum();
303         if (operationEnum == ArtifactOperationEnum.UPDATE || operationEnum == ArtifactOperationEnum.DELETE
304             || operationEnum == ArtifactOperationEnum.DOWNLOAD) {
305             ArtifactDefinition dbArtifact = getArtifactIfBelongsToComponent(componentId, componentType, artifactId, component);
306             if (operation.isDownload()) {
307                 artifactInfoToReturn = dbArtifact;
308                 handleHeatEnvDownload(componentId, componentType, user, component, dbArtifact, shouldLock, inTransaction);
309             }
310         }
311         return artifactInfoToReturn;
312     }
313
314     @VisibleForTesting
315     void handleHeatEnvDownload(String componentId, ComponentTypeEnum componentType, User user, Component component,
316                                ArtifactDefinition artifactDefinition, boolean shouldLock, boolean inTransaction) {
317         if (artifactDefinition.getArtifactType().equalsIgnoreCase(ArtifactTypeEnum.HEAT_ENV.getType()) && ComponentTypeEnum.SERVICE == component
318             .getComponentType()) {
319             ComponentInstance componentInstance = component.getComponentInstances().stream().filter(p -> p.getUniqueId().equals(componentId))
320                 .findAny().orElse(null);
321             if (componentInstance == null) {
322                 throw new ByActionStatusComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, componentId, "instance", "Service",
323                     component.getName());
324             }
325             Map<String, ArtifactDefinition> deploymentArtifacts = componentInstance.getDeploymentArtifacts();
326             ArtifactDefinition heatEnvWithHeatParams = deploymentArtifacts.values().stream()
327                 .filter(p -> p.getUniqueId().equals(artifactDefinition.getUniqueId())).findAny().orElse(null);
328             Either<ArtifactDefinition, ResponseFormat> eitherGenerated = generateHeatEnvArtifact(heatEnvWithHeatParams, componentType, component,
329                 componentInstance.getName(), user, componentId, shouldLock, inTransaction);
330             if (eitherGenerated.isRight()) {
331                 throw new ByResponseFormatComponentException((eitherGenerated.right().value()));
332             }
333         }
334     }
335
336     private boolean artifactGenerationRequired(Component component, ArtifactDefinition artifactInfo) {
337         boolean needGenerate;
338         needGenerate = artifactInfo.getArtifactGroupType() == ArtifactGroupTypeEnum.TOSCA && (
339             component.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN
340                 || component.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
341         needGenerate = needGenerate || (ComponentTypeEnum.RESOURCE == component.getComponentType() && (
342             artifactInfo.getArtifactType().equalsIgnoreCase(ArtifactTypeEnum.HEAT_ENV.getType()) || isAbstractVfcEmptyCsar((Resource) component,
343                 artifactInfo)));
344         return needGenerate;
345     }
346
347     private boolean isAbstractVfcEmptyCsar(Resource resource, ArtifactDefinition artifactInfo) {
348         return resource.isAbstract() && artifactInfo.getArtifactGroupType() == ArtifactGroupTypeEnum.TOSCA && artifactInfo.getArtifactType()
349             .equals(ArtifactTypeEnum.TOSCA_CSAR.getType()) && StringUtils.isEmpty(artifactInfo.getArtifactChecksum());
350     }
351
352     public Either<ArtifactDefinition, Operation> generateAndSaveToscaArtifact(ArtifactDefinition artifactDefinition, Component component, User user,
353                                                                               boolean isInCertificationRequest, boolean shouldLock,
354                                                                               boolean inTransaction, boolean fetchTemplatesFromDB) {
355         return decodeToscaArtifactPayload(component, isInCertificationRequest, fetchTemplatesFromDB, artifactDefinition.getArtifactType()).left()
356             .bind(payload -> {
357                 // TODO: Avoid output argument
358                 artifactDefinition.setPayload(payload);
359                 artifactDefinition.setEsId(artifactDefinition.getUniqueId());
360                 artifactDefinition.setArtifactChecksum(GeneralUtility.calculateMD5Base64EncodedByByteArray(payload));
361                 return lockComponentAndUpdateArtifact(component.getUniqueId(), artifactDefinition, AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE,
362                     artifactDefinition.getUniqueId(), user, component.getComponentType(), component, payload, shouldLock, inTransaction);
363             }).right().map(ex -> {
364                 // TODO: This should not be done but in order to keep this refactoring small enough, we stop here.
365
366                 // Bubble up this exception
367                 throw ex;
368             });
369     }
370
371     private Either<byte[], ComponentException> decodeToscaArtifactPayload(Component parent, boolean isInCertificationRequest,
372                                                                           boolean fetchTemplatesFromDB, String artifactType) {
373         log.debug("tosca artifact generation");
374         if (ArtifactTypeEnum.TOSCA_CSAR.getType().equals(artifactType)) {
375             return csarUtils.createCsar(parent, fetchTemplatesFromDB, isInCertificationRequest).right().map(error -> {
376                 log.debug("Failed to generate tosca csar for component {} error {}", parent.getUniqueId(), error);
377                 return new ByResponseFormatComponentException(error);
378             });
379         } else {
380             return toscaExportUtils.exportComponent(parent).left().map(toscaRepresentation -> {
381                 log.debug("Tosca yaml exported for component {} ", parent.getUniqueId());
382                 return toscaRepresentation.getMainYaml();
383             }).right().map(toscaError -> {
384                 log.debug("Failed export tosca yaml for component {} error {}", parent.getUniqueId(), toscaError);
385                 return new ByActionStatusComponentException(componentsUtils.convertFromToscaError(toscaError));
386             });
387         }
388     }
389
390     private Either<ArtifactDefinition, Operation> doAction(String componentId, ComponentTypeEnum componentType, ArtifactOperationInfo operation,
391                                                            String artifactId, ArtifactDefinition artifactInfo, String origMd5, String originData,
392                                                            String interfaceName, String operationName, AuditingActionEnum auditingAction, User user,
393                                                            Component parent, boolean shouldLock, boolean inTransaction, boolean needUpdateGroup) {
394         if (interfaceName != null && operationName != null) {
395             interfaceName = interfaceName.toLowerCase();
396             operationName = operationName.toLowerCase();
397         }
398         if (shouldLock) {
399             lockComponent(componentType, artifactId, auditingAction, user, parent);
400         }
401         Either<ArtifactDefinition, Operation> result;
402         boolean operationSucceeded = false;
403         try {
404             switch (operation.getArtifactOperationEnum()) {
405                 case DOWNLOAD:
406                     if (artifactGenerationRequired(parent, artifactInfo)) {
407                         result = Either.left(generateNotSavedArtifact(parent, artifactInfo));
408                     } else {
409                         result = Either.left(handleDownload(componentId, artifactId, componentType, parent));
410                     }
411                     break;
412                 case DELETE:
413                     result = Either.left(handleDeleteInternal(componentId, artifactId, componentType, parent));
414                     break;
415                 case UPDATE:
416                     result = handleUpdate(componentId, componentType, operation, artifactId, artifactInfo, null, origMd5, originData, interfaceName,
417                         operationName, auditingAction, user, parent, needUpdateGroup);
418                     break;
419                 case CREATE:
420                     result = handleCreate(componentId, artifactInfo, operation, auditingAction, user, componentType, parent, origMd5, originData,
421                         interfaceName, operationName);
422                     break;
423                 case LINK:
424                     result = Either.left(handleLink(componentId, artifactInfo, componentType, parent));
425                     break;
426                 default:
427                     throw new UnsupportedOperationException(
428                         "In ArtifactsBusinessLogic received illegal operation: " + operation.getArtifactOperationEnum());
429             }
430             operationSucceeded = true;
431             return result;
432         } finally {
433             handleLockingAndCommit(parent, shouldLock, inTransaction, operationSucceeded);
434         }
435     }
436
437     private void lockComponent(ComponentTypeEnum componentType, String artifactId, AuditingActionEnum auditingAction, User user, Component parent) {
438         try {
439             lockComponent(parent, ARTIFACT_ACTION_LOCK);
440         } catch (ComponentException e) {
441             handleAuditing(auditingAction, parent, parent.getUniqueId(), user, null, null, artifactId, e.getResponseFormat(), componentType, null);
442             throw e;
443         }
444     }
445
446     @VisibleForTesting
447     public Either<ArtifactDefinition, Operation> handleUpdate(String componentId, ComponentTypeEnum componentType, ArtifactOperationInfo operation,
448                                                               String artifactId, ArtifactDefinition artifactInfo, byte[] decodedPayload,
449                                                               String origMd5, String originData, String interfaceName, String operationName,
450                                                               AuditingActionEnum auditingAction, User user, Component parent,
451                                                               boolean needUpdateGroup) {
452         Either<ArtifactDefinition, Operation> result;
453         validateArtifactType(artifactInfo);
454         final String artifactType = artifactInfo.getArtifactType();
455         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE && (ArtifactTypeEnum.HEAT.getType().equals(artifactType) || ArtifactTypeEnum.HEAT_VOL
456             .getType().equals(artifactType) || ArtifactTypeEnum.HEAT_NET.getType().equals(artifactType) || ArtifactTypeEnum.HEAT_ENV.getType()
457             .equals(artifactType))) {
458             result = handleUpdateHeatEnvAndHeatMeta(componentId, artifactInfo, auditingAction, artifactId, user, componentType, parent, originData,
459                 origMd5, operation);
460             if (needUpdateGroup) {
461                 ActionStatus error = updateGroupInstance(artifactInfo, result.left().value(), parent, componentId);
462                 if (error != ActionStatus.OK) {
463                     throw new ByActionStatusComponentException(error);
464                 }
465             }
466         } else if (componentType == ComponentTypeEnum.RESOURCE && ArtifactTypeEnum.HEAT_ENV.getType().equals(artifactType)) {
467             result = handleUpdateHeatWithHeatEnvParams(componentId, artifactInfo, auditingAction, componentType, parent, originData, origMd5,
468                 operation, needUpdateGroup);
469         } else {
470             if (decodedPayload == null) {
471                 decodedPayload = validateInput(componentId, artifactInfo, operation, auditingAction, artifactId, user, componentType, parent, origMd5,
472                     originData, interfaceName, operationName);
473             }
474             result = updateArtifactFlow(parent, componentId, artifactId, artifactInfo, decodedPayload, componentType, auditingAction);
475             if (needUpdateGroup && result.isLeft()) {
476                 ArtifactDefinition updatedArtifact = result.left().value();
477                 updateGroupForHeat(artifactInfo, updatedArtifact, parent);
478             }
479         }
480         return result;
481     }
482
483     private void validateArtifactType(final ArtifactDefinition artifactInfo) {
484         if (!isArtifactSupported(artifactInfo.getArtifactType())) {
485             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED, artifactInfo.getArtifactType());
486         }
487     }
488
489     private void validateArtifactType(final ArtifactDefinition artifactInfo, final ComponentTypeEnum componentType) {
490         final ArtifactConfiguration artifactConfiguration = loadArtifactTypeConfig(artifactInfo.getArtifactType()).orElse(null);
491         if (artifactConfiguration == null) {
492             BeEcompErrorManager.getInstance().logBeMissingArtifactInformationError("Artifact Update / Upload", "artifactLabel");
493             log.debug("Missing artifact type for artifact {}", artifactInfo.getArtifactName());
494             final ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_ARTIFACT_TYPE);
495             throw new ByResponseFormatComponentException(responseFormat);
496         }
497         final ArtifactGroupTypeEnum artifactGroupType = artifactInfo.getArtifactGroupType();
498         try {
499             validateArtifactType(componentType, artifactGroupType, artifactConfiguration);
500         } catch (final ComponentException e) {
501             log.debug("Artifact is invalid", e);
502             BeEcompErrorManager.getInstance()
503                 .logBeInvalidTypeError("Artifact Upload / Delete / Update - Not supported artifact type", artifactInfo.getArtifactType(),
504                     "Artifact " + artifactInfo.getArtifactName());
505             log.debug("Not supported artifact type = {}", artifactInfo.getArtifactType());
506             final ResponseFormat responseFormat = componentsUtils
507                 .getResponseFormat(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED, artifactInfo.getArtifactType());
508             throw new ByResponseFormatComponentException(responseFormat);
509         }
510     }
511
512     private void validateArtifactType(final ComponentTypeEnum componentType, final ArtifactGroupTypeEnum groupType,
513                                       final ArtifactConfiguration artifactConfiguration) {
514         final boolean supportComponentType =
515             CollectionUtils.isNotEmpty(artifactConfiguration.getComponentTypes()) && artifactConfiguration.getComponentTypes().stream()
516                 .anyMatch(componentType1 -> componentType1.getValue().equalsIgnoreCase(componentType.getValue()));
517         if (!supportComponentType) {
518             log.debug("Artifact Type '{}' not supported for Component Type '{}'", artifactConfiguration.getType(), componentType.getValue());
519             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED, artifactConfiguration.getType());
520         }
521         final boolean supportResourceType = artifactConfiguration.hasSupport(groupType);
522         if (!supportResourceType) {
523             log.debug("Artifact Type '{}' not supported for Component Type '{}' and Category '{}'", artifactConfiguration.getType(),
524                 componentType.getValue(), groupType.getType());
525             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED, artifactConfiguration.getType());
526         }
527     }
528
529     private boolean isArtifactSupported(final String artifactType) {
530         final Configuration configuration = ConfigurationManager.getConfigurationManager().getConfiguration();
531         final List<ArtifactConfiguration> artifactConfigurationList = configuration.getArtifacts();
532         if (CollectionUtils.isEmpty(artifactConfigurationList)) {
533             return false;
534         }
535         return artifactConfigurationList.stream().anyMatch(artifactConfiguration -> artifactConfiguration.getType().equalsIgnoreCase(artifactType));
536     }
537
538     @VisibleForTesting
539     public ActionStatus updateGroupForHeat(ArtifactDefinition artifactInfo, ArtifactDefinition artAfterUpdate, Component parent) {
540         List<GroupDefinition> groups = parent.getGroups();
541         if (groups != null && !groups.isEmpty()) {
542             List<GroupDataDefinition> groupToUpdate = groups.stream()
543                 .filter(g -> g.getArtifacts() != null && g.getArtifacts().contains(artifactInfo.getUniqueId())).collect(Collectors.toList());
544             if (groupToUpdate != null && !groupToUpdate.isEmpty()) {
545                 groupToUpdate.forEach(g -> {
546                     g.getArtifacts().remove(artifactInfo.getUniqueId());
547                     g.getArtifactsUuid().remove(artifactInfo.getArtifactUUID());
548                     g.getArtifacts().add(artAfterUpdate.getUniqueId());
549                     g.getArtifactsUuid().add(artAfterUpdate.getArtifactUUID());
550                     if (!artifactInfo.getArtifactUUID().equals(artAfterUpdate.getArtifactUUID())) {
551                         g.setGroupUUID(UniqueIdBuilder.generateUUID());
552                     }
553                 });
554                 Either<List<GroupDefinition>, StorageOperationStatus> status = toscaOperationFacade.updateGroupsOnComponent(parent, groupToUpdate);
555                 if (status.isRight()) {
556                     log.debug(FAILED_UPDATE_GROUPS, parent.getUniqueId());
557                     throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status.right().value()));
558                 }
559             }
560         }
561         return ActionStatus.OK;
562     }
563
564     @VisibleForTesting
565     ActionStatus updateGroupForHeat(ArtifactDefinition artifactInfoHeat, ArtifactDefinition artHeatAfterUpdate, ArtifactDefinition artifactInfoHeatE,
566                                     ArtifactDefinition artHEAfterUpdate, Component parent) {
567         List<GroupDefinition> groups = parent.getGroups();
568         if (groups != null && !groups.isEmpty()) {
569             List<GroupDataDefinition> groupToUpdate = groups.stream()
570                 .filter(g -> g.getArtifacts() != null && g.getArtifacts().contains(artifactInfoHeat.getUniqueId())).collect(Collectors.toList());
571             if (groupToUpdate != null && !groupToUpdate.isEmpty()) {
572                 groupToUpdate.forEach(g -> {
573                     g.getArtifacts().remove(artifactInfoHeat.getUniqueId());
574                     g.getArtifactsUuid().remove(artifactInfoHeat.getArtifactUUID());
575                     g.getArtifacts().remove(artifactInfoHeatE.getUniqueId());
576                     g.getArtifacts().add(artHeatAfterUpdate.getUniqueId());
577                     g.getArtifactsUuid().add(artHeatAfterUpdate.getArtifactUUID());
578                     g.getArtifacts().add(artHEAfterUpdate.getUniqueId());
579                 });
580                 Either<List<GroupDefinition>, StorageOperationStatus> status = toscaOperationFacade.updateGroupsOnComponent(parent, groupToUpdate);
581                 if (status.isRight()) {
582                     log.debug(FAILED_UPDATE_GROUPS, parent.getUniqueId());
583                     return componentsUtils.convertFromStorageResponse(status.right().value());
584                 }
585             }
586         }
587         return ActionStatus.OK;
588     }
589
590     private ActionStatus updateGroupInstance(ArtifactDefinition artifactInfo, ArtifactDefinition artAfterUpdate, Component parent, String parentId) {
591         List<GroupInstance> updatedGroupInstances = new ArrayList<>();
592         List<GroupInstance> groupInstances = null;
593         Optional<ComponentInstance> componentInstOp = parent.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(parentId))
594             .findFirst();
595         if (componentInstOp.isPresent()) {
596             groupInstances = componentInstOp.get().getGroupInstances();
597         }
598         if (CollectionUtils.isNotEmpty(groupInstances)) {
599             boolean isUpdated = false;
600             for (GroupInstance groupInstance : groupInstances) {
601                 isUpdated = false;
602                 if (CollectionUtils.isNotEmpty(groupInstance.getGroupInstanceArtifacts()) && groupInstance.getGroupInstanceArtifacts()
603                     .contains(artifactInfo.getUniqueId())) {
604                     groupInstance.getGroupInstanceArtifacts().remove(artifactInfo.getUniqueId());
605                     groupInstance.getGroupInstanceArtifacts().add(artAfterUpdate.getUniqueId());
606                     isUpdated = true;
607                 }
608                 if (CollectionUtils.isNotEmpty(groupInstance.getGroupInstanceArtifactsUuid()) && groupInstance.getGroupInstanceArtifactsUuid()
609                     .contains(artifactInfo.getArtifactUUID())) {
610                     groupInstance.getGroupInstanceArtifactsUuid().remove(artifactInfo.getArtifactUUID());
611                     groupInstance.getGroupInstanceArtifacts().add(artAfterUpdate.getArtifactUUID());
612                     isUpdated = true;
613                 }
614                 if (isUpdated) {
615                     updatedGroupInstances.add(groupInstance);
616                 }
617             }
618         }
619         Either<List<GroupInstance>, StorageOperationStatus> status = toscaOperationFacade
620             .updateGroupInstancesOnComponent(parent, parentId, updatedGroupInstances);
621         if (status.isRight()) {
622             log.debug(FAILED_UPDATE_GROUPS, parent.getUniqueId());
623             return componentsUtils.convertFromStorageResponse(status.right().value());
624         }
625         return ActionStatus.OK;
626     }
627
628     ArtifactDefinition generateNotSavedArtifact(Component parent, ArtifactDefinition artifactDefinition) {
629         if (artifactDefinition.getArtifactGroupType() == ArtifactGroupTypeEnum.TOSCA) {
630             Either<byte[], ComponentException> decodedPayload = decodeToscaArtifactPayload(parent, false, false,
631                 artifactDefinition.getArtifactType());
632             // TODO: This should not be done, but in order to keep this refactoring relatively small, we stop here
633             if (decodedPayload.isRight()) {
634                 throw decodedPayload.right().value();
635             } else {
636                 artifactDefinition.setPayload(decodedPayload.left().value());
637                 return artifactDefinition;
638             }
639         } else {
640             String heatArtifactId = artifactDefinition.getGeneratedFromId();
641             Either<ArtifactDefinition, StorageOperationStatus> heatRes = artifactToscaOperation.getArtifactById(parent.getUniqueId(), heatArtifactId);
642             if (heatRes.isRight()) {
643                 log.debug("Failed to fetch heat artifact by generated id {} for heat env {}", heatArtifactId, artifactDefinition.getUniqueId());
644                 throw new StorageException(heatRes.right().value());
645             }
646             String generatedPayload = generateHeatEnvPayload(heatRes.left().value());
647             artifactDefinition.setPayloadData(generatedPayload);
648             return artifactDefinition;
649         }
650     }
651
652     private Either<ArtifactDefinition, Operation> handleUpdateHeatWithHeatEnvParams(String componentId, ArtifactDefinition artifactInfo,
653                                                                                     AuditingActionEnum auditingAction,
654                                                                                     ComponentTypeEnum componentType, Component parent,
655                                                                                     String originData, String origMd5,
656                                                                                     ArtifactOperationInfo operation, boolean needToUpdateGroup) {
657         Either<ArtifactDefinition, StorageOperationStatus> artifactHeatRes = artifactToscaOperation
658             .getArtifactById(componentId, artifactInfo.getGeneratedFromId());
659         ArtifactDefinition currHeatArtifact = artifactHeatRes.left().value();
660         if (origMd5 != null) {
661             validateMd5(origMd5, originData, artifactInfo.getPayloadData(), operation);
662             if (ArrayUtils.isNotEmpty(artifactInfo.getPayloadData())) {
663                 handlePayload(artifactInfo, isArtifactMetadataUpdate(auditingAction));
664             } else { // duplicate
665                 throw new ByActionStatusComponentException(ActionStatus.MISSING_DATA, ARTIFACT_PAYLOAD);
666             }
667         }
668         return updateHeatParams(componentId, artifactInfo, auditingAction, parent, componentType, currHeatArtifact, needToUpdateGroup);
669     }
670
671     private void handleLockingAndCommit(Component parent, boolean shouldLock, boolean inTransaction, boolean actionSucceeded) {
672         if (actionSucceeded) {
673             log.debug(COMMIT);
674             if (!inTransaction) {
675                 janusGraphDao.commit();
676             }
677         } else {
678             log.debug(ROLLBACK);
679             if (!inTransaction) {
680                 janusGraphDao.rollback();
681             }
682         }
683         if (shouldLock) {
684             graphLockOperation.unlockComponent(parent.getUniqueId(), parent.getComponentType().getNodeType());
685         }
686     }
687
688     public ImmutablePair<String, byte[]> handleDownloadToscaModelRequest(Component component, ArtifactDefinition csarArtifact) {
689         if (artifactGenerationRequired(component, csarArtifact)) {
690             Either<byte[], ResponseFormat> generated = csarUtils.createCsar(component, false, false);
691             if (generated.isRight()) {
692                 log.debug("Failed to export tosca csar for component {} error {}", component.getUniqueId(), generated.right().value());
693                 throw new ByResponseFormatComponentException(generated.right().value());
694             }
695             return new ImmutablePair<>(csarArtifact.getArtifactName(), generated.left().value());
696         }
697         return downloadArtifact(csarArtifact);
698     }
699
700     public ImmutablePair<String, byte[]> handleDownloadRequestById(String componentId, String artifactId, String userId,
701                                                                    ComponentTypeEnum componentType, String parentId, String containerComponentType) {
702         // perform all validation in common flow
703         Either<ArtifactDefinition, Operation> result = handleArtifactRequest(componentId, userId, componentType,
704             new ArtifactOperationInfo(false, false, ArtifactOperationEnum.DOWNLOAD), artifactId, null, null, null, null, null, parentId,
705             containerComponentType);
706         ArtifactDefinition artifactDefinition;
707         Either<ArtifactDefinition, Operation> insideValue = result;
708         if (insideValue.isLeft()) {
709             artifactDefinition = insideValue.left().value();
710         } else {
711             artifactDefinition = insideValue.right().value().getImplementationArtifact();
712         }
713         // for tosca artifacts and heat env on VF level generated on download without saving
714         if (artifactDefinition.getPayloadData() != null) {
715             return (new ImmutablePair<>(artifactDefinition.getArtifactName(), artifactDefinition.getPayloadData()));
716         }
717         return downloadArtifact(artifactDefinition);
718     }
719
720     public Map<String, ArtifactDefinition> handleGetArtifactsByType(String containerComponentType, String parentId, ComponentTypeEnum componentType,
721                                                                     String componentId, String artifactGroupType, String userId) {
722         // step 1
723
724         // detect auditing type
725         Map<String, ArtifactDefinition> resMap = null;
726         new Wrapper<>();
727         // step 2
728
729         // check header
730         if (userId == null) {
731             log.debug("handleGetArtifactsByType - no HTTP_CSP_HEADER , component id {}", componentId);
732             throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
733         }
734         // step 3
735
736         // check user existence
737
738         // step 4
739
740         // check user's role
741         validateUserExists(userId);
742         // steps 5 - 6 - 7
743
744         // 5. check service/resource existence
745
746         // 6. check service/resource check out
747
748         // 7. user is owner of checkout state
749         String realComponentId = componentType == ComponentTypeEnum.RESOURCE_INSTANCE ? parentId : componentId;
750         ComponentParametersView componentFilter = new ComponentParametersView();
751         componentFilter.disableAll();
752         componentFilter.setIgnoreArtifacts(false);
753         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
754             componentFilter.setIgnoreComponentInstances(false);
755         }
756         Component component = validateComponentExistsByFilter(realComponentId, ComponentTypeEnum.findByParamName(containerComponentType),
757             componentFilter);
758         lockComponent(component, ARTIFACT_ACTION_LOCK);
759         boolean failed = false;
760         try {
761             ArtifactGroupTypeEnum groupType = ArtifactGroupTypeEnum.findType(artifactGroupType);
762             if (groupType == null) {
763                 log.debug("handleGetArtifactsByType - not failed groupType {} , component id {}", artifactGroupType, componentId);
764                 throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
765             }
766             if (parentId == null && groupType == ArtifactGroupTypeEnum.DEPLOYMENT) {
767                 List<ArtifactDefinition> list = getDeploymentArtifacts(component, componentId);
768                 if (list != null && !list.isEmpty()) {
769                     resMap = list.stream().collect(Collectors.toMap(ArtifactDataDefinition::getArtifactLabel, Function.identity()));
770                 } else {
771                     resMap = new HashMap<>();
772                 }
773                 return resMap;
774             } else {
775                 Either<Map<String, ArtifactDefinition>, StorageOperationStatus> artifactsMapStatus = getArtifacts(realComponentId,
776                     componentType.getNodeType(), groupType, componentId);
777                 if (artifactsMapStatus.isRight()) {
778                     if (artifactsMapStatus.right().value() != StorageOperationStatus.NOT_FOUND) {
779                         log.debug("handleGetArtifactsByType - not failed groupType {} , component id {}", artifactGroupType, componentId);
780                         throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
781                     } else {
782                         resMap = new HashMap<>();
783                     }
784                 } else {
785                     resMap = artifactsMapStatus.left().value();
786                 }
787                 return resMap;
788             }
789         } catch (ComponentException e) {
790             failed = true;
791             throw e;
792         } finally {
793             // unlock resource
794             if (failed) {
795                 log.debug(ROLLBACK);
796                 janusGraphDao.rollback();
797             } else {
798                 log.debug(COMMIT);
799                 janusGraphDao.commit();
800             }
801             componentType = component.getComponentType();
802             NodeTypeEnum nodeType = componentType.getNodeType();
803             graphLockOperation.unlockComponent(component.getUniqueId(), nodeType);
804         }
805     }
806
807     private ArtifactDefinition getArtifactIfBelongsToComponent(String componentId, ComponentTypeEnum componentType, String artifactId,
808                                                                Component component) {
809         // check artifact existence
810         Either<ArtifactDefinition, StorageOperationStatus> artifactResult = artifactToscaOperation
811             .getArtifactById(componentId, artifactId, componentType, component.getUniqueId());
812         if (artifactResult.isRight()) {
813             throw new ByActionStatusComponentException(ActionStatus.COMPONENT_ARTIFACT_NOT_FOUND, artifactId, componentId);
814         }
815         // verify artifact belongs to component
816         boolean found;
817         switch (componentType) {
818             case RESOURCE:
819             case SERVICE:
820                 found = ComponentUtils.checkArtifactInComponent(component, artifactId);
821                 break;
822             case RESOURCE_INSTANCE:
823                 found = ComponentUtils.checkArtifactInResourceInstance(component, componentId, artifactId);
824                 break;
825             default:
826                 found = false;
827         }
828         if (!found) {
829             throw new ByActionStatusComponentException(ActionStatus.COMPONENT_ARTIFACT_NOT_FOUND, artifactId, componentType.name().toLowerCase());
830         }
831         return artifactResult.left().value();
832     }
833
834     private Either<ArtifactDefinition, Operation> handleCreate(String componentId, ArtifactDefinition artifactInfo, ArtifactOperationInfo operation,
835                                                                AuditingActionEnum auditingAction, User user, ComponentTypeEnum componentType,
836                                                                Component parent, String origMd5, String originData, String interfaceType,
837                                                                String operationName) {
838         byte[] decodedPayload = validateInput(componentId, artifactInfo, operation, auditingAction, null, user, componentType, parent, origMd5,
839             originData, interfaceType, operationName);
840         return createArtifact(parent, componentId, artifactInfo, decodedPayload, componentType, auditingAction, interfaceType, operationName);
841     }
842
843     private ArtifactDefinition handleLink(String componentId, ArtifactDefinition artifactInfo, ComponentTypeEnum componentType, Component parent) {
844         ComponentInstance foundInstance = findComponentInstance(componentId, parent);
845         String instanceId = null;
846         if (foundInstance != null) {
847             instanceId = foundInstance.getUniqueId();
848         }
849         NodeTypeEnum nodeType = convertParentType(componentType);
850         Either<ArtifactDefinition, StorageOperationStatus> artifactDefinitionEither = artifactToscaOperation
851             .addArtifactToComponent(artifactInfo, parent, nodeType, true, instanceId);
852         if (artifactDefinitionEither.isRight()) {
853             throw new StorageException(artifactDefinitionEither.right().value(), artifactInfo.getArtifactDisplayName());
854         }
855         if (generateCustomizationUUIDOnInstance(parent.getUniqueId(), componentId, componentType) != StorageOperationStatus.OK) {
856             throw new StorageException(artifactDefinitionEither.right().value(), artifactInfo.getArtifactDisplayName());
857         }
858         return artifactDefinitionEither.left().value();
859     }
860
861     private <T> Either<ArtifactDefinition, T> lockComponentAndUpdateArtifact(String parentId, ArtifactDefinition artifactInfo,
862                                                                              AuditingActionEnum auditingAction, String artifactId, User user,
863                                                                              ComponentTypeEnum componentType, Component parent, byte[] decodedPayload,
864                                                                              boolean shouldLock, boolean inTransaction) {
865         boolean failed = false;
866         boolean writeAudit = true;
867         try {
868             lockComponent(parent, shouldLock, ARTIFACT_ACTION_LOCK);
869             writeAudit = false;
870             return updateArtifactFlow(parent, parentId, artifactId, artifactInfo, decodedPayload, componentType, auditingAction);
871         } catch (ComponentException ce) {
872             if (writeAudit) {
873                 handleAuditing(auditingAction, parent, parentId, user, null, null, artifactId, ce.getResponseFormat(), componentType, null);
874             }
875             failed = true;
876             throw ce;
877         } catch (StorageException se) {
878             //TODO: audit
879             failed = true;
880             throw se;
881         } finally {
882             if (shouldLock) {
883                 unlockComponent(failed, parent, inTransaction);
884             }
885         }
886     }
887
888     private byte[] validateInput(String componentId, ArtifactDefinition artifactInfo, ArtifactOperationInfo operation,
889                                  AuditingActionEnum auditingAction, String artifactId, User user, ComponentTypeEnum componentType, Component parent,
890                                  String origMd5, String originData, String interfaceType, String operationName) {
891         validateMd5(origMd5, originData, artifactInfo.getPayloadData(), operation);
892         return getValidPayload(componentId, artifactInfo, operation, auditingAction, artifactId, user, componentType, parent, interfaceType,
893             operationName);
894     }
895
896     private byte[] getValidPayload(String componentId, ArtifactDefinition artifactInfo, ArtifactOperationInfo operation,
897                                    AuditingActionEnum auditingAction, String artifactId, User user, ComponentTypeEnum componentType, Component parent,
898                                    String interfaceType, String operationName) {
899         // step 11
900         Either<ArtifactDefinition, ResponseFormat> validateResult = validateInput(componentId, artifactInfo, operation, artifactId, user,
901             interfaceType, operationName, componentType, parent);
902         if (validateResult.isRight()) {
903             ResponseFormat responseFormat = validateResult.right().value();
904             handleAuditing(auditingAction, parent, componentId, user, null, null, artifactId, responseFormat, componentType, null);
905             throw new ByResponseFormatComponentException(responseFormat);
906         }
907         Either<byte[], ResponseFormat> payloadEither = handlePayload(artifactInfo, isArtifactMetadataUpdate(auditingAction));
908         if (payloadEither.isRight()) {
909             ResponseFormat responseFormat = payloadEither.right().value();
910             handleAuditing(auditingAction, parent, componentId, user, null, null, artifactId, responseFormat, componentType, null);
911             log.debug("Error during handle payload");
912             throw new ByResponseFormatComponentException(responseFormat);
913         }
914         // validate heat parameters. this part must be after the parameters are
915
916         // extracted in "handlePayload"
917         Either<ArtifactDefinition, ResponseFormat> validateAndConvertHeatParameters = validateAndConvertHeatParameters(artifactInfo,
918             artifactInfo.getArtifactType());
919         if (validateAndConvertHeatParameters.isRight()) {
920             ResponseFormat responseFormat = validateAndConvertHeatParameters.right().value();
921             handleAuditing(auditingAction, parent, componentId, user, artifactInfo, null, artifactId, responseFormat, componentType, null);
922             log.debug("Error during handle payload");
923             throw new ByResponseFormatComponentException(responseFormat);
924         }
925         return payloadEither.left().value();
926     }
927
928     public void handleAuditing(AuditingActionEnum auditingActionEnum, Component component, String componentId, User user,
929                                ArtifactDefinition artifactDefinition, String prevArtifactUuid, String currentArtifactUuid,
930                                ResponseFormat responseFormat, ComponentTypeEnum componentTypeEnum, String resourceInstanceName) {
931         if (componentsUtils.isExternalApiEvent(auditingActionEnum)) {
932             return;
933         }
934         if (user == null) {
935             user = new User();
936             user.setUserId("UNKNOWN");
937         }
938         handleInternalAuditEvent(auditingActionEnum, component, componentId, user, artifactDefinition, prevArtifactUuid, currentArtifactUuid,
939             responseFormat, componentTypeEnum, resourceInstanceName);
940     }
941
942     private void handleInternalAuditEvent(AuditingActionEnum auditingActionEnum, Component component, String componentId, User user,
943                                           ArtifactDefinition artifactDefinition, String prevArtifactUuid, String currentArtifactUuid,
944                                           ResponseFormat responseFormat, ComponentTypeEnum componentTypeEnum, String resourceInstanceName) {
945         switch (componentTypeEnum) {
946             case RESOURCE:
947                 Resource resource = (Resource) component;
948                 if (resource == null) {
949                     // In that case, component ID should be instead of name
950                     resource = new Resource();
951                     resource.setName(componentId);
952                 }
953                 componentsUtils.auditResource(responseFormat, user, resource, resource.getName(), auditingActionEnum,
954                     ResourceVersionInfo.newBuilder().artifactUuid(prevArtifactUuid).build(), currentArtifactUuid, artifactDefinition);
955                 break;
956             case SERVICE:
957                 Service service = (Service) component;
958                 if (service == null) {
959                     // In that case, component ID should be instead of name
960                     service = new Service();
961                     service.setName(componentId);
962                 }
963                 componentsUtils
964                     .auditComponent(responseFormat, user, service, auditingActionEnum, new ResourceCommonInfo(ComponentTypeEnum.SERVICE.getValue()),
965                         ResourceVersionInfo.newBuilder().artifactUuid(prevArtifactUuid).build(),
966                         ResourceVersionInfo.newBuilder().artifactUuid(currentArtifactUuid).build(), null, artifactDefinition, null);
967                 break;
968             case RESOURCE_INSTANCE:
969                 if (resourceInstanceName == null) {
970                     resourceInstanceName = getResourceInstanceNameFromComponent(component, componentId);
971                 }
972                 componentsUtils.auditComponent(responseFormat, user, component, auditingActionEnum,
973                     new ResourceCommonInfo(resourceInstanceName, ComponentTypeEnum.RESOURCE_INSTANCE.getValue()),
974                     ResourceVersionInfo.newBuilder().artifactUuid(prevArtifactUuid).build(),
975                     ResourceVersionInfo.newBuilder().artifactUuid(currentArtifactUuid).build(), null, artifactDefinition, null);
976                 break;
977             default:
978                 break;
979         }
980     }
981
982     private String getResourceInstanceNameFromComponent(Component component, String componentId) {
983         ComponentInstance resourceInstance = component.getComponentInstances().stream().filter(p -> p.getUniqueId().equals(componentId)).findFirst()
984             .orElse(null);
985         String resourceInstanceName = null;
986         if (resourceInstance != null) {
987             resourceInstanceName = resourceInstance.getName();
988         }
989         return resourceInstanceName;
990     }
991
992     private void validateMd5(String origMd5, String originData, byte[] payload, ArtifactOperationInfo operation) {
993         if (origMd5 == null) {
994             if (operation.isCreateOrLink() && ArrayUtils.isNotEmpty(payload)) {
995                 log.debug("Missing md5 header during artifact create");
996                 throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_INVALID_MD5);
997             }
998             // Update metadata
999             if (ArrayUtils.isNotEmpty(payload)) {
1000                 log.debug("Cannot have payload while md5 header is missing");
1001                 throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
1002             }
1003         } else {
1004             String encodeBase64Str = GeneralUtility.calculateMD5Base64EncodedByString(originData);
1005             if (!encodeBase64Str.equals(origMd5)) {
1006                 log.debug("The calculated md5 is different then the received one");
1007                 throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_INVALID_MD5);
1008             }
1009         }
1010     }
1011
1012     private Either<ArtifactDefinition, ResponseFormat> validateInput(final String componentId, final ArtifactDefinition artifactInfo,
1013                                                                      final ArtifactOperationInfo operation, final String artifactId, final User user,
1014                                                                      String interfaceName, String operationName,
1015                                                                      final ComponentTypeEnum componentType, final Component parentComponent) {
1016         final ArtifactDefinition existingArtifactInfo = findArtifact(parentComponent, componentType, componentId, operation, artifactId);
1017         final boolean isCreateOrLinkOperation = ArtifactOperationEnum.isCreateOrLink(operation.getArtifactOperationEnum());
1018         if (!isCreateOrLinkOperation && existingArtifactInfo == null) {
1019             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactId);
1020         }
1021         final Component component;
1022         if (parentComponent.getUniqueId().equals(componentId)) {
1023             component = parentComponent;
1024         } else {
1025             final ComponentInstance componentInstance = findComponentInstance(componentId, parentComponent);
1026             component = findComponent(componentInstance.getComponentUid());
1027             component.setComponentType(componentType);
1028         }
1029         if (!isCreateOrLinkOperation) {
1030             ignoreUnupdateableFieldsInUpdate(operation, artifactInfo, existingArtifactInfo);
1031         }
1032         if (isInformationalArtifact(artifactInfo)) {
1033             validateInformationalArtifact(artifactInfo, component);
1034         }
1035         Either<Boolean, ResponseFormat> validateAndSetArtifactname = validateAndSetArtifactName(artifactInfo);
1036         if (validateAndSetArtifactname.isRight()) {
1037             return Either.right(validateAndSetArtifactname.right().value());
1038         }
1039         if (!validateArtifactNameUniqueness(componentId, parentComponent, artifactInfo, componentType)) {
1040             return Either.right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_EXIST));
1041         }
1042         if (operationName != null && interfaceName != null) {
1043             operationName = operationName.toLowerCase();
1044             interfaceName = interfaceName.toLowerCase();
1045         }
1046         Either<ActionStatus, ResponseFormat> logicalNameStatus = handleArtifactLabel(componentId, parentComponent, operation, artifactInfo,
1047             operationName, componentType);
1048         if (logicalNameStatus.isRight()) {
1049             return Either.right(logicalNameStatus.right().value());
1050         }
1051         // This is a patch to block possibility of updating service api fields
1052
1053         // through other artifacts flow
1054         final ArtifactGroupTypeEnum artifactGroupType =
1055             operationName != null ? ArtifactGroupTypeEnum.LIFE_CYCLE : ArtifactGroupTypeEnum.INFORMATIONAL;
1056         if (operation.isNotCreateOrLink()) {
1057             checkAndSetUnUpdatableFields(user, artifactInfo, existingArtifactInfo, artifactGroupType);
1058         } else {
1059             checkCreateFields(user, artifactInfo, artifactGroupType);
1060         }
1061         composeArtifactId(componentId, artifactId, artifactInfo, interfaceName, operationName);
1062         if (existingArtifactInfo != null) {
1063             artifactInfo.setMandatory(existingArtifactInfo.getMandatory());
1064             if (operation.isNotCreateOrLink()) {
1065                 validateArtifactTypeNotChanged(artifactInfo, existingArtifactInfo);
1066             }
1067         }
1068         // artifactGroupType is not allowed to be updated
1069         if (operation.isNotCreateOrLink()) {
1070             Either<ArtifactDefinition, ResponseFormat> validateGroupType = validateOrSetArtifactGroupType(artifactInfo, existingArtifactInfo);
1071             if (validateGroupType.isRight()) {
1072                 return Either.right(validateGroupType.right().value());
1073             }
1074         }
1075         setArtifactTimeout(artifactInfo, existingArtifactInfo);
1076         if (isHeatArtifact(artifactInfo)) {
1077             validateHeatArtifact(parentComponent, componentId, artifactInfo);
1078         }
1079         if (isDeploymentArtifact(artifactInfo)) {
1080             if (componentType != ComponentTypeEnum.RESOURCE_INSTANCE) {
1081                 final String artifactName = artifactInfo.getArtifactName();
1082                 final String existingArtifactName = (existingArtifactInfo == null) ? null : existingArtifactInfo.getArtifactName();
1083                 if (operation.isCreateOrLink() || ((artifactName != null) && !artifactName.equalsIgnoreCase(existingArtifactName))) {
1084                     validateSingleDeploymentArtifactName(artifactName, parentComponent);
1085                 }
1086             }
1087             validateDeploymentArtifact(artifactInfo, component);
1088         }
1089         Either<Boolean, ResponseFormat> descriptionResult = validateAndCleanDescription(artifactInfo);
1090         if (descriptionResult.isRight()) {
1091             return Either.right(descriptionResult.right().value());
1092         }
1093         validateArtifactType(artifactInfo, component.getComponentType());
1094         artifactInfo.setArtifactType(artifactInfo.getArtifactType().toUpperCase());
1095         if (existingArtifactInfo != null && existingArtifactInfo.getArtifactGroupType() == ArtifactGroupTypeEnum.SERVICE_API) {
1096             // Change of type is not allowed and should be ignored
1097             artifactInfo.setArtifactType(ARTIFACT_TYPE_OTHER);
1098             Either<Boolean, ResponseFormat> validateUrl = validateAndServiceApiUrl(artifactInfo);
1099             if (validateUrl.isRight()) {
1100                 return Either.right(validateUrl.right().value());
1101             }
1102             Either<Boolean, ResponseFormat> validateUpdate = validateFirstUpdateHasPayload(artifactInfo, existingArtifactInfo);
1103             if (validateUpdate.isRight()) {
1104                 log.debug("serviceApi first update cnnot be without payload.");
1105                 return Either.right(validateUpdate.right().value());
1106             }
1107         } else {
1108             if (artifactInfo.getApiUrl() != null) {
1109                 artifactInfo.setApiUrl(null);
1110                 log.error("Artifact URL cannot be set through this API - ignoring");
1111             }
1112             if (Boolean.TRUE.equals(artifactInfo.getServiceApi())) {
1113                 artifactInfo.setServiceApi(false);
1114                 log.error("Artifact service API flag cannot be changed - ignoring");
1115             }
1116         }
1117         return Either.left(artifactInfo);
1118     }
1119
1120     private Component findComponent(final String componentId) {
1121         Either<? extends Component, StorageOperationStatus> component = toscaOperationFacade.getToscaFullElement(componentId);
1122         if (component.isRight()) {
1123             log.debug("Component '{}' not found ", componentId);
1124             throw new ByActionStatusComponentException(ActionStatus.COMPONENT_NOT_FOUND, componentId);
1125         }
1126         return component.left().value();
1127     }
1128
1129     private void ignoreUnupdateableFieldsInUpdate(final ArtifactOperationInfo operation, final ArtifactDefinition artifactInfo,
1130                                                   final ArtifactDefinition currentArtifactInfo) {
1131         if (operation.isUpdate()) {
1132             artifactInfo.setArtifactType(currentArtifactInfo.getArtifactType());
1133             artifactInfo.setArtifactGroupType(currentArtifactInfo.getArtifactGroupType());
1134             artifactInfo.setArtifactLabel(currentArtifactInfo.getArtifactLabel());
1135         }
1136     }
1137
1138     private ArtifactDefinition findArtifact(final Component parentComponent, final ComponentTypeEnum componentType, final String parentId,
1139                                             final ArtifactOperationInfo operation, final String artifactId) {
1140         ArtifactDefinition foundArtifact = null;
1141         if (StringUtils.isNotEmpty(artifactId)) {
1142             foundArtifact = findArtifact(parentComponent, componentType, parentId, artifactId);
1143         }
1144         if (foundArtifact != null && operation.isCreateOrLink()) {
1145             log.debug("Artifact {} already exist", artifactId);
1146             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_EXIST, foundArtifact.getArtifactLabel());
1147         }
1148         if (foundArtifact == null && operation.isNotCreateOrLink()) {
1149             log.debug("The artifact {} was not found on parent component or instance {}. ", artifactId, parentId);
1150             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, "");
1151         }
1152         return foundArtifact;
1153     }
1154
1155     private ArtifactDefinition findArtifact(Component parentComponent, ComponentTypeEnum componentType, String parentId, String artifactId) {
1156         ArtifactDefinition foundArtifact;
1157         if (parentComponent.getUniqueId().equals(parentId)) {
1158             foundArtifact = artifactsResolver.findArtifactOnComponent(parentComponent, componentType, artifactId);
1159         } else {
1160             ComponentInstance instance = findComponentInstance(parentId, parentComponent);
1161             foundArtifact = artifactsResolver.findArtifactOnComponentInstance(instance, artifactId);
1162         }
1163         return foundArtifact;
1164     }
1165
1166     private void validateInformationalArtifact(final ArtifactDefinition artifactInfo, final Component component) {
1167         final ArtifactGroupTypeEnum groupType = artifactInfo.getArtifactGroupType();
1168         if (groupType != ArtifactGroupTypeEnum.INFORMATIONAL) {
1169             return;
1170         }
1171         final ComponentTypeEnum parentComponentType = component.getComponentType();
1172         final String artifactType = artifactInfo.getArtifactType();
1173         final ArtifactConfiguration artifactConfiguration = loadArtifactTypeConfig(artifactType).orElse(null);
1174         if (artifactConfiguration == null) {
1175             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED, artifactType);
1176         }
1177         validateArtifactType(parentComponentType, artifactInfo.getArtifactGroupType(), artifactConfiguration);
1178         if (component.getComponentType() == ComponentTypeEnum.RESOURCE || component.getComponentType() == ComponentTypeEnum.RESOURCE_INSTANCE) {
1179             final ResourceTypeEnum resourceType = ((Resource) component).getResourceType();
1180             validateResourceType(resourceType, artifactInfo, artifactConfiguration.getResourceTypes());
1181         }
1182         validateArtifactExtension(artifactConfiguration, artifactInfo);
1183     }
1184
1185     private NodeTypeEnum convertParentType(ComponentTypeEnum componentType) {
1186         if (componentType == ComponentTypeEnum.RESOURCE) {
1187             return NodeTypeEnum.Resource;
1188         } else if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1189             return NodeTypeEnum.ResourceInstance;
1190         } else {
1191             return NodeTypeEnum.Service;
1192         }
1193     }
1194
1195     // This method is here for backward compatibility - when other parts of the code are cleaned can change to use the internal version
1196     public Either<ArtifactDefinition, ResponseFormat> handleDelete(String parentId, String artifactId, User user, Component parent,
1197                                                                    boolean shouldLock, boolean inTransaction) {
1198         ResponseFormat responseFormat;
1199         boolean operationSucceeded = false;
1200         if (shouldLock) {
1201             lockComponent(ComponentTypeEnum.RESOURCE, artifactId, AuditingActionEnum.ARTIFACT_DELETE, user, parent);
1202         }
1203         try {
1204             ArtifactDefinition artifactDefinition = handleDeleteInternal(parentId, artifactId, ComponentTypeEnum.RESOURCE, parent);
1205             operationSucceeded = true;
1206             return Either.left(artifactDefinition);
1207         } catch (ComponentException ce) {
1208             responseFormat = componentsUtils.getResponseFormat(ce);
1209             handleAuditing(AuditingActionEnum.ARTIFACT_DELETE, parent, parentId, user, null, null, artifactId, responseFormat,
1210                 ComponentTypeEnum.RESOURCE, null);
1211             return Either.right(responseFormat);
1212         } catch (StorageException se) {
1213             responseFormat = componentsUtils.getResponseFormat(se);
1214             handleAuditing(AuditingActionEnum.ARTIFACT_DELETE, parent, parentId, user, null, null, artifactId, responseFormat,
1215                 ComponentTypeEnum.RESOURCE, null);
1216             return Either.right(responseFormat);
1217         } finally {
1218             handleLockingAndCommit(parent, shouldLock, inTransaction, operationSucceeded);
1219         }
1220     }
1221
1222     private ArtifactDefinition handleDeleteInternal(String parentId, String artifactId, ComponentTypeEnum componentType, Component parent) {
1223         NodeTypeEnum parentType = convertParentType(componentType);
1224         log.debug("Going to find the artifact {} on the component {}", artifactId, parent.getUniqueId());
1225         Either<ImmutablePair<ArtifactDefinition, ComponentInstance>, ActionStatus> getArtifactRes = findArtifact(artifactId, parent, parentId,
1226             componentType);
1227         if (getArtifactRes.isRight()) {
1228             log.debug("Failed to find the artifact {} belonging to {} on the component {}", artifactId, parentId, parent.getUniqueId());
1229             throw new ByActionStatusComponentException(getArtifactRes.right().value(), artifactId);
1230         }
1231         ArtifactDefinition foundArtifact = getArtifactRes.left().value().getLeft();
1232         ComponentInstance foundInstance = getArtifactRes.left().value().getRight();
1233         String esId = foundArtifact.getEsId();
1234         Either<Boolean, StorageOperationStatus> needClone = ifTrue(StringUtils.isNotEmpty(esId),
1235             () -> forEach(artifactToscaOperation.isCloneNeeded(parent.getUniqueId(), foundArtifact, parentType), b -> log
1236                 .debug("handleDelete: clone is needed for deleting {} held by {} in component {} {}? {}", foundArtifact.getArtifactName(), parentType,
1237                     parent.getUniqueId(), parent.getName(), b)));
1238         boolean needToClone = false;
1239         // TODO: This should not be done, but in order to keep this refactoring small, we stop here.
1240
1241         // Remove this block once the above refactoring is merged.
1242         if (needClone.isLeft()) {
1243             needToClone = needClone.left().value();
1244         } else {
1245             throw new StorageException(needClone.right().value(), foundArtifact.getArtifactDisplayName());
1246         }
1247         boolean isNeedToDeleteArtifactFromDB =
1248             componentType == ComponentTypeEnum.RESOURCE_INSTANCE && isArtifactOnlyResourceInstanceArtifact(foundArtifact, parent, parentId);
1249         boolean isDuplicated = false;
1250         ArtifactDataDefinition updatedArtifact = deleteOrUpdateArtifactOnGraph(parent, parentId, artifactId, parentType, foundArtifact, needToClone);
1251         isDuplicated = updatedArtifact.getDuplicated();
1252         if (!needToClone && !isDuplicated && isNeedToDeleteArtifactFromDB) {
1253             log.debug("Going to delete the artifact {} from the database. ", artifactId);
1254             CassandraOperationStatus cassandraStatus = artifactCassandraDao.deleteArtifact(esId);
1255             if (cassandraStatus != CassandraOperationStatus.OK) {
1256                 log.debug("Failed to delete the artifact {} from the database. ", artifactId);
1257                 throw new StorageException(convertToStorageOperationStatus(cassandraStatus), foundArtifact.getArtifactDisplayName());
1258             }
1259         }
1260         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1261             List<GroupInstance> updatedGroupInstances = getUpdatedGroupInstances(artifactId, foundArtifact, foundInstance.getGroupInstances());
1262             if (CollectionUtils.isNotEmpty(updatedGroupInstances)) {
1263                 Either<List<GroupInstance>, StorageOperationStatus> status = toscaOperationFacade
1264                     .updateGroupInstancesOnComponent(parent, parentId, updatedGroupInstances);
1265                 if (status.isRight()) {
1266                     log.debug(FAILED_UPDATE_GROUPS, parent.getUniqueId());
1267                     throw new StorageException(status.right().value(), foundArtifact.getArtifactDisplayName());
1268                 }
1269             }
1270             StorageOperationStatus status = generateCustomizationUUIDOnInstance(parent.getUniqueId(), parentId, componentType);
1271             if (status != StorageOperationStatus.OK) {
1272                 log.debug("Failed to generate new customization UUID for the component instance {}. ", parentId);
1273                 throw new StorageException(status, foundArtifact.getArtifactDisplayName());
1274             }
1275         } else {
1276             List<GroupDataDefinition> updatedGroups = getUpdatedGroups(artifactId, foundArtifact, parent.getGroups());
1277             if (CollectionUtils.isNotEmpty(updatedGroups)) {
1278                 Either<List<GroupDefinition>, StorageOperationStatus> status = toscaOperationFacade.updateGroupsOnComponent(parent, updatedGroups);
1279                 if (status.isRight()) {
1280                     log.debug(FAILED_UPDATE_GROUPS, parent.getUniqueId());
1281                     throw new StorageException(status.right().value(), foundArtifact.getArtifactDisplayName());
1282                 }
1283             }
1284         }
1285         return foundArtifact;
1286     }
1287
1288     private boolean isArtifactOnlyResourceInstanceArtifact(ArtifactDefinition foundArtifact, Component parent, String instanceId) {
1289         Optional<ComponentInstance> componentInstanceOpt = parent.getComponentInstanceById(instanceId);
1290         if (!componentInstanceOpt.isPresent()) {
1291             throw new ByActionStatusComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, instanceId, "", "", parent.getName());
1292         }
1293         ComponentInstance foundInstance = componentInstanceOpt.get();
1294         String componentUid = foundInstance.getComponentUid();
1295         Either<Component, StorageOperationStatus> getContainerRes = toscaOperationFacade.getToscaElement(componentUid);
1296         if (getContainerRes.isRight()) {
1297             log.debug("Failed to fetch the container component {}. ", componentUid);
1298             throw new StorageException(getContainerRes.right().value());
1299         }
1300         Component origComponent = getContainerRes.left().value();
1301         Map<String, ArtifactDefinition> deploymentArtifacts = origComponent.getDeploymentArtifacts();
1302         if (MapUtils.isNotEmpty(deploymentArtifacts)) {
1303             Optional<String> op = deploymentArtifacts.keySet().stream().filter(a -> a.equals(foundArtifact.getArtifactLabel())).findAny();
1304             if (op.isPresent()) {
1305                 return false;
1306             }
1307         }
1308         Map<String, ArtifactDefinition> artifacts = origComponent.getArtifacts();
1309         if (MapUtils.isNotEmpty(artifacts)) {
1310             Optional<String> op = artifacts.keySet().stream().filter(a -> a.equals(foundArtifact.getArtifactLabel())).findAny();
1311             if (op.isPresent()) {
1312                 return false;
1313             }
1314         }
1315         return true;
1316     }
1317
1318     private List<GroupDataDefinition> getUpdatedGroups(String artifactId, ArtifactDefinition foundArtifact, List<GroupDefinition> groups) {
1319         List<GroupDataDefinition> updatedGroups = new ArrayList<>();
1320         boolean isUpdated = false;
1321         if (groups != null) {
1322             for (GroupDefinition group : groups) {
1323                 isUpdated = false;
1324                 if (CollectionUtils.isNotEmpty(group.getArtifacts()) && group.getArtifacts().contains(artifactId)) {
1325                     group.getArtifacts().remove(artifactId);
1326                     isUpdated = true;
1327                 }
1328                 if (CollectionUtils.isNotEmpty(group.getArtifactsUuid()) && group.getArtifactsUuid().contains(foundArtifact.getArtifactUUID())) {
1329                     group.getArtifactsUuid().remove(foundArtifact.getArtifactUUID());
1330                     isUpdated = true;
1331                 }
1332                 if (isUpdated) {
1333                     updatedGroups.add(group);
1334                 }
1335             }
1336         }
1337         return updatedGroups;
1338     }
1339
1340     private List<GroupInstance> getUpdatedGroupInstances(String artifactId, ArtifactDefinition foundArtifact, List<GroupInstance> groupInstances) {
1341         if (CollectionUtils.isEmpty(groupInstances)) {
1342             return new ArrayList<>();
1343         }
1344         // TODO: A defensive copy should be created here for groupInstances. Modifying
1345
1346         // arguments (aka output arguments) is overall a bad practice as explained in
1347
1348         // Clean Code by Robert Martin.
1349
1350         // A better approach would be to use Lenses.
1351         return groupInstances.stream().filter(gi -> {
1352             boolean groupInstanceArtifactRemoved = gi.getGroupInstanceArtifacts() != null && gi.getGroupInstanceArtifacts().remove(artifactId);
1353             boolean groupInstanceArtifactUUIDRemoved =
1354                 gi.getGroupInstanceArtifactsUuid() != null && gi.getGroupInstanceArtifactsUuid().remove(foundArtifact.getArtifactUUID());
1355             return groupInstanceArtifactRemoved || groupInstanceArtifactUUIDRemoved;
1356         }).collect(Collectors.toList());
1357     }
1358
1359     private ArtifactDataDefinition deleteOrUpdateArtifactOnGraph(Component component, String parentId, String artifactId, NodeTypeEnum parentType,
1360                                                                  ArtifactDefinition foundArtifact, Boolean cloneIsNeeded) {
1361         Either<ArtifactDataDefinition, StorageOperationStatus> result;
1362         boolean isMandatory = foundArtifact.getMandatory() || foundArtifact.getServiceApi();
1363         String componentId = component.getUniqueId();
1364         String instanceId = componentId.equals(parentId) ? null : parentId;
1365         if (isMandatory) {
1366             log.debug("Going to update mandatory artifact {} from the component {}", artifactId, parentId);
1367             resetMandatoryArtifactFields(foundArtifact);
1368             result = artifactToscaOperation.updateArtifactOnGraph(component, foundArtifact, parentType, artifactId, instanceId, true, true);
1369         } else if (cloneIsNeeded) {
1370             log.debug("Going to clone artifacts and to delete the artifact {} from the component {}", artifactId, parentId);
1371             result = artifactToscaOperation.deleteArtifactWithCloningOnGraph(componentId, foundArtifact, parentType, instanceId, false);
1372         } else {
1373             log.debug("Going to delete the artifact {} from the component {}", artifactId, parentId);
1374             result = artifactToscaOperation.removeArtifactOnGraph(foundArtifact, componentId, instanceId, parentType, false);
1375         }
1376         if (result.isRight()) {
1377             throw new StorageException(result.right().value(), foundArtifact.getArtifactDisplayName());
1378         }
1379         return result.left().value();
1380     }
1381
1382     private Either<ImmutablePair<ArtifactDefinition, ComponentInstance>, ActionStatus> findArtifact(String artifactId,
1383                                                                                                     Component fetchedContainerComponent,
1384                                                                                                     String parentId,
1385                                                                                                     ComponentTypeEnum componentType) {
1386         Either<ImmutablePair<ArtifactDefinition, ComponentInstance>, ActionStatus> result = null;
1387         Map<String, ArtifactDefinition> artifacts = new HashMap<>();
1388         ComponentInstance foundInstance = null;
1389         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE && StringUtils.isNotEmpty(parentId)) {
1390             Optional<ComponentInstance> componentInstanceOpt = fetchedContainerComponent.getComponentInstances().stream()
1391                 .filter(i -> i.getUniqueId().equals(parentId)).findFirst();
1392             if (!componentInstanceOpt.isPresent()) {
1393                 result = Either.right(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER);
1394             } else {
1395                 foundInstance = componentInstanceOpt.get();
1396                 fetchArtifactsFromInstance(artifactId, artifacts, foundInstance);
1397             }
1398         } else {
1399             fetchArtifactsFromComponent(artifactId, fetchedContainerComponent, artifacts);
1400         }
1401         if (result == null) {
1402             if (artifacts.containsKey(artifactId)) {
1403                 result = Either.left(new ImmutablePair<>(artifacts.get(artifactId), foundInstance));
1404             } else {
1405                 result = Either.right(ActionStatus.ARTIFACT_NOT_FOUND);
1406             }
1407         }
1408         return result;
1409     }
1410
1411     private void fetchArtifactsFromComponent(String artifactId, Component component, Map<String, ArtifactDefinition> artifacts) {
1412         Map<String, ArtifactDefinition> currArtifacts;
1413         if (!artifacts.containsKey(artifactId) && MapUtils.isNotEmpty(component.getDeploymentArtifacts())) {
1414             currArtifacts = component.getDeploymentArtifacts().values().stream()
1415                 .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, i -> i));
1416             if (MapUtils.isNotEmpty(currArtifacts)) {
1417                 artifacts.putAll(currArtifacts);
1418             }
1419         }
1420         if (!artifacts.containsKey(artifactId) && MapUtils.isNotEmpty(component.getArtifacts())) {
1421             currArtifacts = component.getArtifacts().values().stream()
1422                 .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, Function.identity()));
1423             if (MapUtils.isNotEmpty(currArtifacts)) {
1424                 artifacts.putAll(currArtifacts);
1425             }
1426         }
1427         if (!artifacts.containsKey(artifactId) && MapUtils.isNotEmpty(component.getArtifacts())) {
1428             currArtifacts = component.getToscaArtifacts().values().stream()
1429                 .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, Function.identity()));
1430             if (MapUtils.isNotEmpty(currArtifacts)) {
1431                 artifacts.putAll(currArtifacts);
1432             }
1433         }
1434     }
1435
1436     private void fetchArtifactsFromInstance(String artifactId, Map<String, ArtifactDefinition> artifacts, ComponentInstance instance) {
1437         Map<String, ArtifactDefinition> currArtifacts;
1438         if (MapUtils.isNotEmpty(instance.getDeploymentArtifacts())) {
1439             currArtifacts = instance.getDeploymentArtifacts().values().stream()
1440                 .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, Function.identity()));
1441             if (MapUtils.isNotEmpty(currArtifacts)) {
1442                 artifacts.putAll(currArtifacts);
1443             }
1444         }
1445         if (!artifacts.containsKey(artifactId) && MapUtils.isNotEmpty(instance.getArtifacts())) {
1446             currArtifacts = instance.getArtifacts().values().stream()
1447                 .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, Function.identity()));
1448             if (MapUtils.isNotEmpty(currArtifacts)) {
1449                 artifacts.putAll(currArtifacts);
1450             }
1451         }
1452     }
1453
1454     private StorageOperationStatus convertToStorageOperationStatus(CassandraOperationStatus cassandraStatus) {
1455         StorageOperationStatus result;
1456         switch (cassandraStatus) {
1457             case OK:
1458                 result = StorageOperationStatus.OK;
1459                 break;
1460             case NOT_FOUND:
1461                 result = StorageOperationStatus.NOT_FOUND;
1462                 break;
1463             case CLUSTER_NOT_CONNECTED:
1464             case KEYSPACE_NOT_CONNECTED:
1465                 result = StorageOperationStatus.CONNECTION_FAILURE;
1466                 break;
1467             default:
1468                 result = StorageOperationStatus.GENERAL_ERROR;
1469                 break;
1470         }
1471         return result;
1472     }
1473
1474     private void resetMandatoryArtifactFields(ArtifactDefinition fetchedArtifact) {
1475         if (fetchedArtifact != null) {
1476             log.debug("Going to reset mandatory artifact {} fields. ", fetchedArtifact.getUniqueId());
1477             fetchedArtifact.setEsId(null);
1478             fetchedArtifact.setArtifactName(null);
1479             fetchedArtifact.setDescription(null);
1480             fetchedArtifact.setApiUrl(null);
1481             fetchedArtifact.setArtifactChecksum(null);
1482             nodeTemplateOperation.setDefaultArtifactTimeout(fetchedArtifact.getArtifactGroupType(), fetchedArtifact);
1483             fetchedArtifact.setArtifactUUID(null);
1484             long time = System.currentTimeMillis();
1485             fetchedArtifact.setPayloadUpdateDate(time);
1486             fetchedArtifact.setHeatParameters(null);
1487             fetchedArtifact.setHeatParamsUpdateDate(null);
1488         }
1489     }
1490
1491     private StorageOperationStatus generateCustomizationUUIDOnInstance(String componentId, String instanceId, ComponentTypeEnum componentType) {
1492         StorageOperationStatus error = StorageOperationStatus.OK;
1493         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1494             log.debug("Need to re-generate  customization UUID for instance {}", instanceId);
1495             error = toscaOperationFacade.generateCustomizationUUIDOnInstance(componentId, instanceId);
1496         }
1497         return error;
1498     }
1499
1500     private ArtifactDefinition handleDownload(String componentId, String artifactId, ComponentTypeEnum componentType, Component parent) {
1501         Either<ArtifactDefinition, StorageOperationStatus> artifactById = artifactToscaOperation
1502             .getArtifactById(componentId, artifactId, componentType, parent.getUniqueId());
1503         if (artifactById.isRight()) {
1504             throw new StorageException(artifactById.right().value());
1505         }
1506         ArtifactDefinition artifactDefinition = artifactById.left().value();
1507         if (artifactDefinition == null) {
1508             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactId);
1509         }
1510         return artifactDefinition;
1511     }
1512
1513     private Either<ActionStatus, ResponseFormat> handleArtifactLabel(String componentId, Component parentComponent, ArtifactOperationInfo operation,
1514                                                                      ArtifactDefinition artifactInfo, String operationName,
1515                                                                      ComponentTypeEnum componentType) {
1516         String artifactLabel = artifactInfo.getArtifactLabel();
1517         if (operationName == null && (artifactInfo.getArtifactLabel() == null || artifactInfo.getArtifactLabel().isEmpty())) {
1518             BeEcompErrorManager.getInstance().logBeMissingArtifactInformationError("Artifact Update / Upload", "artifactLabel");
1519             log.debug("missing artifact logical name for component {}", componentId);
1520             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_LABEL));
1521         }
1522         if (operation.isCreateOrLink() && !artifactInfo.getMandatory()) {
1523             if (operationName != null) {
1524                 if (artifactInfo.getArtifactLabel() != null && !operationName.equals(artifactInfo.getArtifactLabel())) {
1525                     log.debug("artifact label cannot be set {}", artifactLabel);
1526                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_LOGICAL_NAME_CANNOT_BE_CHANGED));
1527                 } else {
1528                     artifactLabel = operationName;
1529                 }
1530             }
1531             String displayName = artifactInfo.getArtifactDisplayName();
1532             if (displayName == null || displayName.isEmpty()) {
1533                 displayName = artifactLabel;
1534             }
1535             displayName = ValidationUtils.cleanArtifactDisplayName(displayName);
1536             artifactInfo.setArtifactDisplayName(displayName);
1537             if (!ValidationUtils.validateArtifactLabel(artifactLabel)) {
1538                 log.debug("Invalid format form Artifact label : {}", artifactLabel);
1539                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_ARTIFACT_LABEL_NAME, VALID_ARTIFACT_LABEL_NAME));
1540             }
1541             artifactLabel = ValidationUtils.normalizeArtifactLabel(artifactLabel);
1542             if (artifactLabel.isEmpty()) {
1543                 log.debug("missing normalized artifact logical name for component {}", componentId);
1544                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_LABEL));
1545             }
1546             if (!ValidationUtils.validateArtifactLabelLength(artifactLabel)) {
1547                 log.debug("Invalid lenght form Artifact label : {}", artifactLabel);
1548                 return Either.right(componentsUtils
1549                     .getResponseFormat(ActionStatus.EXCEEDS_LIMIT, ARTIFACT_LABEL, String.valueOf(ValidationUtils.ARTIFACT_LABEL_LENGTH)));
1550             }
1551             if (!validateLabelUniqueness(componentId, parentComponent, artifactLabel, componentType)) {
1552                 log.debug("Non unique Artifact label : {}", artifactLabel);
1553                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_EXIST, artifactLabel));
1554             }
1555         }
1556         artifactInfo.setArtifactLabel(artifactLabel);
1557         return Either.left(ActionStatus.OK);
1558     }
1559
1560     private boolean validateLabelUniqueness(String componentId, Component parentComponent, String artifactLabel, ComponentTypeEnum componentType) {
1561         boolean isUnique = true;
1562         Either<Map<String, ArtifactDefinition>, StorageOperationStatus> artifacts;
1563         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1564             artifacts = artifactToscaOperation.getAllInstanceArtifacts(parentComponent.getUniqueId(), componentId);
1565         } else {
1566             artifacts = artifactToscaOperation.getArtifacts(componentId);
1567         }
1568         if (artifacts.isLeft()) {
1569             for (String label : artifacts.left().value().keySet()) {
1570                 if (label.equals(artifactLabel)) {
1571                     isUnique = false;
1572                     break;
1573                 }
1574             }
1575         }
1576         if (componentType == ComponentTypeEnum.RESOURCE && isUnique) {
1577             isUnique = isUniqueLabelInResourceInterfaces(componentId, artifactLabel);
1578         }
1579         return isUnique;
1580     }
1581
1582     boolean validateArtifactNameUniqueness(String componentId, Component parentComponent, ArtifactDefinition artifactInfo,
1583                                            ComponentTypeEnum componentType) {
1584         Either<Map<String, ArtifactDefinition>, StorageOperationStatus> artifacts = getArtifacts(componentType, parentComponent, componentId,
1585             artifactInfo.getArtifactGroupType());
1586         String artifactName = artifactInfo.getArtifactName();
1587         if (artifacts.isLeft() && Objects.nonNull(artifacts.left().value())) {
1588             if (artifacts.left().value().values().stream().anyMatch(ad -> artifactName.equals(ad.getArtifactName())
1589                 //check whether it is the same artifact we hold (by label)
1590                 && !artifactInfo.getArtifactLabel().equals(ad.getArtifactLabel()))) {
1591                 return false;
1592             }
1593         }
1594         if (ComponentTypeEnum.RESOURCE == componentType) {
1595             return isUniqueArtifactNameInResourceInterfaces(componentId, artifactName, artifactInfo.getArtifactLabel());
1596         }
1597         return true;
1598     }
1599
1600     private boolean isUniqueArtifactNameInResourceInterfaces(String componentId, String artifactName, String artifactLabel) {
1601         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> allInterfacesOfResource = interfaceLifecycleOperation
1602             .getAllInterfacesOfResource(componentId, true, true);
1603         if (allInterfacesOfResource.isLeft()) {
1604             return allInterfacesOfResource.left().value().values().stream().map(InterfaceDefinition::getOperationsMap)
1605                 .flatMap(map -> map.values().stream()).map(OperationDataDefinition::getImplementation).filter(Objects::nonNull)
1606                 .noneMatch(add -> artifactName.equals(add.getArtifactName()) && !artifactLabel.equals(add.getArtifactLabel()));
1607         }
1608         return true;
1609     }
1610
1611     private boolean isUniqueLabelInResourceInterfaces(String componentId, String artifactLabel) {
1612         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> allInterfacesOfResource = interfaceLifecycleOperation
1613             .getAllInterfacesOfResource(componentId, true, true);
1614         if (allInterfacesOfResource.isLeft()) {
1615             return allInterfacesOfResource.left().value().values().stream().map(InterfaceDefinition::getOperationsMap)
1616                 .flatMap(map -> map.values().stream()).map(OperationDataDefinition::getImplementation).filter(Objects::nonNull)
1617                 .noneMatch(add -> artifactLabel.equals(add.getArtifactLabel()));
1618         }
1619         return true;
1620     }
1621
1622     private Either<Map<String, ArtifactDefinition>, StorageOperationStatus> getArtifacts(ComponentTypeEnum componentType, Component parentComponent,
1623                                                                                          String componentId,
1624                                                                                          ArtifactGroupTypeEnum artifactGroupType) {
1625         Either<Map<String, ArtifactDefinition>, StorageOperationStatus> artifactsResponse;
1626         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1627             artifactsResponse = artifactToscaOperation.getAllInstanceArtifacts(parentComponent.getUniqueId(), componentId);
1628         } else {
1629             artifactsResponse = artifactToscaOperation.getArtifacts(componentId);
1630         }
1631         if (artifactsResponse.isRight() && artifactsResponse.right().value() == StorageOperationStatus.NOT_FOUND) {
1632             log.debug("failed to retrieve artifacts for {} ", componentId);
1633             return Either.right(artifactsResponse.right().value());
1634         }
1635         return Either.left(artifactsResponse.left().value().entrySet().stream().filter(x -> artifactGroupType == x.getValue().getArtifactGroupType())
1636             .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
1637     }
1638
1639     // ***************************************************************
1640     private Either<ArtifactDefinition, Operation> createArtifact(Component parent, String parentId, ArtifactDefinition artifactInfo,
1641                                                                  byte[] decodedPayload, ComponentTypeEnum componentTypeEnum,
1642                                                                  AuditingActionEnum auditingActionEnum, String interfaceType, String operationName) {
1643         DAOArtifactData artifactData = createEsArtifactData(artifactInfo, decodedPayload);
1644         if (artifactData == null) {
1645             BeEcompErrorManager.getInstance().logBeDaoSystemError("Upload Artifact");
1646             log.debug("Failed to create artifact object for ES.");
1647             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
1648         }
1649         ComponentInstance foundInstance = findComponentInstance(parentId, parent);
1650         String instanceId = null;
1651         if (foundInstance != null) {
1652             if (foundInstance.isArtifactExists(artifactInfo.getArtifactGroupType(), artifactInfo.getArtifactLabel())) {
1653                 log.debug("Failed to create artifact, already exists");
1654                 throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_EXIST, artifactInfo.getArtifactLabel());
1655             }
1656             instanceId = foundInstance.getUniqueId();
1657         }
1658         // set on graph object id of artifact in ES!
1659         artifactInfo.setEsId(artifactData.getId());
1660         Either<ArtifactDefinition, Operation> operationResult;
1661         if (interfaceType != null && operationName != null) {
1662             // lifecycle artifact
1663             Operation operation = convertToOperation(artifactInfo, operationName);
1664             Either<Operation, StorageOperationStatus> result = interfaceLifecycleOperation
1665                 .updateInterfaceOperation(parentId, interfaceType, operationName, operation);
1666             if (result.isRight()) {
1667                 throw new StorageException(result.right().value());
1668             }
1669             operationResult = Either.right(result.left().value());
1670         } else {
1671             // information/deployment/api artifacts
1672             NodeTypeEnum nodeType = convertParentType(componentTypeEnum);
1673             Either<ArtifactDefinition, StorageOperationStatus> result = artifactToscaOperation
1674                 .addArtifactToComponent(artifactInfo, parent, nodeType, true, instanceId);
1675             if (result.isRight()) {
1676                 throw new StorageException(result.right().value());
1677             }
1678             ArtifactDefinition artifactDefinition = result.left().value();
1679             artifactData.setId(artifactDefinition.getEsId());
1680             operationResult = Either.left(artifactDefinition);
1681             if (generateCustomizationUUIDOnInstance(parent.getUniqueId(), parentId, componentTypeEnum) != StorageOperationStatus.OK) {
1682                 throw new StorageException(generateCustomizationUUIDOnInstance(parent.getUniqueId(), parentId, componentTypeEnum));
1683             }
1684         }
1685         saveArtifactInCassandra(artifactData, parent, artifactInfo, "", "", auditingActionEnum, componentTypeEnum);
1686         return operationResult;
1687     }
1688
1689     private ComponentInstance findComponentInstance(String componentInstanceId, Component containerComponent) {
1690         ComponentInstance foundInstance = null;
1691         if (CollectionUtils.isNotEmpty(containerComponent.getComponentInstances())) {
1692             foundInstance = containerComponent.getComponentInstances().stream().filter(i -> i.getUniqueId().equals(componentInstanceId)).findFirst()
1693                 .orElse(null);
1694         }
1695         return foundInstance;
1696     }
1697
1698     private void validateDeploymentArtifact(final ArtifactDefinition artifactInfo, final Component component) {
1699         final ComponentTypeEnum componentType = component.getComponentType();
1700         if (componentType != ComponentTypeEnum.RESOURCE && componentType != ComponentTypeEnum.SERVICE
1701             && componentType != ComponentTypeEnum.RESOURCE_INSTANCE) {
1702             log.debug("Invalid component type '{}' for artifact. " + "Expected Resource, Component or Resource Instance", componentType.getValue());
1703             throw new ByActionStatusComponentException(MISMATCH_BETWEEN_ARTIFACT_TYPE_AND_COMPONENT_TYPE, componentType.getValue(),
1704                 "Service, Resource or ResourceInstance", componentType.getValue());
1705         }
1706         final String artifactType = artifactInfo.getArtifactType();
1707         final ArtifactConfiguration artifactConfiguration = loadArtifactTypeConfig(artifactType).orElse(null);
1708         if (artifactConfiguration == null) {
1709             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED, artifactType);
1710         }
1711         validateArtifactType(componentType, artifactInfo.getArtifactGroupType(), artifactConfiguration);
1712         if (componentType == ComponentTypeEnum.RESOURCE || componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1713             final Resource resource = (Resource) component;
1714             final ResourceTypeEnum resourceType = resource.getResourceType();
1715             validateResourceType(resourceType, artifactInfo, artifactConfiguration.getResourceTypes());
1716         }
1717         validateArtifactExtension(artifactConfiguration, artifactInfo);
1718     }
1719
1720     private void validateHeatArtifact(final Component parentComponent, final String componentId, final ArtifactDefinition artifactDefinition) {
1721         final String artifactType = artifactDefinition.getArtifactType();
1722         final ArtifactTypeEnum artifactTypeEnum = ArtifactTypeEnum.parse(artifactType);
1723         if (artifactTypeEnum == null) {
1724             return;
1725         }
1726         switch (artifactTypeEnum) {
1727             case HEAT:
1728             case HEAT_VOL:
1729             case HEAT_NET:
1730                 validateHeatTimeoutValue(artifactDefinition);
1731                 break;
1732             case HEAT_ENV:
1733                 validateHeatEnvDeploymentArtifact(parentComponent, componentId, artifactDefinition);
1734                 break;
1735             default:
1736                 break;
1737         }
1738     }
1739
1740     private void setArtifactTimeout(final ArtifactDefinition newArtifactInfo, final ArtifactDefinition existingArtifactInfo) {
1741         final String artifactType = newArtifactInfo.getArtifactType();
1742         final ArtifactTypeEnum artifactTypeEnum = ArtifactTypeEnum.parse(artifactType);
1743         if (artifactTypeEnum == null) {
1744             newArtifactInfo.setTimeout(NodeTemplateOperation.NON_HEAT_TIMEOUT);
1745             return;
1746         }
1747         switch (artifactTypeEnum) {
1748             case HEAT:
1749             case HEAT_VOL:
1750             case HEAT_NET:
1751                 if (newArtifactInfo.getTimeout() == null) {
1752                     if (existingArtifactInfo == null) {
1753                         newArtifactInfo.setTimeout(NodeTemplateOperation.getDefaultHeatTimeout());
1754                     } else {
1755                         newArtifactInfo.setTimeout(existingArtifactInfo.getTimeout());
1756                     }
1757                 }
1758                 break;
1759             default:
1760                 newArtifactInfo.setTimeout(NodeTemplateOperation.NON_HEAT_TIMEOUT);
1761                 break;
1762         }
1763     }
1764
1765     @VisibleForTesting
1766     void validateDeploymentArtifactTypeIsLegalForParent(ArtifactDefinition artifactInfo, ArtifactTypeEnum artifactType,
1767                                                         Map<String, ArtifactTypeConfig> resourceDeploymentArtifacts) {
1768         if ((resourceDeploymentArtifacts == null) || !resourceDeploymentArtifacts.containsKey(artifactType.name())) {
1769             log.debug("Artifact Type: {} Not found !", artifactInfo.getArtifactType());
1770             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED, artifactInfo.getArtifactType());
1771         }
1772     }
1773
1774     Optional<ArtifactConfiguration> loadArtifactTypeConfig(final String artifactType) {
1775         if (artifactType == null) {
1776             return Optional.empty();
1777         }
1778         final List<ArtifactConfiguration> artifactConfigurationList = ConfigurationManager.getConfigurationManager().getConfiguration()
1779             .getArtifacts();
1780         if (CollectionUtils.isEmpty(artifactConfigurationList)) {
1781             return Optional.empty();
1782         }
1783         return artifactConfigurationList.stream().filter(artifactConfiguration -> artifactConfiguration.getType().equalsIgnoreCase(artifactType))
1784             .findFirst();
1785     }
1786
1787     private Either<Boolean, ResponseFormat> extractHeatParameters(ArtifactDefinition artifactInfo) {
1788         // extract heat parameters
1789         if (artifactInfo.getPayloadData() != null) {
1790             String heatDecodedPayload = new String(Base64.decodeBase64(artifactInfo.getPayloadData()));
1791             Either<List<HeatParameterDefinition>, ResultStatusEnum> heatParameters = ImportUtils
1792                 .getHeatParamsWithoutImplicitTypes(heatDecodedPayload, artifactInfo.getArtifactType());
1793             if (heatParameters.isRight() && (heatParameters.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND)) {
1794                 log.info("failed to parse heat parameters ");
1795                 ResponseFormat responseFormat = componentsUtils
1796                     .getResponseFormat(ActionStatus.INVALID_DEPLOYMENT_ARTIFACT_HEAT, artifactInfo.getArtifactType());
1797                 return Either.right(responseFormat);
1798             } else if (heatParameters.isLeft() && heatParameters.left().value() != null) {
1799                 artifactInfo.setListHeatParameters(heatParameters.left().value());
1800             }
1801         }
1802         return Either.left(true);
1803     }
1804
1805     @VisibleForTesting
1806     void validateArtifactExtension(final ArtifactConfiguration artifactConfiguration, final ArtifactDefinition artifactDefinition) {
1807         final List<String> acceptedTypes = artifactConfiguration.getAcceptedTypes();
1808         /*
1809          * No need to check specific types. In case there are no acceptedTypes in configuration, then any type is accepted.
1810          */
1811         if (CollectionUtils.isEmpty(acceptedTypes)) {
1812             return;
1813         }
1814         final String artifactName = artifactDefinition.getArtifactName();
1815         final String fileExtension = FilenameUtils.getExtension(artifactName);
1816         if (fileExtension == null || !acceptedTypes.contains(fileExtension.toLowerCase())) {
1817             final String artifactType = artifactDefinition.getArtifactType();
1818             log.debug("File extension \"{}\" is not allowed for artifact type \"{}\"", fileExtension, artifactType);
1819             throw new ByActionStatusComponentException(ActionStatus.WRONG_ARTIFACT_FILE_EXTENSION, artifactType);
1820         }
1821     }
1822
1823     @VisibleForTesting
1824     void validateHeatEnvDeploymentArtifact(final Component parentComponent, final String parentId, final ArtifactDefinition artifactInfo) {
1825         final Wrapper<ArtifactDefinition> heatMDWrapper = new Wrapper<>();
1826         final Wrapper<byte[]> payloadWrapper = new Wrapper<>();
1827         validateYaml(artifactInfo);
1828         validateHeatExist(parentComponent.getUniqueId(), parentId, heatMDWrapper, artifactInfo, parentComponent.getComponentType());
1829         if (!heatMDWrapper.isEmpty()) {
1830             fillArtifactPayload(payloadWrapper, heatMDWrapper.getInnerElement());
1831         }
1832         if (!heatMDWrapper.isEmpty()) {
1833             validateEnvVsHeat(artifactInfo, heatMDWrapper.getInnerElement(), payloadWrapper.getInnerElement());
1834         }
1835     }
1836
1837     public void fillArtifactPayload(Wrapper<byte[]> payloadWrapper, ArtifactDefinition artifactDefinition) {
1838         if (ArrayUtils.isEmpty(artifactDefinition.getPayloadData())) {
1839             Either<DAOArtifactData, CassandraOperationStatus> eitherArtifactData = artifactCassandraDao.getArtifact(artifactDefinition.getEsId());
1840             if (eitherArtifactData.isLeft()) {
1841                 byte[] data = eitherArtifactData.left().value().getDataAsArray();
1842                 payloadWrapper.setInnerElement(Base64.encodeBase64(data));
1843             } else {
1844                 log.debug("Error getting payload for artifact:{}", artifactDefinition.getArtifactName());
1845                 throw new StorageException(DaoStatusConverter.convertCassandraStatusToStorageStatus(eitherArtifactData.right().value()));
1846             }
1847         } else {
1848             payloadWrapper.setInnerElement(artifactDefinition.getPayloadData());
1849         }
1850     }
1851
1852     private void validateEnvVsHeat(ArtifactDefinition envArtifact, ArtifactDefinition heatArtifact, byte[] heatPayloadData) {
1853         String envPayload = new String(Base64.decodeBase64(envArtifact.getPayloadData()));
1854         Map<String, Object> heatEnvToscaJson = (Map<String, Object>) new Yaml().load(envPayload);
1855         String heatDecodedPayload = new String(Base64.decodeBase64(heatPayloadData));
1856         Map<String, Object> heatToscaJson = (Map<String, Object>) new Yaml().load(heatDecodedPayload);
1857         Either<Map<String, Object>, ResultStatusEnum> eitherHeatEnvProperties = ImportUtils
1858             .findFirstToscaMapElement(heatEnvToscaJson, TypeUtils.ToscaTagNamesEnum.PARAMETERS);
1859         if (eitherHeatEnvProperties.isRight()) {
1860             log.debug("Invalid heat env format for file:{}", envArtifact.getArtifactName());
1861             throw new ByActionStatusComponentException(ActionStatus.CORRUPTED_FORMAT, "Heat Env");
1862         }
1863         Either<Map<String, Object>, ResultStatusEnum> eitherHeatProperties = ImportUtils
1864             .findFirstToscaMapElement(heatToscaJson, TypeUtils.ToscaTagNamesEnum.PARAMETERS);
1865         if (eitherHeatProperties.isRight()) {
1866             log.debug("Invalid heat format for file:{}", heatArtifact.getArtifactName());
1867             throw new ByActionStatusComponentException(ActionStatus.CORRUPTED_FORMAT, "Heat");
1868         }
1869         Set<String> heatPropertiesKeys = eitherHeatProperties.left().value().keySet();
1870         Set<String> heatEnvPropertiesKeys = eitherHeatEnvProperties.left().value().keySet();
1871         heatEnvPropertiesKeys.removeAll(heatPropertiesKeys);
1872         if (!heatEnvPropertiesKeys.isEmpty()) {
1873             log.debug("Validation of heat_env for artifact:{} vs heat artifact for artifact :{} failed", envArtifact.getArtifactName(),
1874                 heatArtifact.getArtifactName());
1875             throw new ByActionStatusComponentException(ActionStatus.MISMATCH_HEAT_VS_HEAT_ENV, envArtifact.getArtifactName(),
1876                 heatArtifact.getArtifactName());
1877         }
1878     }
1879
1880     private void validateYaml(ArtifactDefinition artifactInfo) {
1881         YamlToObjectConverter yamlConverter = new YamlToObjectConverter();
1882         boolean isYamlValid = yamlConverter.isValidYamlEncoded64(artifactInfo.getPayloadData());
1883         if (!isYamlValid) {
1884             log.debug("Yaml is not valid for artifact : {}", artifactInfo.getArtifactName());
1885             throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML, artifactInfo.getArtifactType());
1886         }
1887     }
1888
1889     private void validateSingleDeploymentArtifactName(final String artifactName, final Component parentComponent) {
1890         boolean artifactNameFound = false;
1891         final Iterator<ArtifactDefinition> parentDeploymentArtifactsItr = getDeploymentArtifacts(parentComponent, null).iterator();
1892         while (!artifactNameFound && parentDeploymentArtifactsItr.hasNext()) {
1893             artifactNameFound = artifactName.equalsIgnoreCase(parentDeploymentArtifactsItr.next().getArtifactName());
1894         }
1895         if (artifactNameFound) {
1896             final ComponentTypeEnum componentType = parentComponent.getComponentType();
1897             log.debug("Can't upload artifact: {}, because another artifact with this name already exist.", artifactName);
1898             throw new ByActionStatusComponentException(ActionStatus.DEPLOYMENT_ARTIFACT_NAME_ALREADY_EXISTS, componentType.getValue(),
1899                 parentComponent.getName(), artifactName);
1900         }
1901     }
1902
1903     private void validateHeatExist(String componentId, String parentRiId, Wrapper<ArtifactDefinition> heatArtifactMDWrapper,
1904                                    ArtifactDefinition heatEnvArtifact, ComponentTypeEnum componentType) {
1905         final Either<ArtifactDefinition, StorageOperationStatus> res = artifactToscaOperation
1906             .getHeatArtifactByHeatEnvId(parentRiId, heatEnvArtifact, componentId, componentType);
1907         if (res.isRight()) {
1908             throw new ByActionStatusComponentException(ActionStatus.MISSING_HEAT);
1909         }
1910         heatArtifactMDWrapper.setInnerElement(res.left().value());
1911     }
1912
1913     @VisibleForTesting
1914     void validateHeatTimeoutValue(final ArtifactDefinition artifactInfo) {
1915         log.trace("Started HEAT pre-payload validation for artifact {}", artifactInfo.getArtifactLabel());
1916         // timeout > 0 for HEAT artifacts
1917         if (artifactInfo.getTimeout() == null || artifactInfo.getTimeout() < 1) {
1918             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_INVALID_TIMEOUT);
1919         }
1920         // US649856 - Allow several HEAT files on Resource
1921         log.trace("Ended HEAT validation for artifact {}", artifactInfo.getArtifactLabel());
1922     }
1923
1924     @VisibleForTesting
1925     void validateResourceType(final ResourceTypeEnum resourceType, final ArtifactDefinition artifactInfo, final List<String> typeList) {
1926         if (CollectionUtils.isEmpty(typeList) || typeList.contains(resourceType.getValue())) {
1927             return;
1928         }
1929         final String listToString = typeList.stream().collect(Collectors.joining(", "));
1930         throw new ByActionStatusComponentException(MISMATCH_BETWEEN_ARTIFACT_TYPE_AND_COMPONENT_TYPE, artifactInfo.getArtifactGroupType().getType(),
1931             listToString, resourceType.getValue());
1932     }
1933
1934     @VisibleForTesting
1935     Either<ArtifactDefinition, ResponseFormat> validateAndConvertHeatParameters(ArtifactDefinition artifactInfo, String artifactType) {
1936         if (artifactInfo.getHeatParameters() != null) {
1937             for (HeatParameterDefinition heatParam : artifactInfo.getListHeatParameters()) {
1938                 String parameterType = heatParam.getType();
1939                 HeatParameterType heatParameterType = HeatParameterType.isValidType(parameterType);
1940                 String artifactTypeStr = artifactType != null ? artifactType : ArtifactTypeEnum.HEAT.getType();
1941                 if (heatParameterType == null) {
1942                     ResponseFormat responseFormat = componentsUtils
1943                         .getResponseFormat(ActionStatus.INVALID_HEAT_PARAMETER_TYPE, artifactTypeStr, heatParam.getType());
1944                     return Either.right(responseFormat);
1945                 }
1946                 StorageOperationStatus validateAndUpdateProperty = heatParametersOperation.validateAndUpdateProperty(heatParam);
1947                 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
1948                     log.debug("Heat parameter {} is invalid. Status is {}", heatParam.getName(), validateAndUpdateProperty);
1949                     ActionStatus status = ActionStatus.INVALID_HEAT_PARAMETER_VALUE;
1950                     ResponseFormat responseFormat = componentsUtils
1951                         .getResponseFormat(status, artifactTypeStr, heatParam.getType(), heatParam.getName());
1952                     return Either.right(responseFormat);
1953                 }
1954             }
1955         }
1956         return Either.left(artifactInfo);
1957     }
1958
1959     public List<ArtifactDefinition> getDeploymentArtifacts(final Component component, final String ciId) {
1960         final ComponentTypeEnum componentType = component.getComponentType();
1961         if (component.getDeploymentArtifacts() == null) {
1962             return Collections.emptyList();
1963         }
1964         final List<ArtifactDefinition> deploymentArtifacts = new ArrayList<>();
1965         if (ComponentTypeEnum.RESOURCE == componentType && ciId != null) {
1966             final Either<ComponentInstance, ResponseFormat> getRI = getRIFromComponent(component, ciId, null, null, null);
1967             if (getRI.isRight()) {
1968                 return Collections.emptyList();
1969             }
1970             final ComponentInstance ri = getRI.left().value();
1971             if (ri.getDeploymentArtifacts() != null) {
1972                 deploymentArtifacts.addAll(ri.getDeploymentArtifacts().values());
1973             }
1974         } else {
1975             deploymentArtifacts.addAll(component.getDeploymentArtifacts().values());
1976         }
1977         return deploymentArtifacts;
1978     }
1979
1980     private void checkCreateFields(User user, ArtifactDefinition artifactInfo, ArtifactGroupTypeEnum type) {
1981         // on create if null add informational to current
1982         if (artifactInfo.getArtifactGroupType() == null) {
1983             artifactInfo.setArtifactGroupType(type);
1984         }
1985         if (artifactInfo.getUniqueId() != null) {
1986             log.error("artifact uniqid cannot be set ignoring");
1987         }
1988         artifactInfo.setUniqueId(null);
1989         if (artifactInfo.getArtifactRef() != null) {
1990             log.error("artifact ref cannot be set ignoring");
1991         }
1992         artifactInfo.setArtifactRef(null);
1993         if (artifactInfo.getArtifactRepository() != null) {
1994             log.error("artifact repository cannot be set ignoring");
1995         }
1996         artifactInfo.setArtifactRepository(null);
1997         if (artifactInfo.getUserIdCreator() != null) {
1998             log.error("creator uuid cannot be set ignoring");
1999         }
2000         artifactInfo.setArtifactCreator(user.getUserId());
2001         if (artifactInfo.getUserIdLastUpdater() != null) {
2002             log.error("userId of last updater cannot be set ignoring");
2003         }
2004         artifactInfo.setUserIdLastUpdater(user.getUserId());
2005         if (artifactInfo.getCreatorFullName() != null) {
2006             log.error("creator Full name cannot be set ignoring");
2007         }
2008         String fullName = user.getFirstName() + " " + user.getLastName();
2009         artifactInfo.setUpdaterFullName(fullName);
2010         if (artifactInfo.getUpdaterFullName() != null) {
2011             log.error("updater Full name cannot be set ignoring");
2012         }
2013         artifactInfo.setUpdaterFullName(fullName);
2014         if (artifactInfo.getCreationDate() != null) {
2015             log.error("Creation Date cannot be set ignoring");
2016         }
2017         long time = System.currentTimeMillis();
2018         artifactInfo.setCreationDate(time);
2019         if (artifactInfo.getLastUpdateDate() != null) {
2020             log.error("Last Update Date cannot be set ignoring");
2021         }
2022         artifactInfo.setLastUpdateDate(time);
2023         if (artifactInfo.getEsId() != null) {
2024             log.error("es id cannot be set ignoring");
2025         }
2026         artifactInfo.setEsId(null);
2027     }
2028
2029     private String composeArtifactId(String resourceId, String artifactId, ArtifactDefinition artifactInfo, String interfaceName,
2030                                      String operationName) {
2031         String id = artifactId;
2032         if (artifactId == null || artifactId.isEmpty()) {
2033             String uniqueId = null;
2034             if (interfaceName != null && operationName != null) {
2035                 uniqueId = UniqueIdBuilder
2036                     .buildArtifactByInterfaceUniqueId(resourceId, interfaceName, operationName, artifactInfo.getArtifactLabel());
2037             } else {
2038                 uniqueId = UniqueIdBuilder.buildPropertyUniqueId(resourceId, artifactInfo.getArtifactLabel());
2039             }
2040             artifactInfo.setUniqueId(uniqueId);
2041             artifactInfo.setEsId(uniqueId);
2042             id = uniqueId;
2043         } else {
2044             artifactInfo.setUniqueId(artifactId);
2045             artifactInfo.setEsId(artifactId);
2046         }
2047         return id;
2048     }
2049
2050     private Either<Boolean, ResponseFormat> validateFirstUpdateHasPayload(ArtifactDefinition artifactInfo, ArtifactDefinition currentArtifact) {
2051         if (currentArtifact.getEsId() == null && (artifactInfo.getPayloadData() == null || artifactInfo.getPayloadData().length == 0)) {
2052             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_PAYLOAD));
2053         }
2054         return Either.left(true);
2055     }
2056
2057     @VisibleForTesting
2058     Either<Boolean, ResponseFormat> validateAndSetArtifactName(ArtifactDefinition artifactInfo) {
2059         if (artifactInfo.getArtifactName() == null || artifactInfo.getArtifactName().isEmpty()) {
2060             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_ARTIFACT_NAME));
2061         }
2062         String normalizeFileName = ValidationUtils.normalizeFileName(artifactInfo.getArtifactName());
2063         if (normalizeFileName == null || normalizeFileName.isEmpty()) {
2064             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_ARTIFACT_NAME));
2065         }
2066         artifactInfo.setArtifactName(normalizeFileName);
2067         if (!ValidationUtils.validateArtifactNameLength(artifactInfo.getArtifactName())) {
2068             return Either.right(
2069                 componentsUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, ARTIFACT_NAME, String.valueOf(ValidationUtils.ARTIFACT_NAME_LENGTH)));
2070         }
2071         return Either.left(true);
2072     }
2073
2074     private void validateArtifactTypeNotChanged(ArtifactDefinition artifactInfo, ArtifactDefinition currentArtifact) {
2075         if (StringUtils.isEmpty(artifactInfo.getArtifactType())) {
2076             log.info("artifact type is missing operation ignored");
2077             throw new ByActionStatusComponentException(ActionStatus.MISSING_ARTIFACT_TYPE);
2078         }
2079         if (!currentArtifact.getArtifactType().equalsIgnoreCase(artifactInfo.getArtifactType())) {
2080             log.info("artifact type cannot be changed operation ignored");
2081             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
2082         }
2083     }
2084
2085     private Either<ArtifactDefinition, ResponseFormat> validateOrSetArtifactGroupType(ArtifactDefinition artifactInfo,
2086                                                                                       ArtifactDefinition currentArtifact) {
2087         if (Objects.nonNull(artifactInfo) && Objects.nonNull(currentArtifact)) {
2088             if (artifactInfo.getArtifactGroupType() == null) {
2089                 artifactInfo.setArtifactGroupType(currentArtifact.getArtifactGroupType());
2090             } else if (!currentArtifact.getArtifactGroupType().getType().equalsIgnoreCase(artifactInfo.getArtifactGroupType().getType())) {
2091                 log.info("artifact group type cannot be changed. operation failed");
2092                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
2093             }
2094         }
2095         return Either.left(artifactInfo);
2096     }
2097
2098     private void checkAndSetUnUpdatableFields(User user, ArtifactDefinition artifactInfo, ArtifactDefinition currentArtifact,
2099                                               ArtifactGroupTypeEnum type) {
2100         // on update if null add informational to current
2101         if (currentArtifact.getArtifactGroupType() == null && type != null) {
2102             currentArtifact.setArtifactGroupType(type);
2103         }
2104         if (artifactInfo.getUniqueId() != null && !currentArtifact.getUniqueId().equals(artifactInfo.getUniqueId())) {
2105             log.error("artifact uniqid cannot be set ignoring");
2106         }
2107         artifactInfo.setUniqueId(currentArtifact.getUniqueId());
2108         if (artifactInfo.getArtifactRef() != null && !currentArtifact.getArtifactRef().equals(artifactInfo.getArtifactRef())) {
2109             log.error("artifact ref cannot be set ignoring");
2110         }
2111         artifactInfo.setArtifactRef(currentArtifact.getArtifactRef());
2112         if (artifactInfo.getArtifactRepository() != null && !currentArtifact.getArtifactRepository().equals(artifactInfo.getArtifactRepository())) {
2113             log.error("artifact repository cannot be set ignoring");
2114         }
2115         artifactInfo.setArtifactRepository(currentArtifact.getArtifactRepository());
2116         if (artifactInfo.getUserIdCreator() != null && !currentArtifact.getUserIdCreator().equals(artifactInfo.getUserIdCreator())) {
2117             log.error("creator uuid cannot be set ignoring");
2118         }
2119         artifactInfo.setUserIdCreator(currentArtifact.getUserIdCreator());
2120         if (artifactInfo.getArtifactCreator() != null && !currentArtifact.getArtifactCreator().equals(artifactInfo.getArtifactCreator())) {
2121             log.error("artifact creator cannot be set ignoring");
2122         }
2123         artifactInfo.setArtifactCreator(currentArtifact.getArtifactCreator());
2124         if (artifactInfo.getUserIdLastUpdater() != null && !currentArtifact.getUserIdLastUpdater().equals(artifactInfo.getUserIdLastUpdater())) {
2125             log.error("userId of last updater cannot be set ignoring");
2126         }
2127         artifactInfo.setUserIdLastUpdater(user.getUserId());
2128         if (artifactInfo.getCreatorFullName() != null && !currentArtifact.getCreatorFullName().equals(artifactInfo.getCreatorFullName())) {
2129             log.error("creator Full name cannot be set ignoring");
2130         }
2131         artifactInfo.setCreatorFullName(currentArtifact.getCreatorFullName());
2132         if (artifactInfo.getUpdaterFullName() != null && !currentArtifact.getUpdaterFullName().equals(artifactInfo.getUpdaterFullName())) {
2133             log.error("updater Full name cannot be set ignoring");
2134         }
2135         String fullName = user.getFirstName() + " " + user.getLastName();
2136         artifactInfo.setUpdaterFullName(fullName);
2137         if (artifactInfo.getCreationDate() != null && !currentArtifact.getCreationDate().equals(artifactInfo.getCreationDate())) {
2138             log.error("Creation Date cannot be set ignoring");
2139         }
2140         artifactInfo.setCreationDate(currentArtifact.getCreationDate());
2141         if (artifactInfo.getLastUpdateDate() != null && !currentArtifact.getLastUpdateDate().equals(artifactInfo.getLastUpdateDate())) {
2142             log.error("Last Update Date cannot be set ignoring");
2143         }
2144         long time = System.currentTimeMillis();
2145         artifactInfo.setLastUpdateDate(time);
2146         if (artifactInfo.getEsId() != null && !currentArtifact.getEsId().equals(artifactInfo.getEsId())) {
2147             log.error("es id cannot be set ignoring");
2148         }
2149         artifactInfo.setEsId(currentArtifact.getUniqueId());
2150         if (artifactInfo.getArtifactDisplayName() != null && !currentArtifact.getArtifactDisplayName()
2151             .equals(artifactInfo.getArtifactDisplayName())) {
2152             log.error(" Artifact Display Name cannot be set ignoring");
2153         }
2154         artifactInfo.setArtifactDisplayName(currentArtifact.getArtifactDisplayName());
2155         if (artifactInfo.getServiceApi() != null && !currentArtifact.getServiceApi().equals(artifactInfo.getServiceApi())) {
2156             log.debug("serviceApi cannot be set. ignoring.");
2157         }
2158         artifactInfo.setServiceApi(currentArtifact.getServiceApi());
2159         if (artifactInfo.getArtifactGroupType() != null && currentArtifact.getArtifactGroupType() != artifactInfo.getArtifactGroupType()) {
2160             log.debug("artifact group cannot be set. ignoring.");
2161         }
2162         artifactInfo.setArtifactGroupType(currentArtifact.getArtifactGroupType());
2163         artifactInfo.setArtifactVersion(currentArtifact.getArtifactVersion());
2164         if (artifactInfo.getArtifactUUID() != null && !artifactInfo.getArtifactUUID().isEmpty() && !currentArtifact.getArtifactUUID()
2165             .equals(artifactInfo.getArtifactUUID())) {
2166             log.debug("artifact UUID cannot be set. ignoring.");
2167         }
2168         artifactInfo.setArtifactUUID(currentArtifact.getArtifactUUID());
2169         if ((artifactInfo.getHeatParameters() != null) && (currentArtifact.getHeatParameters() != null) && !artifactInfo.getHeatParameters().isEmpty()
2170             && !currentArtifact.getHeatParameters().isEmpty()) {
2171             checkAndSetUnupdatableHeatParams(artifactInfo.getListHeatParameters(), currentArtifact.getListHeatParameters());
2172         }
2173     }
2174
2175     private void checkAndSetUnupdatableHeatParams(List<HeatParameterDefinition> heatParameters, List<HeatParameterDefinition> currentParameters) {
2176         Map<String, HeatParameterDefinition> currentParametersMap = getMapOfParameters(currentParameters);
2177         for (HeatParameterDefinition parameter : heatParameters) {
2178             HeatParameterDefinition currentParam = currentParametersMap.get(parameter.getUniqueId());
2179             if (currentParam != null) {
2180                 if (parameter.getName() != null && !parameter.getName().equalsIgnoreCase(currentParam.getName())) {
2181                     log.debug("heat parameter name cannot be updated  ({}). ignoring.", parameter.getName());
2182                     parameter.setName(currentParam.getName());
2183                 }
2184                 if (parameter.getDefaultValue() != null && !parameter.getDefaultValue().equalsIgnoreCase(currentParam.getDefaultValue())) {
2185                     log.debug("heat parameter defaultValue cannot be updated  ({}). ignoring.", parameter.getDefaultValue());
2186                     parameter.setDefaultValue(currentParam.getDefaultValue());
2187                 }
2188                 if (parameter.getType() != null && !parameter.getType().equalsIgnoreCase(currentParam.getType())) {
2189                     log.debug("heat parameter type cannot be updated  ({}). ignoring.", parameter.getType());
2190                     parameter.setType(currentParam.getType());
2191                 }
2192                 if (parameter.getDescription() != null && !parameter.getDescription().equalsIgnoreCase(currentParam.getDescription())) {
2193                     log.debug("heat parameter description cannot be updated  ({}). ignoring.", parameter.getDescription());
2194                     parameter.setDescription(currentParam.getDescription());
2195                 }
2196                 // check and set current value
2197                 if ((parameter.getCurrentValue() == null) && (currentParam.getDefaultValue() != null)) {
2198                     log.debug("heat parameter current value is null. set it to default value {}). ignoring.", parameter.getDefaultValue());
2199                     parameter.setCurrentValue(currentParam.getDefaultValue());
2200                 }
2201             }
2202         }
2203     }
2204
2205     private Map<String, HeatParameterDefinition> getMapOfParameters(List<HeatParameterDefinition> currentParameters) {
2206         Map<String, HeatParameterDefinition> currentParamsMap = new HashMap<>();
2207         for (HeatParameterDefinition param : currentParameters) {
2208             currentParamsMap.put(param.getUniqueId(), param);
2209         }
2210         return currentParamsMap;
2211     }
2212
2213     private Either<Boolean, ResponseFormat> validateAndServiceApiUrl(ArtifactDefinition artifactInfo) {
2214         if (!ValidationUtils.validateStringNotEmpty(artifactInfo.getApiUrl())) {
2215             log.debug("Artifact url cannot be empty.");
2216             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_URL));
2217         }
2218         artifactInfo.setApiUrl(artifactInfo.getApiUrl().toLowerCase());
2219         if (!ValidationUtils.validateUrl(artifactInfo.getApiUrl())) {
2220             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_SERVICE_API_URL));
2221         }
2222         if (!ValidationUtils.validateUrlLength(artifactInfo.getApiUrl())) {
2223             return Either
2224                 .right(componentsUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, ARTIFACT_URL, String.valueOf(ValidationUtils.API_URL_LENGTH)));
2225         }
2226         return Either.left(true);
2227     }
2228
2229     private Either<Boolean, ResponseFormat> validateAndCleanDescription(ArtifactDefinition artifactInfo) {
2230         if (artifactInfo.getDescription() == null || artifactInfo.getDescription().isEmpty()) {
2231             log.debug("Artifact description cannot be empty.");
2232             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_DESCRIPTION));
2233         }
2234         String description = artifactInfo.getDescription();
2235         description = ValidationUtils.removeNoneUtf8Chars(description);
2236         description = ValidationUtils.normaliseWhitespace(description);
2237         description = ValidationUtils.stripOctets(description);
2238         description = ValidationUtils.removeHtmlTagsOnly(description);
2239         if (!ValidationUtils.validateIsEnglish(description)) {
2240             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
2241         }
2242         if (!ValidationUtils.validateLength(description, ValidationUtils.ARTIFACT_DESCRIPTION_MAX_LENGTH)) {
2243             return Either.right(componentsUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, ARTIFACT_DESCRIPTION,
2244                 String.valueOf(ValidationUtils.ARTIFACT_DESCRIPTION_MAX_LENGTH)));
2245         }
2246         artifactInfo.setDescription(description);
2247         return Either.left(true);
2248     }
2249
2250     private <T> Either<ArtifactDefinition, T> updateArtifactFlow(Component parent, String parentId, String artifactId,
2251                                                                  ArtifactDefinition artifactInfo, byte[] decodedPayload,
2252                                                                  ComponentTypeEnum componentType, AuditingActionEnum auditingAction) {
2253         DAOArtifactData artifactData = createEsArtifactData(artifactInfo, decodedPayload);
2254         if (artifactData == null) {
2255             BeEcompErrorManager.getInstance().logBeDaoSystemError(UPDATE_ARTIFACT);
2256             log.debug("Failed to create artifact object for ES.");
2257             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
2258         }
2259         log.debug("Entry on graph is updated. Update artifact in ES");
2260         // Changing previous and current artifactId for auditing
2261         String currArtifactId = artifactInfo.getUniqueId();
2262         NodeTypeEnum parentType = convertParentType(componentType);
2263         if (decodedPayload == null) {
2264             if (!artifactInfo.getMandatory() || artifactInfo.getEsId() != null) {
2265                 Either<DAOArtifactData, CassandraOperationStatus> artifactFromCassandra = artifactCassandraDao.getArtifact(artifactInfo.getEsId());
2266                 if (artifactFromCassandra.isRight()) {
2267                     throw new StorageException(artifactFromCassandra.right().value());
2268                 }
2269                 // clone data to new artifact
2270                 artifactData.setData(artifactFromCassandra.left().value().getData());
2271                 artifactData.setId(artifactFromCassandra.left().value().getId());
2272             }
2273         } else if (artifactInfo.getEsId() == null) {
2274             artifactInfo.setEsId(artifactInfo.getUniqueId());
2275             artifactData.setId(artifactInfo.getUniqueId());
2276         }
2277         Either<ArtifactDefinition, StorageOperationStatus> result = artifactToscaOperation
2278             .updateArtifactOnResource(artifactInfo, parent, artifactId, parentType, parentId, true);
2279         if (result.isRight()) {
2280             throw new StorageException(result.right().value());
2281         }
2282         ArtifactDefinition artifactDefinition = result.left().value();
2283         updateGeneratedIdInHeatEnv(parent, parentId, artifactId, artifactInfo, artifactDefinition, parentType);
2284         StorageOperationStatus storageOperationStatus = generateCustomizationUUIDOnInstance(parent.getUniqueId(), parentId, componentType);
2285         if (storageOperationStatus != StorageOperationStatus.OK) {
2286             throw new StorageException(storageOperationStatus);
2287         }
2288         if (artifactData.getData() != null) {
2289             if (!artifactDefinition.getDuplicated() || artifactData.getId() == null) {
2290                 artifactData.setId(artifactDefinition.getEsId());
2291             }
2292             saveArtifactInCassandra(artifactData, parent, artifactInfo, currArtifactId, artifactId, auditingAction, componentType);
2293         }
2294         return Either.left(artifactDefinition);
2295     }
2296
2297     private String updateGeneratedIdInHeatEnv(Component parent, String parentId, String artifactId, ArtifactDefinition artifactInfo,
2298                                               ArtifactDefinition artifactDefinition, NodeTypeEnum parentType) {
2299         if (NodeTypeEnum.Resource == parentType) {
2300             return updateGeneratedIdInHeatEnv(parent.getDeploymentArtifacts(), parent, parentId, artifactId, artifactInfo, artifactDefinition,
2301                 parentType, false);
2302         }
2303         return artifactDefinition.getUniqueId();
2304     }
2305
2306     private String updateGeneratedIdInHeatEnv(Map<String, ArtifactDefinition> deploymentArtifacts, Component parentComponent, String parentId,
2307                                               String artifactId, ArtifactDefinition artifactInfo, ArtifactDefinition artifactDefinition,
2308                                               NodeTypeEnum parentType, boolean isInstanceArtifact) {
2309         String artifactUniqueId;
2310         artifactUniqueId = artifactDefinition.getUniqueId();
2311         String artifactType = artifactInfo.getArtifactType();
2312         if ((ArtifactTypeEnum.HEAT.getType().equalsIgnoreCase(artifactType) || ArtifactTypeEnum.HEAT_VOL.getType().equalsIgnoreCase(artifactType)
2313             || ArtifactTypeEnum.HEAT_NET.getType().equalsIgnoreCase(artifactType)) && !artifactUniqueId.equals(artifactId)) {
2314             // need to update the generated id in heat env
2315             Optional<Entry<String, ArtifactDefinition>> findFirst = deploymentArtifacts.entrySet().stream()
2316                 .filter(a -> artifactId.equals(a.getValue().getGeneratedFromId())).findFirst();
2317             if (findFirst.isPresent()) {
2318                 ArtifactDefinition artifactEnvInfo = findFirst.get().getValue();
2319                 artifactEnvInfo.setIsFromCsar(artifactDefinition.getIsFromCsar());
2320                 artifactEnvInfo.setArtifactChecksum(null);
2321                 if (isInstanceArtifact) {
2322                     artifactToscaOperation
2323                         .updateHeatEnvArtifactOnInstance(parentComponent, artifactEnvInfo, artifactId, artifactUniqueId, parentType, parentId);
2324                 } else {
2325                     artifactToscaOperation
2326                         .updateHeatEnvArtifact(parentComponent, artifactEnvInfo, artifactId, artifactUniqueId, parentType, parentId);
2327                 }
2328             }
2329         }
2330         return artifactUniqueId;
2331     }
2332
2333     private String updateGeneratedIdInHeatEnvOnInstance(ComponentInstance parent, Component parentComponent, String artifactId,
2334                                                         ArtifactDefinition artifactInfo, ArtifactDefinition artifactDefinition,
2335                                                         NodeTypeEnum parentType) {
2336         return updateGeneratedIdInHeatEnv(parent.getDeploymentArtifacts(), parentComponent, parent.getUniqueId(), artifactId, artifactInfo,
2337             artifactDefinition, parentType, true);
2338     }
2339
2340     @VisibleForTesting
2341     private Either<byte[], ResponseFormat> handlePayload(ArtifactDefinition artifactInfo, boolean isArtifactMetadataUpdate) {
2342         log.trace("Starting payload handling");
2343         byte[] payload = artifactInfo.getPayloadData();
2344         byte[] decodedPayload = null;
2345         if (payload != null && payload.length != 0) {
2346             // the generated artifacts were already decoded by the handler
2347             decodedPayload = artifactInfo.getGenerated() ? payload : Base64.decodeBase64(payload);
2348             if (decodedPayload.length == 0) {
2349                 log.debug("Failed to decode the payload.");
2350                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
2351                 return Either.right(responseFormat);
2352             }
2353             String checkSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(decodedPayload);
2354             artifactInfo.setArtifactChecksum(checkSum);
2355             log.trace("Calculated checksum, base64 payload: {},  checksum: {}", payload, checkSum);
2356             // Specific payload validations of different types
2357             Either<Boolean, ResponseFormat> result = Either.left(true);
2358             if (isDeploymentArtifact(artifactInfo)) {
2359                 log.trace("Starting deployment artifacts payload validation");
2360                 String artifactType = artifactInfo.getArtifactType();
2361                 String fileExtension = GeneralUtility.getFilenameExtension(artifactInfo.getArtifactName());
2362                 PayloadTypeEnum payloadType = ArtifactTypeToPayloadTypeSelector.getPayloadType(artifactType, fileExtension);
2363                 final Optional<ResponseFormat> pmDictionaryError = validateIfPmDictionary(artifactType, decodedPayload);
2364                 if (pmDictionaryError.isPresent()) {
2365                     return Either.right(pmDictionaryError.get());
2366                 }
2367                 Either<Boolean, ActionStatus> isPayloadValid = payloadType.isValid(decodedPayload);
2368                 if (isPayloadValid.isRight()) {
2369                     ResponseFormat responseFormat = componentsUtils.getResponseFormat(isPayloadValid.right().value(), artifactType);
2370                     return Either.right(responseFormat);
2371                 }
2372                 if (payloadType.isHeatRelated()) {
2373                     log.trace("Payload is heat related so going to extract heat parameters for artifact type {}", artifactType);
2374                     result = extractHeatParameters(artifactInfo);
2375                 }
2376             }
2377             if (result.isRight()) {
2378                 return Either.right(result.right().value());
2379             }
2380         } // null/empty payload is normal if called from metadata update ONLY.
2381
2382         // The validation of whether this is metadata/payload update case is
2383
2384         // currently done separately
2385         else {
2386             if (!isArtifactMetadataUpdate) {
2387                 log.debug("In artifact: {} Payload is missing.", artifactInfo.getArtifactName());
2388                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_PAYLOAD);
2389                 return Either.right(responseFormat);
2390             }
2391         }
2392         log.trace("Ended payload handling");
2393         return Either.left(decodedPayload);
2394     }
2395
2396     private Optional<ResponseFormat> validateIfPmDictionary(String artifactType, byte[] decodedPayload) {
2397         return new PMDictionaryValidator().validateIfPmDictionary(artifactType, decodedPayload).map(this::preparePmDictionaryResponse);
2398     }
2399
2400     private ResponseFormat preparePmDictionaryResponse(String errorMessage) {
2401         return componentsUtils.getResponseFormat(ActionStatus.INVALID_PM_DICTIONARY_FILE, errorMessage);
2402     }
2403
2404     public Either<ArtifactDefinition, ResponseFormat> deleteArtifactByInterface(String resourceId, String userUserId, String artifactId,
2405                                                                                 boolean inTransaction) {
2406         return toscaOperationFacade.getToscaElement(resourceId, JsonParseFlagEnum.ParseMetadata).right().map(componentsUtils.toResponseFormat())
2407             .left().bind(parentComponent -> {
2408                 User user = new User(userUserId);
2409                 return handleDelete(resourceId, artifactId, user, parentComponent, false, inTransaction);
2410             });
2411     }
2412
2413     private Operation convertToOperation(ArtifactDefinition artifactInfo, String operationName) {
2414         Operation op = new Operation();
2415         long time = System.currentTimeMillis();
2416         op.setCreationDate(time);
2417         String artifactName = artifactInfo.getArtifactName();
2418         artifactInfo.setArtifactName(createInterfaceArtifactNameFromOperation(operationName, artifactName));
2419         op.setImplementation(artifactInfo);
2420         op.setLastUpdateDate(time);
2421         return op;
2422     }
2423
2424     private String createInterfaceArtifactNameFromOperation(String operationName, String artifactName) {
2425         String newArtifactName = operationName + "_" + artifactName;
2426         log.trace("converting artifact name {} to {}", artifactName, newArtifactName);
2427         return newArtifactName;
2428     }
2429
2430     // download by MSO
2431     public byte[] downloadRsrcArtifactByNames(String serviceName, String serviceVersion, String resourceName, String resourceVersion,
2432                                               String artifactName) {
2433         // General validation
2434         if (serviceName == null || serviceVersion == null || resourceName == null || resourceVersion == null || artifactName == null) {
2435             log.debug(NULL_PARAMETER);
2436             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
2437         }
2438         // Normalizing artifact name
2439         artifactName = ValidationUtils.normalizeFileName(artifactName);
2440         // Resource validation
2441         Resource resource = validateResourceNameAndVersion(resourceName, resourceVersion);
2442         String resourceId = resource.getUniqueId();
2443         // Service validation
2444         Service validateServiceNameAndVersion = validateServiceNameAndVersion(serviceName, serviceVersion);
2445         Map<String, ArtifactDefinition> artifacts = resource.getDeploymentArtifacts();
2446         if (artifacts == null || artifacts.isEmpty()) {
2447             log.debug("Deployment artifacts of resource {} are not found", resourceId);
2448             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactName);
2449         }
2450         ArtifactDefinition deploymentArtifact = null;
2451         for (ArtifactDefinition artifactDefinition : artifacts.values()) {
2452             if (artifactDefinition.getArtifactName() != null && artifactDefinition.getArtifactName().equals(artifactName)) {
2453                 log.debug(FOUND_DEPLOYMENT_ARTIFACT, artifactName);
2454                 deploymentArtifact = artifactDefinition;
2455                 break;
2456             }
2457         }
2458         if (deploymentArtifact == null) {
2459             log.debug("No deployment artifact {} was found for resource {}", artifactName, resourceId);
2460             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactName);
2461         }
2462         // Downloading the artifact
2463         ImmutablePair<String, byte[]> downloadArtifactEither = downloadArtifact(deploymentArtifact);
2464         log.trace("Download of resource artifact succeeded, uniqueId {}", deploymentArtifact.getUniqueId());
2465         return downloadArtifactEither.getRight();
2466     }
2467
2468     // download by MSO
2469     public byte[] downloadRsrcInstArtifactByNames(String serviceName, String serviceVersion, String resourceInstanceName, String artifactName) {
2470         // General validation
2471         if (serviceName == null || serviceVersion == null || resourceInstanceName == null || artifactName == null) {
2472             log.debug(NULL_PARAMETER);
2473             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
2474         }
2475         // Normalizing artifact name
2476         artifactName = ValidationUtils.normalizeFileName(artifactName);
2477         // Service validation
2478         Service service = validateServiceNameAndVersion(serviceName, serviceVersion);
2479         // ResourceInstance validation
2480         ComponentInstance resourceInstance = validateResourceInstance(service, resourceInstanceName);
2481         Map<String, ArtifactDefinition> artifacts = resourceInstance.getDeploymentArtifacts();
2482         final String finalArtifactName = artifactName;
2483         Predicate<ArtifactDefinition> filterArtifactByName = p -> p.getArtifactName().equals(finalArtifactName);
2484         ArtifactDefinition deployableArtifact =
2485             artifacts == null ? null : artifacts.values().stream().filter(filterArtifactByName).findFirst().orElse(null);
2486         if (deployableArtifact == null) {
2487             log.debug("Deployment artifact with name {} not found", artifactName);
2488             throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND, artifactName));
2489         }
2490         log.debug(FOUND_DEPLOYMENT_ARTIFACT, artifactName);
2491         ImmutablePair<String, byte[]> downloadArtifactEither = downloadArtifact(deployableArtifact);
2492         log.trace("Download of resource artifact succeeded, uniqueId {}", deployableArtifact.getUniqueId());
2493         return downloadArtifactEither.getRight();
2494     }
2495
2496     private ComponentInstance validateResourceInstance(Service service, String resourceInstanceName) {
2497         List<ComponentInstance> riList = service.getComponentInstances();
2498         for (ComponentInstance ri : riList) {
2499             if (ri.getNormalizedName().equals(resourceInstanceName)) {
2500                 return ri;
2501             }
2502         }
2503         throw new ByActionStatusComponentException(ActionStatus.RESOURCE_INSTANCE_NOT_FOUND, resourceInstanceName);
2504     }
2505
2506     private ComponentInstance validateResourceInstanceById(Component component, String resourceInstanceId) {
2507         List<ComponentInstance> riList = component.getComponentInstances();
2508         for (ComponentInstance ri : riList) {
2509             if (ri.getUniqueId().equals(resourceInstanceId)) {
2510                 return ri;
2511             }
2512         }
2513         throw new ByActionStatusComponentException(ActionStatus.RESOURCE_NOT_FOUND, resourceInstanceId);
2514     }
2515
2516     private Service validateServiceNameAndVersion(String serviceName, String serviceVersion) {
2517         Either<List<Service>, StorageOperationStatus> serviceListBySystemName = toscaOperationFacade
2518             .getBySystemName(ComponentTypeEnum.SERVICE, serviceName);
2519         if (serviceListBySystemName.isRight()) {
2520             log.debug("Couldn't fetch any service with name {}", serviceName);
2521             throw new ByActionStatusComponentException(
2522                 componentsUtils.convertFromStorageResponse(serviceListBySystemName.right().value(), ComponentTypeEnum.SERVICE), serviceName);
2523         }
2524         List<Service> serviceList = serviceListBySystemName.left().value();
2525         if (serviceList == null || serviceList.isEmpty()) {
2526             log.debug("Couldn't fetch any service with name {}", serviceName);
2527             throw new ByActionStatusComponentException(ActionStatus.SERVICE_NOT_FOUND, serviceName);
2528         }
2529         Service foundService = null;
2530         for (Service service : serviceList) {
2531             if (service.getVersion().equals(serviceVersion)) {
2532                 log.trace("Found service with version {}", serviceVersion);
2533                 foundService = service;
2534                 break;
2535             }
2536         }
2537         if (foundService == null) {
2538             log.debug("Couldn't find version {} for service {}", serviceVersion, serviceName);
2539             throw new ByActionStatusComponentException(ActionStatus.COMPONENT_VERSION_NOT_FOUND, ComponentTypeEnum.SERVICE.getValue(),
2540                 serviceVersion);
2541         }
2542         return foundService;
2543     }
2544
2545     private Resource validateResourceNameAndVersion(String resourceName, String resourceVersion) {
2546         Either<Resource, StorageOperationStatus> resourceListBySystemName = toscaOperationFacade
2547             .getComponentByNameAndVersion(ComponentTypeEnum.RESOURCE, resourceName, resourceVersion, JsonParseFlagEnum.ParseMetadata);
2548         if (resourceListBySystemName.isRight()) {
2549             log.debug("Couldn't fetch any resource with name {} and version {}. ", resourceName, resourceVersion);
2550             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(resourceListBySystemName.right().value()),
2551                 resourceName);
2552         }
2553         return resourceListBySystemName.left().value();
2554     }
2555
2556     public byte[] downloadServiceArtifactByNames(String serviceName, String serviceVersion, String artifactName) {
2557         // Validation
2558         log.trace("Starting download of service interface artifact, serviceName {}, serviceVersion {}, artifact name {}", serviceName, serviceVersion,
2559             artifactName);
2560         if (serviceName == null || serviceVersion == null || artifactName == null) {
2561             log.debug(NULL_PARAMETER);
2562             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
2563         }
2564         // Normalizing artifact name
2565         final String normalizedArtifactName = ValidationUtils.normalizeFileName(artifactName);
2566         // Service validation
2567         Service service = validateServiceNameAndVersion(serviceName, serviceVersion);
2568         // Looking for deployment or tosca artifacts
2569         String serviceId = service.getUniqueId();
2570         if (MapUtils.isEmpty(service.getDeploymentArtifacts()) && MapUtils.isEmpty(service.getToscaArtifacts())) {
2571             log.debug("Neither Deployment nor Tosca artifacts of service {} are found", serviceId);
2572             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, normalizedArtifactName);
2573         }
2574         Optional<ArtifactDefinition> foundArtifactOptl = Optional.empty();
2575         if (!MapUtils.isEmpty(service.getDeploymentArtifacts())) {
2576             foundArtifactOptl = service.getDeploymentArtifacts().values().stream()
2577                 // filters artifact by name
2578                 .filter(a -> a.getArtifactName().equals(normalizedArtifactName)).findAny();
2579         }
2580         if ((!foundArtifactOptl.isPresent()) && !MapUtils.isEmpty(service.getToscaArtifacts())) {
2581             foundArtifactOptl = service.getToscaArtifacts().values().stream()
2582                 // filters TOSCA artifact by name
2583                 .filter(a -> a.getArtifactName().equals(normalizedArtifactName)).findAny();
2584         }
2585         if (!foundArtifactOptl.isPresent()) {
2586             log.debug("The artifact {} was not found for service {}", normalizedArtifactName, serviceId);
2587             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, normalizedArtifactName);
2588         }
2589         log.debug(FOUND_DEPLOYMENT_ARTIFACT, normalizedArtifactName);
2590         // Downloading the artifact
2591         ImmutablePair<String, byte[]> downloadArtifactEither = downloadArtifact(foundArtifactOptl.get());
2592         log.trace("Download of service artifact succeeded, uniqueId {}", foundArtifactOptl.get().getUniqueId());
2593         return downloadArtifactEither.getRight();
2594     }
2595
2596     public ImmutablePair<String, byte[]> downloadArtifact(String parentId, String artifactUniqueId) {
2597         log.trace("Starting download of artifact, uniqueId {}", artifactUniqueId);
2598         Either<ArtifactDefinition, StorageOperationStatus> artifactById = artifactToscaOperation.getArtifactById(parentId, artifactUniqueId);
2599         if (artifactById.isRight()) {
2600             ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(artifactById.right().value());
2601             log.debug("Error when getting artifact info by id{}, error: {}", artifactUniqueId, actionStatus);
2602             throw new ByResponseFormatComponentException(componentsUtils.getResponseFormatByArtifactId(actionStatus, ""));
2603         }
2604         ArtifactDefinition artifactDefinition = artifactById.left().value();
2605         if (artifactDefinition == null) {
2606             log.debug("Empty artifact definition returned from DB by artifact id {}", artifactUniqueId);
2607             throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND, ""));
2608         }
2609         return downloadArtifact(artifactDefinition);
2610     }
2611
2612     private Component validateComponentExists(String componentId, AuditingActionEnum auditingAction, User user, String artifactId,
2613                                               ComponentTypeEnum componentType, String containerComponentType) {
2614         ComponentTypeEnum componentForAudit =
2615             null == containerComponentType ? componentType : ComponentTypeEnum.findByParamName(containerComponentType);
2616         componentForAudit.getNodeType();
2617         Either<? extends Component, StorageOperationStatus> componentResult = toscaOperationFacade.getToscaFullElement(componentId);
2618         if (componentResult.isRight()) {
2619             ActionStatus status = componentForAudit == ComponentTypeEnum.RESOURCE ? ActionStatus.RESOURCE_NOT_FOUND
2620                 : componentForAudit == ComponentTypeEnum.SERVICE ? ActionStatus.SERVICE_NOT_FOUND : ActionStatus.PRODUCT_NOT_FOUND;
2621             ResponseFormat responseFormat = componentsUtils.getResponseFormat(status, componentId);
2622             log.debug("Service not found, serviceId {}", componentId);
2623             handleAuditing(auditingAction, null, componentId, user, null, null, artifactId, responseFormat, componentForAudit, null);
2624             throw new ByActionStatusComponentException(status, componentId);
2625         }
2626         return componentResult.left().value();
2627     }
2628
2629     private void validateWorkOnComponent(Component component, String userId, AuditingActionEnum auditingAction, User user, String artifactId,
2630                                          ArtifactOperationInfo operation) {
2631         if (operation.getArtifactOperationEnum() != ArtifactOperationEnum.DOWNLOAD && !operation.ignoreLifecycleState()) {
2632             try {
2633                 validateCanWorkOnComponent(component, userId);
2634             } catch (ComponentException e) {
2635                 String uniqueId = component.getUniqueId();
2636                 log.debug("Service status isn't  CHECKOUT or user isn't owner, serviceId {}", uniqueId);
2637                 handleAuditing(auditingAction, component, uniqueId, user, null, null, artifactId, e.getResponseFormat(), component.getComponentType(),
2638                     null);
2639                 throw e;
2640             }
2641         }
2642     }
2643
2644     private void validateUserRole(User user, AuditingActionEnum auditingAction, String componentId, String artifactId,
2645                                   ComponentTypeEnum componentType, ArtifactOperationInfo operation) {
2646         if (operation.isNotDownload()) {
2647             String role = user.getRole();
2648             if (!role.equals(Role.ADMIN.name()) && !role.equals(Role.DESIGNER.name())) {
2649                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
2650                 log.debug("addArtifact - user isn't permitted to perform operation, userId {}, role {}", user.getUserId(), role);
2651                 handleAuditing(auditingAction, null, componentId, user, null, null, artifactId, responseFormat, componentType, null);
2652                 throw new ByActionStatusComponentException(ActionStatus.RESTRICTED_OPERATION);
2653             }
2654         }
2655     }
2656
2657     private User validateUserExists(String userId, AuditingActionEnum auditingAction, String componentId, String artifactId,
2658                                     ComponentTypeEnum componentType, boolean inTransaction) {
2659         User user;
2660         try {
2661             user = validateUserExists(userId);
2662         } catch (ByResponseFormatComponentException e) {
2663             ResponseFormat responseFormat = e.getResponseFormat();
2664             handleComponentException(auditingAction, componentId, artifactId, responseFormat, componentType, userId);
2665             throw e;
2666         } catch (ByActionStatusComponentException e) {
2667             ResponseFormat responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
2668             handleComponentException(auditingAction, componentId, artifactId, responseFormat, componentType, userId);
2669             throw e;
2670         }
2671         return user;
2672     }
2673
2674     private void handleComponentException(AuditingActionEnum auditingAction, String componentId, String artifactId, ResponseFormat responseFormat,
2675                                           ComponentTypeEnum componentType, String userId) {
2676         User user = new User();
2677         user.setUserId(userId);
2678         handleAuditing(auditingAction, null, componentId, user, null, null, artifactId, responseFormat, componentType, null);
2679     }
2680
2681     protected AuditingActionEnum detectAuditingType(ArtifactOperationInfo operation, String origMd5) {
2682         AuditingActionEnum auditingAction = null;
2683         switch (operation.getArtifactOperationEnum()) {
2684             case CREATE:
2685                 auditingAction = operation.isExternalApi() ? AuditingActionEnum.ARTIFACT_UPLOAD_BY_API : AuditingActionEnum.ARTIFACT_UPLOAD;
2686                 break;
2687             case UPDATE:
2688                 auditingAction = operation.isExternalApi() ? AuditingActionEnum.ARTIFACT_UPLOAD_BY_API
2689                     : origMd5 == null ? AuditingActionEnum.ARTIFACT_METADATA_UPDATE : AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE;
2690                 break;
2691             case DELETE:
2692                 auditingAction = operation.isExternalApi() ? AuditingActionEnum.ARTIFACT_DELETE_BY_API : AuditingActionEnum.ARTIFACT_DELETE;
2693                 break;
2694             case DOWNLOAD:
2695                 auditingAction = operation.isExternalApi() ? AuditingActionEnum.DOWNLOAD_ARTIFACT : AuditingActionEnum.ARTIFACT_DOWNLOAD;
2696                 break;
2697             default:
2698                 break;
2699         }
2700         return auditingAction;
2701     }
2702
2703     private ImmutablePair<String, byte[]> downloadArtifact(ArtifactDefinition artifactDefinition) {
2704         String esArtifactId = artifactDefinition.getEsId();
2705         Either<DAOArtifactData, CassandraOperationStatus> artifactfromES = artifactCassandraDao.getArtifact(esArtifactId);
2706         if (artifactfromES.isRight()) {
2707             CassandraOperationStatus resourceUploadStatus = artifactfromES.right().value();
2708             StorageOperationStatus storageResponse = DaoStatusConverter.convertCassandraStatusToStorageStatus(resourceUploadStatus);
2709             ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(storageResponse);
2710             log.debug("Error when getting artifact from ES, error: {}", actionStatus);
2711             throw new ByActionStatusComponentException(actionStatus, artifactDefinition.getArtifactDisplayName());
2712         }
2713         DAOArtifactData DAOArtifactData = artifactfromES.left().value();
2714         byte[] data = DAOArtifactData.getDataAsArray();
2715         if (data == null) {
2716             log.debug("Artifact data from cassandra is null");
2717             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactDefinition.getArtifactDisplayName());
2718         }
2719         String artifactName = artifactDefinition.getArtifactName();
2720         log.trace("Download of artifact succeeded, uniqueId {}, artifact file name {}", artifactDefinition.getUniqueId(), artifactName);
2721         return new ImmutablePair<>(artifactName, data);
2722     }
2723
2724     public DAOArtifactData createEsArtifactData(ArtifactDataDefinition artifactInfo, byte[] artifactPayload) {
2725         return new DAOArtifactData(artifactInfo.getEsId(), artifactPayload);
2726     }
2727
2728     private void saveArtifactInCassandra(DAOArtifactData artifactData, Component parent, ArtifactDefinition artifactInfo, String currArtifactId,
2729                                          String prevArtifactId, AuditingActionEnum auditingAction, ComponentTypeEnum componentType) {
2730         CassandraOperationStatus resourceUploadStatus = artifactCassandraDao.saveArtifact(artifactData);
2731         if (resourceUploadStatus == CassandraOperationStatus.OK) {
2732             log.debug("Artifact {} was saved in component {}.", artifactData.getId(), parent.getUniqueId());
2733             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
2734             handleAuditing(auditingAction, parent, parent.getUniqueId(), null, artifactInfo, prevArtifactId, currArtifactId, responseFormat,
2735                 componentType, null);
2736         } else {
2737             BeEcompErrorManager.getInstance().logBeDaoSystemError(UPDATE_ARTIFACT);
2738             log.info(FAILED_SAVE_ARTIFACT);
2739             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
2740             handleAuditing(auditingAction, parent, parent.getUniqueId(), null, artifactInfo, prevArtifactId, currArtifactId, responseFormat,
2741                 componentType, null);
2742             throw new StorageException(resourceUploadStatus);
2743         }
2744     }
2745
2746     private boolean isArtifactMetadataUpdate(AuditingActionEnum auditingActionEnum) {
2747         return auditingActionEnum == AuditingActionEnum.ARTIFACT_METADATA_UPDATE;
2748     }
2749
2750     private boolean isDeploymentArtifact(ArtifactDefinition artifactInfo) {
2751         return ArtifactGroupTypeEnum.DEPLOYMENT == artifactInfo.getArtifactGroupType();
2752     }
2753
2754     private boolean isInformationalArtifact(final ArtifactDefinition artifactInfo) {
2755         return ArtifactGroupTypeEnum.INFORMATIONAL == artifactInfo.getArtifactGroupType();
2756     }
2757
2758     private boolean isHeatArtifact(final ArtifactDefinition artifactInfo) {
2759         final String artifactType = artifactInfo.getArtifactType();
2760         final ArtifactTypeEnum artifactTypeEnum = ArtifactTypeEnum.parse(artifactType);
2761         if (artifactTypeEnum == null) {
2762             artifactInfo.setTimeout(NodeTemplateOperation.NON_HEAT_TIMEOUT);
2763             return false;
2764         }
2765         switch (artifactTypeEnum) {
2766             case HEAT:
2767             case HEAT_VOL:
2768             case HEAT_NET:
2769             case HEAT_ENV:
2770                 return true;
2771             default:
2772                 return false;
2773         }
2774     }
2775
2776     public ArtifactDefinition createArtifactPlaceHolderInfo(String resourceId, String logicalName, Map<String, Object> artifactInfoMap,
2777                                                             String userUserId, ArtifactGroupTypeEnum groupType, boolean inTransaction) {
2778         User user = userBusinessLogic.getUser(userUserId, inTransaction);
2779         return createArtifactPlaceHolderInfo(resourceId, logicalName, artifactInfoMap, user, groupType);
2780     }
2781
2782     public ArtifactDefinition createArtifactPlaceHolderInfo(String resourceId, String logicalName, Map<String, Object> artifactInfoMap, User user,
2783                                                             ArtifactGroupTypeEnum groupType) {
2784         ArtifactDefinition artifactInfo = new ArtifactDefinition();
2785         String artifactName = (String) artifactInfoMap.get(ARTIFACT_PLACEHOLDER_DISPLAY_NAME);
2786         String artifactType = (String) artifactInfoMap.get(ARTIFACT_PLACEHOLDER_TYPE);
2787         String artifactDescription = (String) artifactInfoMap.get(ARTIFACT_PLACEHOLDER_DESCRIPTION);
2788         artifactInfo.setArtifactDisplayName(artifactName);
2789         artifactInfo.setArtifactLabel(logicalName.toLowerCase());
2790         artifactInfo.setArtifactType(artifactType);
2791         artifactInfo.setDescription(artifactDescription);
2792         artifactInfo.setArtifactGroupType(groupType);
2793         nodeTemplateOperation.setDefaultArtifactTimeout(groupType, artifactInfo);
2794         setArtifactPlaceholderCommonFields(resourceId, user, artifactInfo);
2795         return artifactInfo;
2796     }
2797
2798     private void setArtifactPlaceholderCommonFields(String resourceId, User user, ArtifactDefinition artifactInfo) {
2799         String uniqueId = null;
2800         if (resourceId != null) {
2801             uniqueId = UniqueIdBuilder.buildPropertyUniqueId(resourceId.toLowerCase(), artifactInfo.getArtifactLabel().toLowerCase());
2802             artifactInfo.setUniqueId(uniqueId);
2803         }
2804         artifactInfo.setUserIdCreator(user.getUserId());
2805         String fullName = user.getFullName();
2806         artifactInfo.setUpdaterFullName(fullName);
2807         long time = System.currentTimeMillis();
2808         artifactInfo.setCreatorFullName(fullName);
2809         artifactInfo.setCreationDate(time);
2810         artifactInfo.setLastUpdateDate(time);
2811         artifactInfo.setUserIdLastUpdater(user.getUserId());
2812         artifactInfo.setMandatory(true);
2813     }
2814
2815     public Either<Map<String, ArtifactDefinition>, StorageOperationStatus> getArtifacts(String parentId, NodeTypeEnum parentType,
2816                                                                                         ArtifactGroupTypeEnum groupType, String instanceId) {
2817         return artifactToscaOperation.getArtifacts(parentId, parentType, groupType, instanceId);
2818     }
2819
2820     public Either<ArtifactDefinition, StorageOperationStatus> addHeatEnvArtifact(ArtifactDefinition artifactHeatEnv, ArtifactDefinition artifact,
2821                                                                                  Component component, NodeTypeEnum parentType, String instanceId) {
2822         return artifactToscaOperation.addHeatEnvArtifact(artifactHeatEnv, artifact, component, parentType, true, instanceId);
2823     }
2824
2825     private Either<DAOArtifactData, ResponseFormat> createEsHeatEnvArtifactDataFromString(ArtifactDefinition artifactDefinition, String payloadStr) {
2826         byte[] payload = payloadStr.getBytes();
2827         DAOArtifactData artifactData = createEsArtifactData(artifactDefinition, payload);
2828         return Either.left(artifactData);
2829     }
2830
2831     /**
2832      * @param artifactDefinition
2833      * @return
2834      */
2835     public Either<ArtifactDefinition, ResponseFormat> generateHeatEnvArtifact(ArtifactDefinition artifactDefinition, ComponentTypeEnum componentType,
2836                                                                               Component component, String resourceInstanceName, User modifier,
2837                                                                               String instanceId, boolean shouldLock, boolean inTransaction) {
2838         String payload = generateHeatEnvPayload(artifactDefinition);
2839         String prevUUID = artifactDefinition.getArtifactUUID();
2840         ArtifactDefinition clonedBeforeGenerate = new ArtifactDefinition(artifactDefinition);
2841         return generateAndSaveHeatEnvArtifact(artifactDefinition, payload, componentType, component, resourceInstanceName, modifier, instanceId,
2842             shouldLock, inTransaction).left()
2843             .bind(artifactDef -> updateArtifactOnGroupInstance(component, instanceId, prevUUID, clonedBeforeGenerate, artifactDef));
2844     }
2845
2846     public Either<ArtifactDefinition, ResponseFormat> forceGenerateHeatEnvArtifact(ArtifactDefinition artifactDefinition,
2847                                                                                    ComponentTypeEnum componentType, Component component,
2848                                                                                    String resourceInstanceName, User modifier, boolean shouldLock,
2849                                                                                    boolean inTransaction, String instanceId) {
2850         String payload = generateHeatEnvPayload(artifactDefinition);
2851         String prevUUID = artifactDefinition.getArtifactUUID();
2852         ArtifactDefinition clonedBeforeGenerate = new ArtifactDefinition(artifactDefinition);
2853         return forceGenerateAndSaveHeatEnvArtifact(artifactDefinition, payload, componentType, component, resourceInstanceName, modifier, instanceId,
2854             shouldLock, inTransaction).left()
2855             .bind(artifactDef -> updateArtifactOnGroupInstance(component, instanceId, prevUUID, clonedBeforeGenerate, artifactDef));
2856     }
2857
2858     @VisibleForTesting
2859     Either<ArtifactDefinition, ResponseFormat> updateArtifactOnGroupInstance(Component component, String instanceId, String prevUUID,
2860                                                                              ArtifactDefinition clonedBeforeGenerate,
2861                                                                              ArtifactDefinition updatedArtDef) {
2862         if (prevUUID == null || !prevUUID.equals(updatedArtDef.getArtifactUUID())) {
2863             List<ComponentInstance> componentInstances = component.getComponentInstances();
2864             if (componentInstances != null) {
2865                 Optional<ComponentInstance> findFirst = componentInstances.stream().filter(ci -> ci.getUniqueId().equals(instanceId)).findFirst();
2866                 if (findFirst.isPresent()) {
2867                     ComponentInstance relevantInst = findFirst.get();
2868                     List<GroupInstance> updatedGroupInstances = getUpdatedGroupInstances(updatedArtDef.getUniqueId(), clonedBeforeGenerate,
2869                         relevantInst.getGroupInstances());
2870                     if (CollectionUtils.isNotEmpty(updatedGroupInstances)) {
2871                         updatedGroupInstances.forEach(gi -> {
2872                             gi.getGroupInstanceArtifacts().add(updatedArtDef.getUniqueId());
2873                             gi.getGroupInstanceArtifactsUuid().add(updatedArtDef.getArtifactUUID());
2874                         });
2875                         Either<List<GroupInstance>, StorageOperationStatus> status = toscaOperationFacade
2876                             .updateGroupInstancesOnComponent(component, instanceId, updatedGroupInstances);
2877                         if (status.isRight()) {
2878                             log.debug(FAILED_UPDATE_GROUPS, component.getUniqueId());
2879                             ResponseFormat responseFormat = componentsUtils
2880                                 .getResponseFormatByArtifactId(componentsUtils.convertFromStorageResponse(status.right().value()),
2881                                     clonedBeforeGenerate.getArtifactDisplayName());
2882                             return Either.right(responseFormat);
2883                         }
2884                     }
2885                 }
2886             }
2887         }
2888         return Either.left(updatedArtDef);
2889     }
2890
2891     private String generateHeatEnvPayload(ArtifactDefinition artifactDefinition) {
2892         List<HeatParameterDefinition> heatParameters = artifactDefinition.getListHeatParameters();
2893         StringBuilder sb = new StringBuilder();
2894         sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactHeader());
2895         sb.append("parameters:\n");
2896         if (heatParameters != null) {
2897             heatParameters.sort(Comparator.comparing(HeatParameterDataDefinition::getName));
2898             List<HeatParameterDefinition> empltyHeatValues = new ArrayList<>();
2899             for (HeatParameterDefinition heatParameterDefinition : heatParameters) {
2900                 String heatValue = heatParameterDefinition.getCurrentValue();
2901                 if (!ValidationUtils.validateStringNotEmpty(heatValue)) {
2902                     heatValue = heatParameterDefinition.getDefaultValue();
2903                     if (!ValidationUtils.validateStringNotEmpty(heatValue)) {
2904                         empltyHeatValues.add(heatParameterDefinition);
2905                         continue;
2906                     }
2907                 }
2908                 HeatParameterType type = HeatParameterType.isValidType(heatParameterDefinition.getType());
2909                 if (type != null) {
2910                     switch (type) {
2911                         case BOOLEAN:
2912                             sb.append("  ").append(heatParameterDefinition.getName()).append(":").append(" ").append(Boolean.parseBoolean(heatValue))
2913                                 .append("\n");
2914                             break;
2915                         case NUMBER:
2916                             sb.append("  ").append(heatParameterDefinition.getName()).append(":").append(" ")
2917                                 .append(new BigDecimal(heatValue).toPlainString()).append("\n");
2918                             break;
2919                         case COMMA_DELIMITED_LIST:
2920                         case JSON:
2921                             sb.append("  ").append(heatParameterDefinition.getName()).append(":").append(" ").append(heatValue).append("\n");
2922                             break;
2923                         default:
2924                             String value = heatValue;
2925                             boolean starts = value.startsWith("\"");
2926                             boolean ends = value.endsWith("\"");
2927                             if (!(starts && ends)) {
2928                                 starts = value.startsWith("'");
2929                                 ends = value.endsWith("'");
2930                                 if (!(starts && ends)) {
2931                                     value = "\"" + value + "\"";
2932                                 }
2933                             }
2934                             sb.append("  ").append(heatParameterDefinition.getName()).append(":").append(" ").append(value);
2935                             sb.append("\n");
2936                             break;
2937                     }
2938                 }
2939             }
2940             if (!empltyHeatValues.isEmpty()) {
2941                 empltyHeatValues.sort(Comparator.comparing(HeatParameterDataDefinition::getName));
2942                 empltyHeatValues.forEach(hv -> {
2943                     sb.append("  ").append(hv.getName()).append(":");
2944                     HeatParameterType type = HeatParameterType.isValidType(hv.getType());
2945                     if (type != null && type == HeatParameterType.STRING && (hv.getCurrentValue() != null && "".equals(hv.getCurrentValue())
2946                         || hv.getDefaultValue() != null && "".equals(hv.getDefaultValue()))) {
2947                         sb.append(" \"\"").append("\n");
2948                     } else {
2949                         sb.append(" ").append("\n");
2950                     }
2951                 });
2952             }
2953         }
2954         sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactFooter());
2955         // DE265919 fix
2956         return sb.toString().replace("\\\\n", "\n");
2957     }
2958
2959     /**
2960      * @param artifactDefinition
2961      * @param payload
2962      * @return
2963      */
2964     public Either<ArtifactDefinition, ResponseFormat> generateAndSaveHeatEnvArtifact(ArtifactDefinition artifactDefinition, String payload,
2965                                                                                      ComponentTypeEnum componentType, Component component,
2966                                                                                      String resourceInstanceName, User modifier, String instanceId,
2967                                                                                      boolean shouldLock, boolean inTransaction) {
2968         return generateArtifactPayload(artifactDefinition, componentType, component, resourceInstanceName, modifier, shouldLock, inTransaction,
2969             artifactDefinition::getHeatParamsUpdateDate, () -> createEsHeatEnvArtifactDataFromString(artifactDefinition, payload), instanceId);
2970     }
2971
2972     public Either<ArtifactDefinition, ResponseFormat> forceGenerateAndSaveHeatEnvArtifact(ArtifactDefinition artifactDefinition, String payload,
2973                                                                                           ComponentTypeEnum componentType, Component component,
2974                                                                                           String resourceInstanceName, User modifier,
2975                                                                                           String instanceId, boolean shouldLock,
2976                                                                                           boolean inTransaction) {
2977         return generateArtifactPayload(artifactDefinition, componentType, component, resourceInstanceName, modifier, shouldLock, inTransaction,
2978             System::currentTimeMillis, () -> createEsHeatEnvArtifactDataFromString(artifactDefinition, payload), instanceId);
2979     }
2980
2981     protected Either<ArtifactDefinition, ResponseFormat> generateArtifactPayload(ArtifactDefinition artifactDefinition,
2982                                                                                  ComponentTypeEnum componentType, Component component,
2983                                                                                  String resourceInstanceName, User modifier, boolean shouldLock,
2984                                                                                  boolean inTransaction, Supplier<Long> payloadUpdateDateGen,
2985                                                                                  Supplier<Either<DAOArtifactData, ResponseFormat>> esDataCreator,
2986                                                                                  String instanceId) {
2987         log.trace("Start generating payload for {} artifact {}", artifactDefinition.getArtifactType(), artifactDefinition.getEsId());
2988         if (artifactDefinition.getPayloadUpdateDate() == null || artifactDefinition.getPayloadUpdateDate() == 0
2989             || artifactDefinition.getPayloadUpdateDate() <= payloadUpdateDateGen.get()) {
2990             log.trace("Generating payload for {} artifact {}", artifactDefinition.getArtifactType(), artifactDefinition.getEsId());
2991             Either<DAOArtifactData, ResponseFormat> artifactDataRes = esDataCreator.get();
2992             DAOArtifactData artifactData = null;
2993             if (artifactDataRes.isLeft()) {
2994                 artifactData = artifactDataRes.left().value();
2995             } else {
2996                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
2997                 handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition,
2998                     artifactDefinition.getUniqueId(), artifactDefinition.getUniqueId(), responseFormat, ComponentTypeEnum.RESOURCE_INSTANCE,
2999                     resourceInstanceName);
3000                 return Either.right(artifactDataRes.right().value());
3001             }
3002             String newCheckSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(artifactData.getDataAsArray());
3003             String oldCheckSum;
3004             String esArtifactId = artifactDefinition.getEsId();
3005             Either<DAOArtifactData, CassandraOperationStatus> artifactfromES;
3006             DAOArtifactData DAOArtifactData;
3007             if (esArtifactId != null && !esArtifactId.isEmpty() && artifactDefinition.getPayloadData() == null) {
3008                 log.debug("Try to fetch artifact from cassandra with id : {}", esArtifactId);
3009                 artifactfromES = artifactCassandraDao.getArtifact(esArtifactId);
3010                 if (artifactfromES.isRight()) {
3011                     CassandraOperationStatus resourceUploadStatus = artifactfromES.right().value();
3012                     StorageOperationStatus storageResponse = DaoStatusConverter.convertCassandraStatusToStorageStatus(resourceUploadStatus);
3013                     ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(storageResponse);
3014                     log.debug("Error when getting artifact from ES, error: {} esid : {}", actionStatus, esArtifactId);
3015                     return Either.right(componentsUtils.getResponseFormatByArtifactId(actionStatus, artifactDefinition.getArtifactDisplayName()));
3016                 }
3017                 DAOArtifactData = artifactfromES.left().value();
3018                 oldCheckSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(DAOArtifactData.getDataAsArray());
3019             } else {
3020                 oldCheckSum = artifactDefinition.getArtifactChecksum();
3021             }
3022             Either<ArtifactDefinition, StorageOperationStatus> updateArifactDefinitionStatus = null;
3023             if (shouldLock) {
3024                 try {
3025                     lockComponent(component, "Update Artifact - lock resource: ");
3026                 } catch (ComponentException e) {
3027                     handleAuditing(AuditingActionEnum.ARTIFACT_METADATA_UPDATE, component, component.getUniqueId(), modifier, null, null,
3028                         artifactDefinition.getUniqueId(), e.getResponseFormat(), component.getComponentType(), null);
3029                     throw e;
3030                 }
3031             }
3032             try {
3033                 if (oldCheckSum != null && oldCheckSum.equals(newCheckSum)) {
3034                     artifactDefinition.setPayloadUpdateDate(payloadUpdateDateGen.get());
3035                     updateArifactDefinitionStatus = artifactToscaOperation
3036                         .updateArtifactOnResource(artifactDefinition, component, artifactDefinition.getUniqueId(), componentType.getNodeType(),
3037                             instanceId, true);
3038                     log.trace("No real update done in payload for {} artifact, updating payloadUpdateDate {}", artifactDefinition.getArtifactType(),
3039                         artifactDefinition.getEsId());
3040                     if (updateArifactDefinitionStatus.isRight()) {
3041                         ResponseFormat responseFormat = componentsUtils
3042                             .getResponseFormatByArtifactId(componentsUtils.convertFromStorageResponse(updateArifactDefinitionStatus.right().value()),
3043                                 artifactDefinition.getArtifactDisplayName());
3044                         log.trace("Failed to update payloadUpdateDate {}", artifactDefinition.getEsId());
3045                         handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition,
3046                             artifactDefinition.getUniqueId(), artifactDefinition.getUniqueId(), responseFormat, ComponentTypeEnum.RESOURCE_INSTANCE,
3047                             resourceInstanceName);
3048                         return Either.right(responseFormat);
3049                     }
3050                 } else {
3051                     artifactDefinition.getArtifactChecksum();
3052                     artifactDefinition.setArtifactChecksum(newCheckSum);
3053                     artifactDefinition.setEsId(artifactDefinition.getUniqueId());
3054                     log.trace("No real update done in payload for {} artifact, updating payloadUpdateDate {}", artifactDefinition.getArtifactType(),
3055                         artifactDefinition.getEsId());
3056                     updateArifactDefinitionStatus = artifactToscaOperation
3057                         .updateArtifactOnResource(artifactDefinition, component, artifactDefinition.getUniqueId(), componentType.getNodeType(),
3058                             instanceId, true);
3059                     log.trace("Update Payload {}", artifactDefinition.getEsId());
3060                 }
3061                 if (updateArifactDefinitionStatus.isLeft()) {
3062                     artifactDefinition = updateArifactDefinitionStatus.left().value();
3063                     artifactData.setId(artifactDefinition.getUniqueId());
3064                     CassandraOperationStatus saveArtifactStatus = artifactCassandraDao.saveArtifact(artifactData);
3065                     if (saveArtifactStatus == CassandraOperationStatus.OK) {
3066                         if (!inTransaction) {
3067                             janusGraphDao.commit();
3068                         }
3069                         log.debug("Artifact Saved In cassandra {}", artifactData.getId());
3070                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
3071                         handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition,
3072                             artifactDefinition.getUniqueId(), artifactDefinition.getUniqueId(), responseFormat, ComponentTypeEnum.RESOURCE_INSTANCE,
3073                             resourceInstanceName);
3074                     } else {
3075                         if (!inTransaction) {
3076                             janusGraphDao.rollback();
3077                         }
3078                         log.info("Failed to save artifact {}.", artifactData.getId());
3079                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
3080                         handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition,
3081                             artifactDefinition.getUniqueId(), artifactDefinition.getUniqueId(), responseFormat, ComponentTypeEnum.RESOURCE_INSTANCE,
3082                             resourceInstanceName);
3083                         return Either.right(responseFormat);
3084                     }
3085                 } else {
3086                     ResponseFormat responseFormat = componentsUtils
3087                         .getResponseFormatByArtifactId(componentsUtils.convertFromStorageResponse(updateArifactDefinitionStatus.right().value()),
3088                             artifactDefinition.getArtifactDisplayName());
3089                     log.debug("Failed To update artifact {}", artifactData.getId());
3090                     handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition,
3091                         artifactDefinition.getUniqueId(), artifactDefinition.getUniqueId(), responseFormat, ComponentTypeEnum.RESOURCE_INSTANCE,
3092                         resourceInstanceName);
3093                     return Either.right(responseFormat);
3094                 }
3095             } finally {
3096                 if (shouldLock) {
3097                     graphLockOperation.unlockComponent(component.getUniqueId(), component.getComponentType().getNodeType());
3098                 }
3099             }
3100         }
3101         return Either.left(artifactDefinition);
3102     }
3103
3104     public Map<String, Object> buildJsonForUpdateArtifact(ArtifactDefinition artifactDef, ArtifactGroupTypeEnum artifactGroupType,
3105                                                           List<ArtifactTemplateInfo> updatedRequiredArtifacts) {
3106         return this
3107             .buildJsonForUpdateArtifact(artifactDef.getUniqueId(), artifactDef.getArtifactName(), artifactDef.getArtifactType(), artifactGroupType,
3108                 artifactDef.getArtifactLabel(), artifactDef.getArtifactDisplayName(), artifactDef.getDescription(), artifactDef.getPayloadData(),
3109                 updatedRequiredArtifacts, artifactDef.getListHeatParameters());
3110     }
3111
3112     public Map<String, Object> buildJsonForUpdateArtifact(String artifactId, String artifactName, String artifactType,
3113                                                           ArtifactGroupTypeEnum artifactGroupType, String label, String displayName,
3114                                                           String description, byte[] artifactContent,
3115                                                           List<ArtifactTemplateInfo> updatedRequiredArtifacts,
3116                                                           List<HeatParameterDefinition> heatParameters) {
3117         Map<String, Object> json = new HashMap<>();
3118         if (artifactId != null && !artifactId.isEmpty()) {
3119             json.put(Constants.ARTIFACT_ID, artifactId);
3120         }
3121         json.put(Constants.ARTIFACT_NAME, artifactName);
3122         json.put(Constants.ARTIFACT_TYPE, artifactType);
3123         json.put(Constants.ARTIFACT_DESCRIPTION, description);
3124         if (artifactContent != null) {
3125             log.debug("payload is encoded. perform decode");
3126             String encodedPayload = Base64.encodeBase64String(artifactContent);
3127             json.put(Constants.ARTIFACT_PAYLOAD_DATA, encodedPayload);
3128         }
3129         json.put(Constants.ARTIFACT_DISPLAY_NAME, displayName);
3130         json.put(Constants.ARTIFACT_LABEL, label);
3131         json.put(Constants.ARTIFACT_GROUP_TYPE, artifactGroupType.getType());
3132         json.put(Constants.REQUIRED_ARTIFACTS, (updatedRequiredArtifacts == null || updatedRequiredArtifacts.isEmpty()) ? new ArrayList<>()
3133             : updatedRequiredArtifacts.stream().filter(
3134                 e -> e.getType().equals(ArtifactTypeEnum.HEAT_ARTIFACT.getType()) || e.getType().equals(ArtifactTypeEnum.HEAT_NESTED.getType()))
3135                 .map(ArtifactTemplateInfo::getFileName).collect(Collectors.toList()));
3136         json.put(Constants.ARTIFACT_HEAT_PARAMS, (heatParameters == null || heatParameters.isEmpty()) ? new ArrayList<>() : heatParameters);
3137         return json;
3138     }
3139
3140     public Either<ArtifactDefinition, Operation> updateResourceInstanceArtifactNoContent(String resourceId, Component containerComponent, User user,
3141                                                                                          Map<String, Object> json, ArtifactOperationInfo operation,
3142                                                                                          ArtifactDefinition artifactInfo) {
3143         String jsonStr = gson.toJson(json);
3144         ArtifactDefinition artifactDefinitionFromJson =
3145             artifactInfo == null ? RepresentationUtils.convertJsonToArtifactDefinition(jsonStr, ArtifactDefinition.class, false) : artifactInfo;
3146         String artifactUniqueId = artifactDefinitionFromJson == null ? null : artifactDefinitionFromJson.getUniqueId();
3147         Either<ArtifactDefinition, Operation> uploadArtifactToService = validateAndHandleArtifact(resourceId, ComponentTypeEnum.RESOURCE_INSTANCE,
3148             operation, artifactUniqueId, artifactDefinitionFromJson, null, jsonStr, null, null, user, containerComponent, false, false, true);
3149         return Either.left(uploadArtifactToService.left().value());
3150     }
3151
3152     private Either<ArtifactDefinition, Operation> handleUpdateHeatEnvAndHeatMeta(String componentId, ArtifactDefinition artifactInfo,
3153                                                                                  AuditingActionEnum auditingAction, String artifactId, User user,
3154                                                                                  ComponentTypeEnum componentType, Component parent, String originData,
3155                                                                                  String origMd5, ArtifactOperationInfo operation) {
3156         if (origMd5 != null) {
3157             validateMd5(origMd5, originData, artifactInfo.getPayloadData(), operation);
3158             if (ArrayUtils.isNotEmpty(artifactInfo.getPayloadData())) {
3159                 validateDeploymentArtifact(artifactInfo, parent);
3160                 handlePayload(artifactInfo, isArtifactMetadataUpdate(auditingAction));
3161             } else { // duplicate
3162                 throw new ByActionStatusComponentException(ActionStatus.MISSING_DATA, ARTIFACT_PAYLOAD);
3163             }
3164         }
3165         return updateHeatEnvParamsAndMetadata(componentId, artifactId, artifactInfo, user, auditingAction, parent, componentType, origMd5);
3166     }
3167
3168     private Either<ArtifactDefinition, Operation> updateHeatEnvParamsAndMetadata(String componentId, String artifactId,
3169                                                                                  ArtifactDefinition artifactInfo, User user,
3170                                                                                  AuditingActionEnum auditingAction, Component parent,
3171                                                                                  ComponentTypeEnum componentType, String origMd5) {
3172         Either<ComponentInstance, ResponseFormat> getRI = getRIFromComponent(parent, componentId, artifactId, auditingAction, user);
3173         if (getRI.isRight()) {
3174             throw new ByResponseFormatComponentException(getRI.right().value());
3175         }
3176         ComponentInstance ri = getRI.left().value();
3177         Either<ArtifactDefinition, ResponseFormat> getArtifactRes = getArtifactFromRI(parent, ri, componentId, artifactId, auditingAction, user);
3178         if (getArtifactRes.isRight()) {
3179             throw new ByResponseFormatComponentException(getArtifactRes.right().value());
3180         }
3181         ArtifactDefinition currArtifact = getArtifactRes.left().value();
3182         if (currArtifact.getArtifactType().equals(ArtifactTypeEnum.HEAT.getType()) || currArtifact.getArtifactType()
3183             .equals(ArtifactTypeEnum.HEAT_VOL.getType()) || currArtifact.getArtifactType().equals(ArtifactTypeEnum.HEAT_NET.getType())) {
3184             throw new ByActionStatusComponentException(ActionStatus.RESTRICTED_OPERATION);
3185         }
3186         List<HeatParameterDefinition> currentHeatEnvParams = currArtifact.getListHeatParameters();
3187         List<HeatParameterDefinition> updatedHeatEnvParams = artifactInfo.getListHeatParameters();
3188         // upload
3189         if (origMd5 != null) {
3190             Either<List<HeatParameterDefinition>, ResponseFormat> uploadParamsValidationResult = validateUploadParamsFromEnvFile(auditingAction,
3191                 parent, user, artifactInfo, artifactId, componentType, ri.getName(), currentHeatEnvParams, updatedHeatEnvParams,
3192                 currArtifact.getArtifactName());
3193             if (uploadParamsValidationResult.isRight()) {
3194                 throw new ByResponseFormatComponentException(uploadParamsValidationResult.right().value());
3195             }
3196             artifactInfo.setListHeatParameters(updatedHeatEnvParams);
3197         }
3198         Either<ArtifactDefinition, ResponseFormat> validateAndConvertHeatParamers = validateAndConvertHeatParameters(artifactInfo,
3199             ArtifactTypeEnum.HEAT_ENV.getType());
3200         if (validateAndConvertHeatParamers.isRight()) {
3201             throw new ByResponseFormatComponentException(validateAndConvertHeatParamers.right().value());
3202         }
3203         if (updatedHeatEnvParams != null && !updatedHeatEnvParams.isEmpty()) {
3204             // fill reduced heat env parameters List for updating
3205             boolean updateRequired = replaceCurrHeatValueWithUpdatedValue(currentHeatEnvParams, updatedHeatEnvParams);
3206             if (updateRequired) {
3207                 currArtifact.setHeatParamsUpdateDate(System.currentTimeMillis());
3208                 currArtifact.setListHeatParameters(currentHeatEnvParams);
3209                 Either<ArtifactDefinition, StorageOperationStatus> updateArtifactRes = artifactToscaOperation
3210                     .updateArtifactOnResource(currArtifact, parent, currArtifact.getUniqueId(), componentType.getNodeType(), componentId, true);
3211                 if (updateArtifactRes.isRight()) {
3212                     log.debug("Failed to update artifact on graph  - {}", artifactId);
3213                     throw new StorageException(updateArtifactRes.right().value());
3214                 }
3215                 StorageOperationStatus error = generateCustomizationUUIDOnGroupInstance(ri, updateArtifactRes.left().value().getUniqueId(),
3216                     parent.getUniqueId());
3217                 if (error != StorageOperationStatus.OK) {
3218                     throw new StorageException(error);
3219                 }
3220             }
3221         }
3222         updateHeatMetaDataIfNeeded(componentId, user, auditingAction, componentType, parent, ri, artifactInfo);
3223         StorageOperationStatus error = generateCustomizationUUIDOnInstance(parent.getUniqueId(), ri.getUniqueId(), componentType);
3224         if (error != StorageOperationStatus.OK) {
3225             throw new StorageException(error);
3226         }
3227         return Either.left(currArtifact);
3228     }
3229
3230     private void updateHeatMetaDataIfNeeded(String componentId, User user, AuditingActionEnum auditingAction, ComponentTypeEnum componentType,
3231                                             Component parent, ComponentInstance resourceInstance, ArtifactDefinition updatedHeatEnvArtifact) {
3232         String heatArtifactId = updatedHeatEnvArtifact.getGeneratedFromId();
3233         Either<ArtifactDefinition, ResponseFormat> getArtifactRes = getArtifactFromRI(parent, resourceInstance, componentId, heatArtifactId,
3234             auditingAction, user);
3235         if (getArtifactRes.isRight()) {
3236             throw new ByResponseFormatComponentException(getArtifactRes.right().value());
3237         }
3238         ArtifactDefinition heatArtifactToUpdate = getArtifactRes.left().value();
3239         if (isUpdateHeatMetaDataNeeded(updatedHeatEnvArtifact, heatArtifactToUpdate)) {
3240             validateHeatMetaData(updatedHeatEnvArtifact);
3241             updateHeatMetadataFromHeatEnv(updatedHeatEnvArtifact, heatArtifactToUpdate);
3242             Either<ArtifactDefinition, StorageOperationStatus> updateArtifactRes = artifactToscaOperation
3243                 .updateArtifactOnResource(heatArtifactToUpdate, parent, heatArtifactToUpdate.getUniqueId(), componentType.getNodeType(), componentId,
3244                     false);
3245             if (updateArtifactRes.isRight()) {
3246                 log.debug("Failed to update artifact on graph  - {}", heatArtifactId);
3247                 throw new StorageException(updateArtifactRes.right().value());
3248             }
3249             ArtifactDefinition artifactDefinition = updateArtifactRes.left().value();
3250             updateGeneratedIdInHeatEnvOnInstance(resourceInstance, parent, heatArtifactId, heatArtifactToUpdate, artifactDefinition,
3251                 componentType.getNodeType());
3252             StorageOperationStatus error = generateCustomizationUUIDOnGroupInstance(resourceInstance, artifactDefinition.getUniqueId(),
3253                 parent.getUniqueId());
3254             if (error != StorageOperationStatus.OK) {
3255                 throw new StorageException(error);
3256             }
3257         }
3258     }
3259
3260     private void validateHeatMetaData(ArtifactDefinition updatedHeatEnv) {
3261         Integer maxMinutes = ConfigurationManager.getConfigurationManager().getConfiguration().getHeatArtifactDeploymentTimeout().getMaxMinutes();
3262         Integer minMinutes = ConfigurationManager.getConfigurationManager().getConfiguration().getHeatArtifactDeploymentTimeout().getMinMinutes();
3263         Integer updateTimeout = updatedHeatEnv.getTimeout();
3264         if (updateTimeout > maxMinutes || updateTimeout < minMinutes) {
3265             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_INVALID_TIMEOUT);
3266         }
3267     }
3268
3269     private boolean isUpdateHeatMetaDataNeeded(ArtifactDefinition updatedHeatEnv, ArtifactDefinition origHeat) {
3270         // currently only timeout metadata can be updated
3271         return !origHeat.getTimeout().equals(updatedHeatEnv.getTimeout());
3272     }
3273
3274     private void updateHeatMetadataFromHeatEnv(ArtifactDefinition updatedHeatEnv, ArtifactDefinition origHeat) {
3275         // currently only timeout metadata can be updated
3276         origHeat.setTimeout(updatedHeatEnv.getTimeout());
3277     }
3278
3279     private boolean replaceCurrHeatValueWithUpdatedValue(List<HeatParameterDefinition> currentHeatEnvParams,
3280                                                          List<HeatParameterDefinition> updatedHeatEnvParams) {
3281         boolean isUpdate = false;
3282         List<String> currentParamsNames = currentHeatEnvParams.stream().map(x -> x.getName()).collect(Collectors.toList());
3283         for (HeatParameterDefinition heatEnvParam : updatedHeatEnvParams) {
3284             String paramName = heatEnvParam.getName();
3285             validateParamName(paramName, currentParamsNames);
3286             for (HeatParameterDefinition currHeatParam : currentHeatEnvParams) {
3287                 if (paramName.equalsIgnoreCase(currHeatParam.getName())) {
3288                     String updatedParamValue = heatEnvParam.getCurrentValue();
3289                     if (!Objects.equals(updatedParamValue, currHeatParam.getCurrentValue())) {
3290                         currHeatParam.setCurrentValue(updatedParamValue);
3291                         isUpdate = true;
3292                     }
3293                 }
3294             }
3295         }
3296         return isUpdate;
3297     }
3298
3299     private void validateParamName(String paramName, List<String> heatParamsNames) {
3300         if (!heatParamsNames.contains(paramName)) {
3301             throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, paramName);
3302         }
3303     }
3304
3305     private Either<ArtifactDefinition, Operation> updateHeatParams(String componentId, ArtifactDefinition artifactEnvInfo,
3306                                                                    AuditingActionEnum auditingAction, Component parent,
3307                                                                    ComponentTypeEnum componentType, ArtifactDefinition currHeatArtifact,
3308                                                                    boolean needToUpdateGroup) {
3309         Either<ArtifactDefinition, Operation> insideEither = null;
3310         String currentHeatId = currHeatArtifact.getUniqueId();
3311         String esArtifactId = currHeatArtifact.getEsId();
3312         Either<DAOArtifactData, CassandraOperationStatus> artifactFromES = artifactCassandraDao.getArtifact(esArtifactId);
3313         if (artifactFromES.isRight()) {
3314             StorageOperationStatus storageResponse = DaoStatusConverter.convertCassandraStatusToStorageStatus(artifactFromES.right().value());
3315             throw new StorageException(storageResponse, currHeatArtifact.getArtifactDisplayName());
3316         }
3317         DAOArtifactData DAOArtifactData = artifactFromES.left().value();
3318         ArtifactDefinition updatedHeatArt = currHeatArtifact;
3319         List<HeatParameterDefinition> updatedHeatEnvParams = artifactEnvInfo.getListHeatParameters();
3320         List<HeatParameterDefinition> currentHeatEnvParams = currHeatArtifact.getListHeatParameters();
3321         List<HeatParameterDefinition> newHeatEnvParams = new ArrayList<>();
3322         if (CollectionUtils.isNotEmpty(updatedHeatEnvParams) && CollectionUtils.isNotEmpty(currentHeatEnvParams)) {
3323             //TODO: improve complexity - currently N^2
3324             String paramName;
3325             for (HeatParameterDefinition heatEnvParam : updatedHeatEnvParams) {
3326                 paramName = heatEnvParam.getName();
3327                 for (HeatParameterDefinition currHeatParam : currentHeatEnvParams) {
3328                     if (paramName.equalsIgnoreCase(currHeatParam.getName())) {
3329                         String updatedParamValue = heatEnvParam.getCurrentValue();
3330                         if (updatedParamValue == null) {
3331                             updatedParamValue = heatEnvParam.getDefaultValue();
3332                         }
3333                         HeatParameterType paramType = HeatParameterType.isValidType(currHeatParam.getType());
3334                         if (!paramType.getValidator().isValid(updatedParamValue, null)) {
3335                             throw new ByActionStatusComponentException(ActionStatus.INVALID_HEAT_PARAMETER_VALUE, ArtifactTypeEnum.HEAT_ENV.getType(),
3336                                 paramType.getType(), paramName);
3337                         }
3338                         currHeatParam.setCurrentValue(paramType.getConverter().convert(updatedParamValue, null, null));
3339                         newHeatEnvParams.add(currHeatParam);
3340                         break;
3341                     }
3342                 }
3343             }
3344             if (!newHeatEnvParams.isEmpty()) {
3345                 currHeatArtifact.setListHeatParameters(currentHeatEnvParams);
3346                 Either<ArtifactDefinition, StorageOperationStatus> operationStatus = artifactToscaOperation
3347                     .updateArtifactOnResource(currHeatArtifact, parent, currHeatArtifact.getUniqueId(), componentType.getNodeType(), componentId,
3348                         true);
3349                 if (operationStatus.isRight()) {
3350                     log.debug("Failed to update artifact on graph  - {}", currHeatArtifact.getUniqueId());
3351                     throw new StorageException(operationStatus.right().value());
3352                 }
3353                 updatedHeatArt = operationStatus.left().value();
3354                 if (!updatedHeatArt.getDuplicated() || DAOArtifactData.getId() == null) {
3355                     DAOArtifactData.setId(updatedHeatArt.getEsId());
3356                 }
3357                 saveArtifactInCassandra(DAOArtifactData, parent, artifactEnvInfo, currentHeatId, updatedHeatArt.getUniqueId(), auditingAction,
3358                     componentType);
3359                 insideEither = Either.left(updatedHeatArt);
3360             }
3361         }
3362         Either<ArtifactDefinition, StorageOperationStatus> updateHeatEnvArtifact;
3363         if (!currentHeatId.equals(updatedHeatArt.getUniqueId())) {
3364             artifactEnvInfo.setArtifactChecksum(null);
3365             updateHeatEnvArtifact = artifactToscaOperation
3366                 .updateHeatEnvArtifact(parent, artifactEnvInfo, currentHeatId, updatedHeatArt.getUniqueId(), componentType.getNodeType(),
3367                     componentId);
3368         } else {
3369             //TODO Andrey check if componentId = parent.getUniqeId
3370             updateHeatEnvArtifact = artifactToscaOperation.updateHeatEnvPlaceholder(artifactEnvInfo, parent, componentType.getNodeType());
3371         }
3372         if (needToUpdateGroup && updateHeatEnvArtifact.isLeft()) {
3373             ActionStatus result = updateGroupForHeat(currHeatArtifact, updatedHeatArt, artifactEnvInfo, updateHeatEnvArtifact.left().value(), parent);
3374             if (result != ActionStatus.OK) {
3375                 throw new ByActionStatusComponentException(result);
3376             }
3377         }
3378         if (updatedHeatEnvParams.isEmpty()) {
3379             throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML, currHeatArtifact.getArtifactName());
3380         }
3381         return insideEither;
3382     }
3383
3384     private StorageOperationStatus generateCustomizationUUIDOnGroupInstance(ComponentInstance ri, String artifactId, String componentId) {
3385         StorageOperationStatus error = StorageOperationStatus.OK;
3386         log.debug("Need to re-generate  customization UUID for group instance on component instance  {}", ri.getUniqueId());
3387         List<GroupInstance> groupsInstances = ri.getGroupInstances();
3388         List<String> groupInstancesId = null;
3389         if (groupsInstances != null && !groupsInstances.isEmpty()) {
3390             groupInstancesId = groupsInstances.stream()
3391                 .filter(p -> p.getGroupInstanceArtifacts() != null && p.getGroupInstanceArtifacts().contains(artifactId))
3392                 .map(GroupInstanceDataDefinition::getUniqueId).collect(Collectors.toList());
3393         }
3394         if (groupInstancesId != null && !groupInstancesId.isEmpty()) {
3395             toscaOperationFacade.generateCustomizationUUIDOnInstanceGroup(componentId, ri.getUniqueId(), groupInstancesId);
3396         }
3397         return error;
3398     }
3399
3400     public Either<List<HeatParameterDefinition>, ResponseFormat> validateUploadParamsFromEnvFile(AuditingActionEnum auditingAction, Component parent,
3401                                                                                                  User user, ArtifactDefinition artifactInfo,
3402                                                                                                  String artifactId, ComponentTypeEnum componentType,
3403                                                                                                  String riName,
3404                                                                                                  List<HeatParameterDefinition> currentHeatEnvParams,
3405                                                                                                  List<HeatParameterDefinition> updatedHeatEnvParams,
3406                                                                                                  String currArtifactName) {
3407         if (updatedHeatEnvParams == null || updatedHeatEnvParams.isEmpty()) {
3408             ResponseFormat responseFormat = componentsUtils
3409                 .getResponseFormat(ActionStatus.INVALID_DEPLOYMENT_ARTIFACT_HEAT, artifactInfo.getArtifactName(), currArtifactName);
3410             handleAuditing(auditingAction, parent, parent.getUniqueId(), user, artifactInfo, null, artifactId, responseFormat, componentType, riName);
3411             return Either.right(responseFormat);
3412         }
3413         for (HeatParameterDefinition uploadedHeatParam : updatedHeatEnvParams) {
3414             String paramName = uploadedHeatParam.getName();
3415             boolean isExistsInHeat = false;
3416             for (HeatParameterDefinition currHeatParam : currentHeatEnvParams) {
3417                 if (paramName.equalsIgnoreCase(currHeatParam.getName())) {
3418                     isExistsInHeat = true;
3419                     uploadedHeatParam.setType(currHeatParam.getType());
3420                     uploadedHeatParam.setCurrentValue(uploadedHeatParam.getDefaultValue());
3421                     uploadedHeatParam.setDefaultValue(currHeatParam.getDefaultValue());
3422                     uploadedHeatParam.setUniqueId(currHeatParam.getUniqueId());
3423                     break;
3424                 }
3425             }
3426             if (!isExistsInHeat) {
3427                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISMATCH_HEAT_VS_HEAT_ENV, currArtifactName);
3428                 handleAuditing(auditingAction, parent, parent.getUniqueId(), user, artifactInfo, null, artifactId, responseFormat, componentType,
3429                     riName);
3430                 return Either.right(responseFormat);
3431             }
3432         }
3433         return Either.left(updatedHeatEnvParams);
3434     }
3435
3436     private Either<ComponentInstance, ResponseFormat> getRIFromComponent(Component component, String riID, String artifactId,
3437                                                                          AuditingActionEnum auditingAction, User user) {
3438         ResponseFormat responseFormat = null;
3439         List<ComponentInstance> ris = component.getComponentInstances();
3440         for (ComponentInstance ri : ris) {
3441             if (riID.equals(ri.getUniqueId())) {
3442                 return Either.left(ri);
3443             }
3444         }
3445         responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE, riID);
3446         log.debug("Resource Instance not found, resourceInstanceId {}", riID);
3447         handleAuditing(auditingAction, null, riID, user, null, null, artifactId, responseFormat, ComponentTypeEnum.RESOURCE_INSTANCE, null);
3448         return Either.right(responseFormat);
3449     }
3450
3451     private Either<ArtifactDefinition, ResponseFormat> getArtifactFromRI(Component component, ComponentInstance ri, String riID, String artifactId,
3452                                                                          AuditingActionEnum auditingAction, User user) {
3453         ResponseFormat responseFormat = null;
3454         Map<String, ArtifactDefinition> rtifactsMap = ri.getDeploymentArtifacts();
3455         for (ArtifactDefinition artifact : rtifactsMap.values()) {
3456             if (artifactId.equals(artifact.getUniqueId())) {
3457                 return Either.left(artifact);
3458             }
3459         }
3460         responseFormat = componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND, riID, component.getUniqueId());
3461         handleAuditing(auditingAction, component, riID, user, null, null, artifactId, responseFormat, ComponentTypeEnum.RESOURCE_INSTANCE,
3462             ri.getName());
3463         return Either.right(responseFormat);
3464     }
3465
3466     public ArtifactDefinition extractArtifactDefinition(Either<ArtifactDefinition, Operation> eitherArtifact) {
3467         ArtifactDefinition ret;
3468         if (eitherArtifact.isLeft()) {
3469             ret = eitherArtifact.left().value();
3470         } else {
3471             ret = eitherArtifact.right().value().getImplementationArtifact();
3472         }
3473         return ret;
3474     }
3475
3476     public byte[] downloadComponentArtifactByUUIDs(ComponentTypeEnum componentType, String componentUuid, String artifactUUID,
3477                                                    ResourceCommonInfo resourceCommonInfo) {
3478         Component component = getComponentByUuid(componentType, componentUuid);
3479         resourceCommonInfo.setResourceName(component.getName());
3480         return downloadArtifact(component.getAllArtifacts(), artifactUUID, component.getName());
3481     }
3482
3483     /**
3484      * downloads an artifact of resource instance of component by UUIDs
3485      *
3486      * @param componentType
3487      * @param componentUuid
3488      * @param resourceInstanceName
3489      * @param artifactUUID
3490      * @return
3491      */
3492     public byte[] downloadResourceInstanceArtifactByUUIDs(ComponentTypeEnum componentType, String componentUuid, String resourceInstanceName,
3493                                                           String artifactUUID) {
3494         ComponentInstance resourceInstance = getRelatedComponentInstance(componentType, componentUuid, resourceInstanceName);
3495         if (resourceInstance != null) {
3496             return downloadArtifact(resourceInstance.getDeploymentArtifacts(), artifactUUID, resourceInstance.getName());
3497         } else {
3498             return downloadArtifact(null, artifactUUID, null);
3499         }
3500     }
3501
3502     /**
3503      * uploads an artifact to a component by UUID
3504      *
3505      * @param data
3506      * @param request
3507      * @param componentType
3508      * @param componentUuid
3509      * @param resourceCommonInfo
3510      * @param operation
3511      * @return
3512      */
3513     public ArtifactDefinition uploadArtifactToComponentByUUID(String data, HttpServletRequest request, ComponentTypeEnum componentType,
3514                                                               String componentUuid, ResourceCommonInfo resourceCommonInfo,
3515                                                               ArtifactOperationInfo operation) {
3516         Either<ArtifactDefinition, Operation> actionResult;
3517         Component component;
3518         String componentId;
3519         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinition(data, ArtifactDefinition.class, false);
3520         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3521         String userId = request.getHeader(Constants.USER_ID_HEADER);
3522         Either<ComponentMetadataData, ActionStatus> getComponentRes = fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
3523         ComponentMetadataDataDefinition componentMetadataDataDefinition = getComponentRes.left().value().getMetadataDataDefinition();
3524         componentId = componentMetadataDataDefinition.getUniqueId();
3525         String componentName = componentMetadataDataDefinition.getName();
3526         if (!componentMetadataDataDefinition.getState().equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3527             component = checkoutParentComponent(componentType, componentId, userId);
3528             if (component != null) {
3529                 componentId = component.getUniqueId();
3530                 componentName = component.getName();
3531             }
3532         }
3533         resourceCommonInfo.setResourceName(componentName);
3534         actionResult = handleArtifactRequest(componentId, userId, componentType, operation, null, artifactInfo, origMd5, data, null, null, null,
3535             null);
3536         return actionResult.left().value();
3537     }
3538
3539     /**
3540      * upload an artifact to a resource instance by UUID
3541      *
3542      * @param data
3543      * @param request
3544      * @param componentType
3545      * @param componentUuid
3546      * @param resourceInstanceName
3547      * @param operation
3548      * @return
3549      */
3550     public ArtifactDefinition uploadArtifactToRiByUUID(String data, HttpServletRequest request, ComponentTypeEnum componentType, String componentUuid,
3551                                                        String resourceInstanceName, ArtifactOperationInfo operation) {
3552         Either<ArtifactDefinition, Operation> actionResult;
3553         Component component = null;
3554         String componentInstanceId;
3555         String componentId;
3556         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3557         String userId = request.getHeader(Constants.USER_ID_HEADER);
3558         ImmutablePair<Component, ComponentInstance> componentRiPair = null;
3559         Either<ComponentMetadataData, ActionStatus> getComponentRes = fetchLatestComponentMetadataOrThrow(componentType, componentUuid,
3560             resourceInstanceName);
3561         if (!getComponentRes.left().value().getMetadataDataDefinition().getState().equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3562             component = checkoutParentComponent(componentType, getComponentRes.left().value().getMetadataDataDefinition().getUniqueId(), userId);
3563         }
3564         if (component == null) {
3565             componentRiPair = getRelatedComponentComponentInstance(componentType, componentUuid, resourceInstanceName);
3566         } else {
3567             componentRiPair = getRelatedComponentComponentInstance(component, resourceInstanceName);
3568         }
3569         componentInstanceId = componentRiPair.getRight().getUniqueId();
3570         componentId = componentRiPair.getLeft().getUniqueId();
3571         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinition(data, ArtifactDefinition.class, false);
3572         actionResult = handleArtifactRequest(componentInstanceId, userId, ComponentTypeEnum.RESOURCE_INSTANCE, operation, null, artifactInfo, origMd5,
3573             data, null, null, componentId, ComponentTypeEnum.findParamByType(componentType));
3574         return actionResult.left().value();
3575     }
3576
3577     /**
3578      * updates an artifact on a component by UUID
3579      *
3580      * @param data
3581      * @param request
3582      * @param componentType
3583      * @param componentUuid
3584      * @param artifactUUID
3585      * @param resourceCommonInfo
3586      * @param operation          TODO
3587      * @return
3588      */
3589     public ArtifactDefinition updateArtifactOnComponentByUUID(String data, HttpServletRequest request, ComponentTypeEnum componentType,
3590                                                               String componentUuid, String artifactUUID, ResourceCommonInfo resourceCommonInfo,
3591                                                               ArtifactOperationInfo operation) {
3592         Either<ArtifactDefinition, Operation> actionResult;
3593         Component component;
3594         String componentId;
3595         String artifactId;
3596         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinitionForUpdate(data, ArtifactDefinition.class);
3597         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3598         String userId = request.getHeader(Constants.USER_ID_HEADER);
3599         Either<ComponentMetadataData, ActionStatus> getComponentRes = fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
3600         componentId = getComponentRes.left().value().getMetadataDataDefinition().getUniqueId();
3601         String componentName = getComponentRes.left().value().getMetadataDataDefinition().getName();
3602         if (!getComponentRes.left().value().getMetadataDataDefinition().getState().equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3603             component = checkoutParentComponent(componentType, componentId, userId);
3604             if (component != null) {
3605                 componentId = component.getUniqueId();
3606                 componentName = component.getName();
3607             }
3608         }
3609         resourceCommonInfo.setResourceName(componentName);
3610         artifactId = getLatestParentArtifactDataIdByArtifactUUID(artifactUUID, componentId, componentType);
3611         actionResult = handleArtifactRequest(componentId, userId, componentType, operation, artifactId, artifactInfo, origMd5, data, null, null, null,
3612             null);
3613         if (actionResult.isRight()) {
3614             log.debug(FAILED_UPLOAD_ARTIFACT_TO_COMPONENT, componentType, componentUuid, actionResult.right().value());
3615         }
3616         return actionResult.left().value();
3617     }
3618
3619     /**
3620      * updates an artifact on a resource instance by UUID
3621      *
3622      * @param data
3623      * @param request
3624      * @param componentType
3625      * @param componentUuid
3626      * @param resourceInstanceName
3627      * @param artifactUUID
3628      * @param operation            TODO
3629      * @return
3630      */
3631     public ArtifactDefinition updateArtifactOnRiByUUID(String data, HttpServletRequest request, ComponentTypeEnum componentType, String componentUuid,
3632                                                        String resourceInstanceName, String artifactUUID, ArtifactOperationInfo operation) {
3633         Either<ArtifactDefinition, Operation> actionResult;
3634         Component component = null;
3635         String componentInstanceId;
3636         String componentId;
3637         String artifactId;
3638         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3639         String userId = request.getHeader(Constants.USER_ID_HEADER);
3640         ImmutablePair<Component, ComponentInstance> componentRiPair = null;
3641         Either<ComponentMetadataData, ActionStatus> getComponentRes = fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
3642         if (!getComponentRes.left().value().getMetadataDataDefinition().getState().equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3643             component = checkoutParentComponent(componentType, getComponentRes.left().value().getMetadataDataDefinition().getUniqueId(), userId);
3644         }
3645         if (component == null) {
3646             componentRiPair = getRelatedComponentComponentInstance(componentType, componentUuid, resourceInstanceName);
3647         } else {
3648             componentRiPair = getRelatedComponentComponentInstance(component, resourceInstanceName);
3649         }
3650         componentInstanceId = componentRiPair.getRight().getUniqueId();
3651         componentId = componentRiPair.getLeft().getUniqueId();
3652         artifactId = findArtifactId(componentRiPair.getRight(), artifactUUID);
3653         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinition(data, ArtifactDefinition.class, false);
3654         actionResult = handleArtifactRequest(componentInstanceId, userId, ComponentTypeEnum.RESOURCE_INSTANCE, operation, artifactId, artifactInfo,
3655             origMd5, data, null, null, componentId, ComponentTypeEnum.findParamByType(componentType));
3656         return actionResult.left().value();
3657     }
3658
3659     private Either<ArtifactDefinition, ResponseFormat> updateOperationArtifact(String componentId, String interfaceType, String operationUuid,
3660                                                                                ArtifactDefinition artifactInfo) {
3661         Either<Component, StorageOperationStatus> componentStorageOperationStatusEither = toscaOperationFacade.getToscaElement(componentId);
3662         if (componentStorageOperationStatusEither.isRight()) {
3663             StorageOperationStatus errorStatus = componentStorageOperationStatusEither.right().value();
3664             log.debug("Failed to fetch resource information by resource id, error {}", errorStatus);
3665             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
3666         }
3667         Component storedComponent = componentStorageOperationStatusEither.left().value();
3668         Optional<InterfaceDefinition> optionalInterface = InterfaceOperationUtils
3669             .getInterfaceDefinitionFromComponentByInterfaceType(storedComponent, interfaceType);
3670         if (!optionalInterface.isPresent()) {
3671             log.debug("Failed to get resource interface for resource Id {}", componentId);
3672             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceType));
3673         }
3674         //fetch the operation from storage
3675         InterfaceDefinition gotInterface = optionalInterface.get();
3676         Map<String, Operation> operationsMap = gotInterface.getOperationsMap();
3677         Optional<Operation> optionalOperation = operationsMap.values().stream().filter(o -> o.getUniqueId().equals(operationUuid)).findFirst();
3678         if (!optionalOperation.isPresent()) {
3679             log.debug("Failed to get resource interface operation for resource Id {} and operationId {}", componentId, operationUuid);
3680             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, componentId);
3681             return Either.right(responseFormat);
3682         }
3683         Operation operation = optionalOperation.get();
3684         ArtifactDefinition implementationArtifact = operation.getImplementationArtifact();
3685         implementationArtifact.setArtifactUUID(artifactInfo.getArtifactUUID());
3686         implementationArtifact.setUniqueId(artifactInfo.getUniqueId());
3687         implementationArtifact.setArtifactName(artifactInfo.getArtifactName());
3688         implementationArtifact.setDescription(artifactInfo.getDescription());
3689         implementationArtifact.setArtifactType(artifactInfo.getArtifactType());
3690         implementationArtifact.setArtifactLabel(artifactInfo.getArtifactLabel());
3691         implementationArtifact.setArtifactDisplayName(artifactInfo.getArtifactDisplayName());
3692         implementationArtifact.setEsId(artifactInfo.getEsId());
3693         operation.setImplementation(implementationArtifact);
3694         gotInterface.setOperationsMap(operationsMap);
3695         Either<List<InterfaceDefinition>, StorageOperationStatus> interfaceDefinitionStorageOperationStatusEither = interfaceOperation
3696             .updateInterfaces(storedComponent.getUniqueId(), Collections.singletonList(gotInterface));
3697         if (interfaceDefinitionStorageOperationStatusEither.isRight()) {
3698             StorageOperationStatus storageOperationStatus = interfaceDefinitionStorageOperationStatusEither.right().value();
3699             ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForDataType(storageOperationStatus);
3700             return Either.right(componentsUtils.getResponseFormat(actionStatus));
3701         }
3702         return Either.left(artifactInfo);
3703     }
3704
3705     /**
3706      * updates an artifact on a component by UUID
3707      *
3708      * @param data
3709      * @param request
3710      * @param componentType
3711      * @param componentUuid
3712      * @param artifactUUID
3713      * @param operation
3714      * @return
3715      */
3716     public Either<ArtifactDefinition, ResponseFormat> updateArtifactOnInterfaceOperationByResourceUUID(String data, HttpServletRequest request,
3717                                                                                                        ComponentTypeEnum componentType,
3718                                                                                                        String componentUuid, String interfaceUUID,
3719                                                                                                        String operationUUID, String artifactUUID,
3720                                                                                                        ResourceCommonInfo resourceCommonInfo,
3721                                                                                                        ArtifactOperationInfo operation) {
3722         Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
3723         Either<ArtifactDefinition, ResponseFormat> updateArtifactResult;
3724         String componentId = null;
3725         ArtifactDefinition existingArtifactInfo = null;
3726         String interfaceName = null;
3727         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinitionForUpdate(data, ArtifactDefinition.class);
3728         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3729         String userId = request.getHeader(Constants.USER_ID_HEADER);
3730         Either<ComponentMetadataData, ActionStatus> getComponentRes = fetchLatestComponentMetadata(componentType, componentUuid).right().map(as -> {
3731             errorWrapper.setInnerElement(componentsUtils.getResponseFormat(as));
3732             return as;
3733         });
3734         if (errorWrapper.isEmpty()) {
3735             componentId = getComponentRes.left().value().getMetadataDataDefinition().getUniqueId();
3736             String componentName = getComponentRes.left().value().getMetadataDataDefinition().getName();
3737             if (!getComponentRes.left().value().getMetadataDataDefinition().getState().equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3738                 Component component = checkoutParentComponent(componentType, componentId, userId);
3739                 if (component != null) {
3740                     componentId = component.getUniqueId();
3741                     componentName = component.getName();
3742                 }
3743             }
3744             resourceCommonInfo.setResourceName(componentName);
3745         }
3746         if (errorWrapper.isEmpty()) {
3747             Either<String, ResponseFormat> interfaceNameEither = fetchInterfaceName(componentId, interfaceUUID);
3748             if (interfaceNameEither.isRight()) {
3749                 errorWrapper.setInnerElement(interfaceNameEither.right().value());
3750             } else {
3751                 interfaceName = interfaceNameEither.left().value();
3752             }
3753             if (errorWrapper.isEmpty()) {
3754                 Either<Component, StorageOperationStatus> toscaComponentEither = toscaOperationFacade.getToscaElement(componentId);
3755                 if (toscaComponentEither.isRight()) {
3756                     StorageOperationStatus status = toscaComponentEither.right().value();
3757                     log.debug("Could not fetch component with type {} and id {}. Status is {}. ", componentType, componentId, status);
3758                     errorWrapper.setInnerElement(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status)));
3759                 }
3760                 if (errorWrapper.isEmpty()) {
3761                     NodeTypeEnum parentType = convertParentType(componentType);
3762                     final List<ArtifactDefinition> existingDeploymentArtifacts = getDeploymentArtifacts(toscaComponentEither.left().value(), null);
3763                     for (ArtifactDefinition artifactDefinition : existingDeploymentArtifacts) {
3764                         if (artifactInfo.getArtifactName().equalsIgnoreCase(artifactDefinition.getArtifactName())) {
3765                             existingArtifactInfo = artifactDefinition;
3766                             break;
3767                         }
3768                     }
3769                     if (existingArtifactInfo != null) {
3770                         return updateOperationArtifact(componentId, interfaceName, operationUUID, existingArtifactInfo);
3771                     }
3772                 }
3773             }
3774         }
3775         if (errorWrapper.isEmpty()) {
3776             updateArtifactResult = handleArtifactRequestAndFlatten(componentId, userId, componentType, operation, artifactUUID, artifactInfo, origMd5,
3777                 data, interfaceName, operationUUID);
3778         } else {
3779             updateArtifactResult = Either.right(errorWrapper.getInnerElement());
3780         }
3781         return updateArtifactResult;
3782     }
3783
3784     private Either<ArtifactDefinition, ResponseFormat> handleArtifactRequestAndFlatten(String componentId, String userId,
3785                                                                                        ComponentTypeEnum componentType,
3786                                                                                        ArtifactOperationInfo operation, String artifactId,
3787                                                                                        ArtifactDefinition artifactInfo, String origMd5,
3788                                                                                        String originData, String interfaceName,
3789                                                                                        String operationName) {
3790         try {
3791             return handleArtifactRequest(componentId, userId, componentType, operation, artifactId, artifactInfo, origMd5, originData, interfaceName,
3792                 operationName, null, null).right().map(op -> {
3793                 log.debug("Unexpected value returned while calling handleArtifactRequest: {}", op);
3794                 return componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
3795             });
3796         } catch (ComponentException e) {
3797             return Either.right(e.getResponseFormat());
3798         }
3799     }
3800
3801     private Either<ComponentMetadataData, ActionStatus> fetchLatestComponentMetadataOrThrow(ComponentTypeEnum componentType, String componentUuid) {
3802         return fetchLatestComponentMetadataOrThrow(componentType, componentUuid, componentUuid);
3803     }
3804
3805     private Either<ComponentMetadataData, ActionStatus> fetchLatestComponentMetadataOrThrow(ComponentTypeEnum componentType, String componentUuid,
3806                                                                                             String resourceInstanceName) {
3807         return fetchLatestComponentMetadata(componentType, componentUuid).right().map(as -> {
3808             throw new ByActionStatusComponentException(as, resourceInstanceName);
3809         });
3810     }
3811
3812     private Either<ComponentMetadataData, ActionStatus> fetchLatestComponentMetadata(ComponentTypeEnum componentType, String componentUuid) {
3813         return toscaOperationFacade.getLatestComponentMetadataByUuid(componentUuid, JsonParseFlagEnum.ParseMetadata, true).right().map(sos -> {
3814             log.debug(FAILED_FETCH_COMPONENT, componentType, componentUuid, sos);
3815             return componentsUtils.convertFromStorageResponse(sos, componentType);
3816         });
3817     }
3818
3819     private Either<String, ResponseFormat> fetchInterfaceName(String componentId, String interfaceUUID) {
3820         Either<Component, StorageOperationStatus> componentStorageOperationStatusEither = toscaOperationFacade.getToscaElement(componentId);
3821         if (componentStorageOperationStatusEither.isRight()) {
3822             StorageOperationStatus errorStatus = componentStorageOperationStatusEither.right().value();
3823             log.debug("Failed to fetch component information by component id, error {}", errorStatus);
3824             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
3825         }
3826         Component storedComponent = componentStorageOperationStatusEither.left().value();
3827         Optional<InterfaceDefinition> optionalInterface = InterfaceOperationUtils
3828             .getInterfaceDefinitionFromComponentByInterfaceId(storedComponent, interfaceUUID);
3829         if (!optionalInterface.isPresent()) {
3830             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceUUID));
3831         }
3832         return Either.left(optionalInterface.get().getType());
3833     }
3834
3835     /**
3836      * deletes an artifact on a component by UUID
3837      *
3838      * @param request
3839      * @param componentType
3840      * @param componentUuid
3841      * @param artifactUUID
3842      * @param resourceCommonInfo
3843      * @param operation          TODO
3844      * @return
3845      */
3846     public ArtifactDefinition deleteArtifactOnComponentByUUID(HttpServletRequest request, ComponentTypeEnum componentType, String componentUuid,
3847                                                               String artifactUUID, ResourceCommonInfo resourceCommonInfo,
3848                                                               ArtifactOperationInfo operation) {
3849         Either<ArtifactDefinition, Operation> actionResult;
3850         Component component;
3851         String componentId;
3852         String artifactId;
3853         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3854         String userId = request.getHeader(Constants.USER_ID_HEADER);
3855         Either<ComponentMetadataData, ActionStatus> getComponentRes = fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
3856         componentId = getComponentRes.left().value().getMetadataDataDefinition().getUniqueId();
3857         String componentName = getComponentRes.left().value().getMetadataDataDefinition().getName();
3858         if (!getComponentRes.left().value().getMetadataDataDefinition().getState().equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3859             component = checkoutParentComponent(componentType, componentId, userId);
3860             if (component != null) {
3861                 componentId = component.getUniqueId();
3862                 componentName = component.getName();
3863             }
3864         }
3865         resourceCommonInfo.setResourceName(componentName);
3866         artifactId = getLatestParentArtifactDataIdByArtifactUUID(artifactUUID, componentId, componentType);
3867         actionResult = handleArtifactRequest(componentId, userId, componentType, operation, artifactId, null, origMd5, null, null, null, null, null);
3868         return actionResult.left().value();
3869     }
3870
3871     /**
3872      * deletes an artifact from a resource instance by UUID
3873      *
3874      * @param request
3875      * @param componentType
3876      * @param componentUuid
3877      * @param resourceInstanceName
3878      * @param artifactUUID
3879      * @param operation            TODO
3880      * @return
3881      */
3882     public ArtifactDefinition deleteArtifactOnRiByUUID(HttpServletRequest request, ComponentTypeEnum componentType, String componentUuid,
3883                                                        String resourceInstanceName, String artifactUUID, ArtifactOperationInfo operation) {
3884         Either<ArtifactDefinition, Operation> actionResult;
3885         Component component = null;
3886         String componentInstanceId;
3887         String componentId;
3888         String artifactId;
3889         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3890         String userId = request.getHeader(Constants.USER_ID_HEADER);
3891         ImmutablePair<Component, ComponentInstance> componentRiPair = null;
3892         Either<ComponentMetadataData, ActionStatus> getComponentRes = fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
3893         if (!getComponentRes.left().value().getMetadataDataDefinition().getState().equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3894             component = checkoutParentComponent(componentType, getComponentRes.left().value().getMetadataDataDefinition().getUniqueId(), userId);
3895         }
3896         if (component == null) {
3897             componentRiPair = getRelatedComponentComponentInstance(componentType, componentUuid, resourceInstanceName);
3898         } else {
3899             componentRiPair = getRelatedComponentComponentInstance(component, resourceInstanceName);
3900         }
3901         componentInstanceId = componentRiPair.getRight().getUniqueId();
3902         componentId = componentRiPair.getLeft().getUniqueId();
3903         artifactId = findArtifactId(componentRiPair.getRight(), artifactUUID);
3904         actionResult = handleArtifactRequest(componentInstanceId, userId, ComponentTypeEnum.RESOURCE_INSTANCE, operation, artifactId, null, origMd5,
3905             null, null, null, componentId, ComponentTypeEnum.findParamByType(componentType));
3906         return actionResult.left().value();
3907     }
3908
3909     private String findArtifactId(ComponentInstance instance, String artifactUUID) {
3910         String artifactId = null;
3911         ArtifactDefinition foundArtifact = null;
3912         if (instance.getDeploymentArtifacts() != null) {
3913             foundArtifact = instance.getDeploymentArtifacts().values().stream()
3914                 .filter(e -> e.getArtifactUUID() != null && e.getArtifactUUID().equals(artifactUUID)).findFirst().orElse(null);
3915         }
3916         if (foundArtifact == null && instance.getArtifacts() != null) {
3917             foundArtifact = instance.getArtifacts().values().stream()
3918                 .filter(e -> e.getArtifactUUID() != null && e.getArtifactUUID().equals(artifactUUID)).findFirst().orElse(null);
3919         }
3920         if (foundArtifact == null) {
3921             log.debug("The artifact {} was not found on instance {}. ", artifactUUID, instance.getUniqueId());
3922             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactUUID);
3923         } else {
3924             artifactId = foundArtifact.getUniqueId();
3925         }
3926         return artifactId;
3927     }
3928
3929     @SuppressWarnings("unchecked")
3930     public ArtifactDefinition createHeatEnvPlaceHolder(List<ArtifactDefinition> createdArtifacts, ArtifactDefinition heatArtifact, String envType,
3931                                                        String parentId, NodeTypeEnum parentType, String parentName, User user, Component component,
3932                                                        Map<String, String> existingEnvVersions) {
3933         Map<String, Object> deploymentResourceArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration()
3934             .getDeploymentResourceInstanceArtifacts();
3935         if (deploymentResourceArtifacts == null) {
3936             log.debug("no deployment artifacts are configured for generated artifacts");
3937             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
3938         }
3939         Map<String, Object> placeHolderData = (Map<String, Object>) deploymentResourceArtifacts.get(envType);
3940         if (placeHolderData == null) {
3941             log.debug("no env type {} are configured for generated artifacts", envType);
3942             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
3943         }
3944         String envLabel = (heatArtifact.getArtifactLabel() + HEAT_ENV_SUFFIX).toLowerCase();
3945         ArtifactDefinition createArtifactPlaceHolder = createArtifactPlaceHolderInfo(parentId, envLabel, placeHolderData, user.getUserId(),
3946             ArtifactGroupTypeEnum.DEPLOYMENT, true);
3947         ArtifactDefinition artifactHeatEnv = createArtifactPlaceHolder;
3948         artifactHeatEnv.setGeneratedFromId(heatArtifact.getUniqueId());
3949         artifactHeatEnv.setHeatParamsUpdateDate(System.currentTimeMillis());
3950         artifactHeatEnv.setTimeout(0);
3951         artifactHeatEnv.setIsFromCsar(heatArtifact.getIsFromCsar());
3952         buildHeatEnvFileName(heatArtifact, artifactHeatEnv, placeHolderData);
3953         // rbetzer - keep env artifactVersion - changeComponentInstanceVersion flow
3954         handleEnvArtifactVersion(artifactHeatEnv, existingEnvVersions);
3955         ArtifactDefinition heatEnvPlaceholder;
3956         // Evg : for resource instance artifact will be added later as block with other env artifacts from BL
3957         if (parentType != NodeTypeEnum.ResourceInstance) {
3958             String checkSum = artifactToscaOperation.sortAndCalculateChecksumForHeatParameters(heatArtifact.getHeatParameters());
3959             artifactHeatEnv.setArtifactChecksum(checkSum);
3960             Either<ArtifactDefinition, StorageOperationStatus> addHeatEnvArtifact = addHeatEnvArtifact(artifactHeatEnv, heatArtifact, component,
3961                 parentType, parentId);
3962             if (addHeatEnvArtifact.isRight()) {
3963                 log.debug("failed to create heat env artifact on resource instance");
3964                 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormatForResourceInstance(
3965                     componentsUtils.convertFromStorageResponseForResourceInstance(addHeatEnvArtifact.right().value(), false), "", null));
3966             }
3967             heatEnvPlaceholder = createArtifactPlaceHolder;
3968         } else {
3969             heatEnvPlaceholder = artifactHeatEnv;
3970             artifactToscaOperation.generateUUID(heatEnvPlaceholder, heatEnvPlaceholder.getArtifactVersion());
3971             setHeatCurrentValuesOnHeatEnvDefaultValues(heatArtifact, heatEnvPlaceholder);
3972         }
3973         ComponentTypeEnum componentType = component.getComponentType();
3974         if (parentType == NodeTypeEnum.ResourceInstance) {
3975             componentType = ComponentTypeEnum.RESOURCE_INSTANCE;
3976         }
3977         createdArtifacts.add(heatEnvPlaceholder);
3978         componentsUtils.auditComponent(componentsUtils.getResponseFormat(ActionStatus.OK), user, component, AuditingActionEnum.ARTIFACT_UPLOAD,
3979             new ResourceCommonInfo(parentName, componentType.getValue()), ResourceVersionInfo.newBuilder().build(),
3980             ResourceVersionInfo.newBuilder().artifactUuid(heatEnvPlaceholder.getUniqueId()).build(), null, heatEnvPlaceholder, null);
3981         return heatEnvPlaceholder;
3982     }
3983
3984     private void setHeatCurrentValuesOnHeatEnvDefaultValues(ArtifactDefinition artifact, ArtifactDefinition artifactDefinition) {
3985         if (artifact.getListHeatParameters() == null) {
3986             return;
3987         }
3988         List<HeatParameterDefinition> heatEnvParameters = new ArrayList<>();
3989         for (HeatParameterDefinition parameter : artifact.getListHeatParameters()) {
3990             HeatParameterDefinition heatEnvParameter = new HeatParameterDefinition(parameter);
3991             heatEnvParameter.setDefaultValue(parameter.getCurrentValue());
3992             heatEnvParameter.setCurrentValue(null);
3993             heatEnvParameters.add(heatEnvParameter);
3994         }
3995         artifactDefinition.setListHeatParameters(heatEnvParameters);
3996     }
3997
3998     private void buildHeatEnvFileName(ArtifactDefinition heatArtifact, ArtifactDefinition heatEnvArtifact, Map<String, Object> placeHolderData) {
3999         String heatExtension = GeneralUtility.getFilenameExtension(heatArtifact.getArtifactName());
4000         String envExtension = (String) placeHolderData.get(ARTIFACT_PLACEHOLDER_FILE_EXTENSION);
4001         String name = heatArtifact.getArtifactName();
4002         String fileName;
4003         if (name == null) {
4004             name = heatArtifact.getArtifactLabel();
4005             fileName = name + "." + envExtension;
4006         } else {
4007             fileName = name.replaceAll("." + heatExtension, "." + envExtension);
4008         }
4009         heatEnvArtifact.setArtifactName(fileName);
4010     }
4011
4012     private void handleEnvArtifactVersion(ArtifactDefinition heatEnvArtifact, Map<String, String> existingEnvVersions) {
4013         if (null != existingEnvVersions) {
4014             String prevVersion = existingEnvVersions.get(heatEnvArtifact.getArtifactName());
4015             if (null != prevVersion) {
4016                 heatEnvArtifact.setArtifactVersion(prevVersion);
4017             }
4018         }
4019     }
4020
4021     public List<ArtifactDefinition> handleArtifactsForInnerVfcComponent(List<ArtifactDefinition> artifactsToHandle, Resource component, User user,
4022                                                                         List<ArtifactDefinition> vfcsNewCreatedArtifacts,
4023                                                                         ArtifactOperationInfo operation, boolean shouldLock, boolean inTransaction) {
4024         ComponentTypeEnum componentType = component.getComponentType();
4025         List<ArtifactDefinition> uploadedArtifacts = new ArrayList<>();
4026         Either<ArtifactDefinition, Operation> result;
4027         try {
4028             for (ArtifactDefinition artifactDefinition : artifactsToHandle) {
4029                 result = handleLoadedArtifact(component, user, operation, shouldLock, inTransaction, componentType, artifactDefinition);
4030                 uploadedArtifacts.add(result.left().value());
4031             }
4032         } catch (ComponentException e) {
4033             log.debug(FAILED_UPLOAD_ARTIFACT_TO_COMPONENT, componentType, component.getName(), e.getResponseFormat());
4034             if (operation.isCreateOrLink()) {
4035                 vfcsNewCreatedArtifacts.addAll(uploadedArtifacts);
4036             }
4037             throw e;
4038         }
4039         return uploadedArtifacts;
4040     }
4041
4042     public Either<ArtifactDefinition, Operation> handleLoadedArtifact(Component component, User user, ArtifactOperationInfo operation,
4043                                                                       boolean shouldLock, boolean inTransaction, ComponentTypeEnum componentType,
4044                                                                       ArtifactDefinition artifactDefinition) {
4045         AuditingActionEnum auditingAction = detectAuditingType(operation, "");
4046         String componentId = component.getUniqueId();
4047         String artifactId = artifactDefinition.getUniqueId();
4048         Either<ArtifactDefinition, Operation> result;
4049         Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
4050         //artifact validation
4051         artifactDefinition = validateArtifact(componentId, componentType, operation, artifactId, artifactDefinition, auditingAction, user, component,
4052             shouldLock, inTransaction);
4053         switch (operation.getArtifactOperationEnum()) {
4054             case CREATE:
4055                 byte[] validPayload = getValidPayload(componentId, artifactDefinition, operation, auditingAction, artifactId, user, componentType,
4056                     component, null, null);
4057                 result = createArtifact(component, componentId, artifactDefinition, validPayload, componentType, auditingAction, null, null);
4058                 break;
4059             case UPDATE:
4060                 validPayload = getValidPayload(componentId, artifactDefinition, operation, auditingAction, artifactId, user, componentType, component,
4061                     null, null);
4062                 result = handleUpdate(componentId, componentType, operation, artifactId, artifactDefinition, validPayload, null, null, null, null,
4063                     auditingAction, user, component, true);
4064                 break;
4065             case DELETE:
4066                 result = Either.left(handleDeleteInternal(componentId, artifactId, componentType, component));
4067                 break;
4068             case DOWNLOAD:
4069                 if (artifactGenerationRequired(component, artifactDefinition)) {
4070                     result = Either.left(generateNotSavedArtifact(component, artifactDefinition));
4071                 } else {
4072                     result = Either.left(handleDownload(componentId, artifactId, componentType, component));
4073                 }
4074                 break;
4075             case LINK:
4076                 result = Either.left(handleLink(componentId, artifactDefinition, componentType, component));
4077                 break;
4078             default:
4079                 throw new UnsupportedOperationException(
4080                     "In ArtifactsBusinessLogic received illegal operation: " + operation.getArtifactOperationEnum());
4081         }
4082         return result;
4083     }
4084
4085     public List<ArtifactDefinition> handleArtifactsRequestForInnerVfcComponent(List<ArtifactDefinition> artifactsToHandle, Resource component,
4086                                                                                User user, List<ArtifactDefinition> vfcsNewCreatedArtifacts,
4087                                                                                ArtifactOperationInfo operation, boolean shouldLock,
4088                                                                                boolean inTransaction) {
4089         List<ArtifactDefinition> handleArtifactsResult;
4090         ComponentTypeEnum componentType = component.getComponentType();
4091         List<ArtifactDefinition> uploadedArtifacts = new ArrayList<>();
4092         Either<ArtifactDefinition, Operation> actionResult;
4093         String originData;
4094         String origMd5;
4095         try {
4096             for (ArtifactDefinition artifact : artifactsToHandle) {
4097                 originData = ArtifactUtils.buildJsonStringForCsarVfcArtifact(artifact);
4098                 origMd5 = GeneralUtility.calculateMD5Base64EncodedByString(originData);
4099                 actionResult = handleArtifactRequest(component.getUniqueId(), user.getUserId(), componentType, operation, artifact.getUniqueId(),
4100                     artifact, origMd5, originData, null, null, null, null, shouldLock, inTransaction);
4101                 uploadedArtifacts.add(actionResult.left().value());
4102             }
4103             handleArtifactsResult = uploadedArtifacts;
4104         } catch (ComponentException e) {
4105             if (operation.isCreateOrLink()) {
4106                 vfcsNewCreatedArtifacts.addAll(uploadedArtifacts);
4107             }
4108             throw e;
4109         }
4110         return handleArtifactsResult;
4111     }
4112
4113     private ComponentInstance getRelatedComponentInstance(ComponentTypeEnum componentType, String componentUuid, String resourceInstanceName) {
4114         String normalizedName = ValidationUtils.normalizeComponentInstanceName(resourceInstanceName);
4115         Option<Component> oComponent = Option.of(getComponentByUuid(componentType, componentUuid));
4116         return oComponent.toTry(componentNotFound(componentType, componentUuid)).flatMap(
4117             component -> findFirstMatching(component, ci -> ValidationUtils.normalizeComponentInstanceName(ci.getName()).equals(normalizedName))
4118                 .toTry(componentInstanceNotFound(componentType, resourceInstanceName, component))).get();
4119     }
4120
4121     private ImmutablePair<Component, ComponentInstance> getRelatedComponentComponentInstance(Component component, String resourceInstanceName) {
4122         String normalizedName = ValidationUtils.normalizeComponentInstanceName(resourceInstanceName);
4123         ComponentInstance componentInstance = findFirstMatching(component,
4124             ci -> ValidationUtils.normalizeComponentInstanceName(ci.getName()).equals(normalizedName))
4125             .toTry(componentInstanceNotFound(component.getComponentType(), resourceInstanceName, component)).get();
4126         return new ImmutablePair<>(component, componentInstance);
4127     }
4128
4129     private ImmutablePair<Component, ComponentInstance> getRelatedComponentComponentInstance(ComponentTypeEnum componentType, String componentUuid,
4130                                                                                              String resourceInstanceName) {
4131         Component component = getLatestComponentByUuid(componentType, componentUuid);
4132         ComponentInstance componentInstance = findFirstMatching(component, ci -> ci.getNormalizedName().equals(resourceInstanceName))
4133             .toTry(componentInstanceNotFound(component.getComponentType(), resourceInstanceName, component)).get();
4134         return new ImmutablePair<>(component, componentInstance);
4135     }
4136
4137     private Supplier<Throwable> componentNotFound(ComponentTypeEnum componentType, String componentUuid) {
4138         return () -> {
4139             log.debug(FAILED_FETCH_COMPONENT, componentType.getValue(), componentUuid);
4140             return new ByActionStatusComponentException(ActionStatus.COMPONENT_NOT_FOUND, componentUuid);
4141         };
4142     }
4143
4144     private Supplier<Throwable> componentInstanceNotFound(ComponentTypeEnum componentType, String resourceInstanceName, Component component) {
4145         return () -> {
4146             log.debug(COMPONENT_INSTANCE_NOT_FOUND, resourceInstanceName, component.getName());
4147             return new ByActionStatusComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, resourceInstanceName,
4148                 RESOURCE_INSTANCE, componentType.getValue(), component.getName());
4149         };
4150     }
4151
4152     private byte[] downloadArtifact(Map<String, ArtifactDefinition> artifacts, String artifactUUID, String componentName) {
4153         ImmutablePair<String, byte[]> downloadArtifact;
4154         List<ArtifactDefinition> artifactsList = null;
4155         ArtifactDefinition deploymentArtifact;
4156         if (artifacts != null && !artifacts.isEmpty()) {
4157             artifactsList = artifacts.values().stream().filter(art -> art.getArtifactUUID() != null && art.getArtifactUUID().equals(artifactUUID))
4158                 .collect(Collectors.toList());
4159         }
4160         if (artifactsList == null || artifactsList.isEmpty()) {
4161             log.debug("Deployment artifact with uuid {} was not found for component {}", artifactUUID, componentName);
4162             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactUUID);
4163         }
4164         deploymentArtifact = artifactsList.get(0);
4165         downloadArtifact = downloadArtifact(deploymentArtifact);
4166         log.trace("Succeeded to download artifact with uniqueId {}", deploymentArtifact.getUniqueId());
4167         return downloadArtifact.getRight();
4168     }
4169
4170     private Component getLatestComponentByUuid(ComponentTypeEnum componentType, String componentUuid) {
4171         Component component;
4172         Either<Component, StorageOperationStatus> getComponentRes = toscaOperationFacade.getLatestComponentByUuid(componentUuid);
4173         if (getComponentRes.isRight()) {
4174             StorageOperationStatus status = getComponentRes.right().value();
4175             log.debug(FAILED_FETCH_COMPONENT, componentType, componentUuid, status);
4176             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status));
4177         } else {
4178             component = getComponentRes.left().value();
4179         }
4180         return component;
4181     }
4182
4183     private Component getComponentByUuid(ComponentTypeEnum componentType, String componentUuid) {
4184         Component component;
4185         Either<List<Component>, StorageOperationStatus> getComponentRes = toscaOperationFacade.getComponentListByUuid(componentUuid, null);
4186         if (getComponentRes.isRight()) {
4187             StorageOperationStatus status = getComponentRes.right().value();
4188             log.debug(FAILED_FETCH_COMPONENT, componentType, componentUuid, status);
4189             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status));
4190         } else {
4191             List<Component> value = getComponentRes.left().value();
4192             if (value.isEmpty()) {
4193                 log.debug("Could not fetch component with type {} and uuid {}.", componentType, componentUuid);
4194                 ActionStatus status = componentType == ComponentTypeEnum.RESOURCE ? ActionStatus.RESOURCE_NOT_FOUND : ActionStatus.SERVICE_NOT_FOUND;
4195                 throw new ByActionStatusComponentException(status);
4196             } else {
4197                 component = value.get(0);
4198             }
4199         }
4200         return component;
4201     }
4202
4203     private String getLatestParentArtifactDataIdByArtifactUUID(String artifactUUID, String parentId, ComponentTypeEnum componentType) {
4204         ActionStatus actionStatus = ActionStatus.ARTIFACT_NOT_FOUND;
4205         StorageOperationStatus storageStatus;
4206         ArtifactDefinition latestArtifact;
4207         List<ArtifactDefinition> artifacts;
4208         Either<Map<String, ArtifactDefinition>, StorageOperationStatus> getArtifactsRes = artifactToscaOperation.getArtifacts(parentId);
4209         if (getArtifactsRes.isRight()) {
4210             storageStatus = getArtifactsRes.right().value();
4211             log.debug("Couldn't fetch artifacts data for parent component {} with uid {}, error: {}", componentType, parentId, storageStatus);
4212             if (storageStatus != StorageOperationStatus.NOT_FOUND) {
4213                 actionStatus = componentsUtils.convertFromStorageResponse(storageStatus);
4214             }
4215             throw new ByActionStatusComponentException(actionStatus, artifactUUID);
4216         }
4217         artifacts = getArtifactsRes.left().value().values().stream()
4218             .filter(a -> a.getArtifactUUID() != null && a.getArtifactUUID().equals(artifactUUID)).collect(Collectors.toList());
4219         if (artifacts == null || artifacts.isEmpty()) {
4220             log.debug("Couldn't fetch artifact with UUID {} data for parent component {} with uid {}, error: {}", artifactUUID, componentType,
4221                 parentId, actionStatus);
4222             throw new ByActionStatusComponentException(actionStatus, artifactUUID);
4223         }
4224         latestArtifact = artifacts.stream().max((a1, a2) -> {
4225             int compareRes = Double.compare(Double.parseDouble(a1.getArtifactVersion()), Double.parseDouble(a2.getArtifactVersion()));
4226             if (compareRes == 0) {
4227                 compareRes = Long.compare(a1.getLastUpdateDate() == null ? 0 : a1.getLastUpdateDate(),
4228                     a2.getLastUpdateDate() == null ? 0 : a2.getLastUpdateDate());
4229             }
4230             return compareRes;
4231         }).get();
4232         if (latestArtifact == null) {
4233             log.debug("Couldn't fetch latest artifact with UUID {} data for parent component {} with uid {}, error: {}", artifactUUID, componentType,
4234                 parentId, actionStatus);
4235             throw new ByActionStatusComponentException(actionStatus, artifactUUID);
4236         }
4237         return latestArtifact.getUniqueId();
4238     }
4239
4240     private Component checkoutParentComponent(ComponentTypeEnum componentType, String parentId, String userId) {
4241         Component component = null;
4242         User modifier = userBusinessLogic.getUser(userId, false);
4243         LifecycleChangeInfoWithAction changeInfo = new LifecycleChangeInfoWithAction("External API checkout",
4244             LifecycleChanceActionEnum.UPDATE_FROM_EXTERNAL_API);
4245         Either<? extends Component, ResponseFormat> checkoutRes = lifecycleBusinessLogic
4246             .changeComponentState(componentType, parentId, modifier, LifeCycleTransitionEnum.CHECKOUT, changeInfo, false, true);
4247         if (checkoutRes.isRight()) {
4248             log.debug("Could not change state of component {} with uid {} to checked out. Status is {}. ", componentType.getNodeType(), parentId,
4249                 checkoutRes.right().value().getStatus());
4250             throw new ByResponseFormatComponentException(checkoutRes.right().value());
4251         }
4252         return checkoutRes.left().value();
4253     }
4254
4255     @Autowired
4256     void setNodeTemplateOperation(NodeTemplateOperation nodeTemplateOperation) {
4257         this.nodeTemplateOperation = nodeTemplateOperation;
4258     }
4259
4260     public List<ArtifactConfiguration> getConfiguration() {
4261         return ConfigurationManager.getConfigurationManager().getConfiguration().getArtifacts();
4262     }
4263
4264     public enum ArtifactOperationEnum {
4265         CREATE, UPDATE, DELETE, DOWNLOAD, LINK;
4266
4267         public static boolean isCreateOrLink(ArtifactOperationEnum operation) {
4268             return operation == CREATE || operation == LINK;
4269         }
4270     }
4271
4272     public Map<String, ArtifactTypeDefinition> getAllToscaArtifacts(final String modelName) {
4273         if (StringUtils.isNotEmpty(modelName)) {
4274             artifactTypeOperation.validateModel(modelName);
4275         }
4276         return artifactTypeOperation.getAllArtifactTypes(modelName);
4277     }
4278 }