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