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