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