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