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