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