Set properties on XML parsers to prevent XXE attack
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ArtifactsBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22
23 package org.openecomp.sdc.be.components.impl;
24
25 import static org.openecomp.sdc.be.dao.api.ActionStatus.MISMATCH_BETWEEN_ARTIFACT_TYPE_AND_COMPONENT_TYPE;
26
27 import com.google.common.annotations.VisibleForTesting;
28 import com.google.gson.Gson;
29 import com.google.gson.GsonBuilder;
30 import fj.F;
31 import fj.data.Either;
32 import io.vavr.control.Option;
33 import java.io.ByteArrayInputStream;
34 import java.io.IOException;
35 import java.math.BigDecimal;
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.Comparator;
39 import java.util.HashMap;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Map.Entry;
44 import java.util.Objects;
45 import java.util.Optional;
46 import java.util.Set;
47 import java.util.function.Consumer;
48 import java.util.function.Function;
49 import java.util.function.Predicate;
50 import java.util.function.Supplier;
51 import java.util.stream.Collectors;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.xml.XMLConstants;
54 import javax.xml.parsers.ParserConfigurationException;
55 import javax.xml.parsers.SAXParser;
56 import javax.xml.parsers.SAXParserFactory;
57 import org.apache.commons.codec.binary.Base64;
58 import org.apache.commons.collections.CollectionUtils;
59 import org.apache.commons.collections.MapUtils;
60 import org.apache.commons.io.FilenameUtils;
61 import org.apache.commons.lang.ArrayUtils;
62 import org.apache.commons.lang.StringUtils;
63 import org.apache.commons.lang3.tuple.ImmutablePair;
64 import org.openecomp.sdc.be.components.ArtifactsResolver;
65 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
66 import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo;
67 import org.openecomp.sdc.be.components.impl.artifact.ArtifactTypeToPayloadTypeSelector;
68 import org.openecomp.sdc.be.components.impl.artifact.PayloadTypeEnum;
69 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
70 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
71 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
72 import org.openecomp.sdc.be.components.utils.ArtifactUtils;
73 import org.openecomp.sdc.be.components.impl.utils.ComponentUtils;
74 import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
75 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
76 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction.LifecycleChanceActionEnum;
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().getBytes();
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 (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(String artifactId, ArtifactDefinition foundArtifact, List<GroupInstance> groupInstances) {
1458         List<GroupInstance> updatedGroupInstances = new ArrayList<>();
1459         if (CollectionUtils.isNotEmpty(groupInstances)) {
1460             boolean isUpdated = false;
1461             for (GroupInstance groupInstance : groupInstances) {
1462                 isUpdated = false;
1463                 if (CollectionUtils.isNotEmpty(groupInstance.getGroupInstanceArtifacts()) && groupInstance.getGroupInstanceArtifacts().contains(artifactId)) {
1464                     groupInstance.getGroupInstanceArtifacts().remove(artifactId);
1465                     isUpdated = true;
1466                 }
1467                 if (CollectionUtils.isNotEmpty(groupInstance.getGroupInstanceArtifactsUuid()) && groupInstance.getGroupInstanceArtifactsUuid()
1468                         .contains(foundArtifact.getArtifactUUID())) {
1469                     groupInstance.getGroupInstanceArtifactsUuid().remove(foundArtifact.getArtifactUUID());
1470                     isUpdated = true;
1471                 }
1472                 if (isUpdated) {
1473                     updatedGroupInstances.add(groupInstance);
1474                 }
1475             }
1476         }
1477         return updatedGroupInstances;
1478     }
1479
1480     private ArtifactDataDefinition deleteOrUpdateArtifactOnGraph(Component component, String parentId, String artifactId, NodeTypeEnum parentType, ArtifactDefinition foundArtifact, Boolean cloneIsNeeded) {
1481
1482         Either<ArtifactDataDefinition, StorageOperationStatus> result;
1483         boolean isMandatory = foundArtifact.getMandatory() || foundArtifact.getServiceApi();
1484         String componentId = component.getUniqueId();
1485         String instanceId = componentId.equals(parentId) ? null : parentId;
1486         if (isMandatory) {
1487             log.debug("Going to update mandatory artifact {} from the component {}", artifactId, parentId);
1488             resetMandatoryArtifactFields(foundArtifact);
1489             result = artifactToscaOperation.updateArtifactOnGraph(component, foundArtifact, parentType, artifactId, instanceId, true, true);
1490         }
1491         else if (cloneIsNeeded) {
1492             log.debug("Going to clone artifacts and to delete the artifact {} from the component {}", artifactId, parentId);
1493             result = artifactToscaOperation.deleteArtifactWithCloningOnGraph(componentId, foundArtifact, parentType, instanceId, false);
1494         }
1495         else {
1496             log.debug("Going to delete the artifact {} from the component {}", artifactId, parentId);
1497             result = artifactToscaOperation.removeArtifactOnGraph(foundArtifact, componentId, instanceId, parentType, false);
1498         }
1499         if (result.isRight()) {
1500             throw new StorageException(result.right().value(), foundArtifact.getArtifactDisplayName());
1501         }
1502         return result.left().value();
1503     }
1504
1505     private Either<ImmutablePair<ArtifactDefinition, ComponentInstance>, ActionStatus> findArtifact(String artifactId, Component fetchedContainerComponent, String parentId, ComponentTypeEnum componentType) {
1506
1507         Either<ImmutablePair<ArtifactDefinition, ComponentInstance>, ActionStatus> result = null;
1508         Map<String, ArtifactDefinition> artifacts = new HashMap<>();
1509         ComponentInstance foundInstance = null;
1510         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE && StringUtils.isNotEmpty(parentId)) {
1511             Optional<ComponentInstance> componentInstanceOpt = fetchedContainerComponent.getComponentInstances()
1512                     .stream()
1513                     .filter(i -> i.getUniqueId()
1514                             .equals(parentId))
1515                     .findFirst();
1516             if (!componentInstanceOpt.isPresent()) {
1517                 result = Either.right(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER);
1518             }
1519             else {
1520                 foundInstance = componentInstanceOpt.get();
1521                 fetchArtifactsFromInstance(artifactId, artifacts, foundInstance);
1522             }
1523         }
1524         else {
1525             fetchArtifactsFromComponent(artifactId, fetchedContainerComponent, artifacts);
1526         }
1527         if (result == null) {
1528             if (artifacts.containsKey(artifactId)) {
1529                 result = Either.left(new ImmutablePair<>(artifacts.get(artifactId), foundInstance));
1530             }
1531             else {
1532                 result = Either.right(ActionStatus.ARTIFACT_NOT_FOUND);
1533             }
1534         }
1535         return result;
1536     }
1537
1538     private void fetchArtifactsFromComponent(String artifactId, Component component, Map<String, ArtifactDefinition> artifacts) {
1539         Map<String, ArtifactDefinition> currArtifacts;
1540         if (!artifacts.containsKey(artifactId) && MapUtils.isNotEmpty(component.getDeploymentArtifacts())) {
1541             currArtifacts = component.getDeploymentArtifacts()
1542                     .values()
1543                     .stream()
1544                     .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, i -> i));
1545             if (MapUtils.isNotEmpty(currArtifacts)) {
1546                 artifacts.putAll(currArtifacts);
1547             }
1548         }
1549         if (!artifacts.containsKey(artifactId) && MapUtils.isNotEmpty(component.getArtifacts())) {
1550             currArtifacts = component.getArtifacts()
1551                     .values()
1552                     .stream()
1553                     .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, Function.identity()));
1554             if (MapUtils.isNotEmpty(currArtifacts)) {
1555                 artifacts.putAll(currArtifacts);
1556             }
1557         }
1558         if (!artifacts.containsKey(artifactId) && MapUtils.isNotEmpty(component.getArtifacts())) {
1559             currArtifacts = component.getToscaArtifacts()
1560                     .values()
1561                     .stream()
1562                     .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, Function.identity()));
1563             if (MapUtils.isNotEmpty(currArtifacts)) {
1564                 artifacts.putAll(currArtifacts);
1565             }
1566         }
1567     }
1568
1569     private void fetchArtifactsFromInstance(String artifactId, Map<String, ArtifactDefinition> artifacts, ComponentInstance instance) {
1570         Map<String, ArtifactDefinition> currArtifacts;
1571         if (MapUtils.isNotEmpty(instance.getDeploymentArtifacts())) {
1572             currArtifacts = instance.getDeploymentArtifacts()
1573                     .values()
1574                     .stream()
1575                     .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, Function.identity()));
1576             if (MapUtils.isNotEmpty(currArtifacts)) {
1577                 artifacts.putAll(currArtifacts);
1578             }
1579         }
1580         if (!artifacts.containsKey(artifactId) && MapUtils.isNotEmpty(instance.getArtifacts())) {
1581             currArtifacts = instance.getArtifacts()
1582                     .values()
1583                     .stream()
1584                     .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, Function.identity()));
1585             if (MapUtils.isNotEmpty(currArtifacts)) {
1586                 artifacts.putAll(currArtifacts);
1587             }
1588         }
1589     }
1590
1591     private StorageOperationStatus convertToStorageOperationStatus(CassandraOperationStatus cassandraStatus) {
1592         StorageOperationStatus result;
1593         switch (cassandraStatus) {
1594             case OK:
1595                 result = StorageOperationStatus.OK;
1596                 break;
1597             case NOT_FOUND:
1598                 result = StorageOperationStatus.NOT_FOUND;
1599                 break;
1600             case CLUSTER_NOT_CONNECTED:
1601             case KEYSPACE_NOT_CONNECTED:
1602                 result = StorageOperationStatus.CONNECTION_FAILURE;
1603                 break;
1604             default:
1605                 result = StorageOperationStatus.GENERAL_ERROR;
1606                 break;
1607         }
1608         return result;
1609     }
1610
1611     private void resetMandatoryArtifactFields(ArtifactDefinition fetchedArtifact) {
1612         if (fetchedArtifact != null) {
1613             log.debug("Going to reset mandatory artifact {} fields. ", fetchedArtifact.getUniqueId());
1614             fetchedArtifact.setEsId(null);
1615             fetchedArtifact.setArtifactName(null);
1616             fetchedArtifact.setDescription(null);
1617             fetchedArtifact.setApiUrl(null);
1618             fetchedArtifact.setArtifactChecksum(null);
1619             nodeTemplateOperation.setDefaultArtifactTimeout(fetchedArtifact.getArtifactGroupType(), fetchedArtifact);
1620             fetchedArtifact.setArtifactUUID(null);
1621             long time = System.currentTimeMillis();
1622             fetchedArtifact.setPayloadUpdateDate(time);
1623             fetchedArtifact.setHeatParameters(null);
1624             fetchedArtifact.setHeatParamsUpdateDate(null);
1625         }
1626     }
1627
1628     private StorageOperationStatus generateCustomizationUUIDOnInstance(String componentId, String instanceId, ComponentTypeEnum componentType) {
1629         StorageOperationStatus error = StorageOperationStatus.OK;
1630         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1631             log.debug("Need to re-generate  customization UUID for instance {}", instanceId);
1632             error = toscaOperationFacade.generateCustomizationUUIDOnInstance(componentId, instanceId);
1633         }
1634         return error;
1635     }
1636
1637     private ArtifactDefinition handleDownload(String componentId, String artifactId, ComponentTypeEnum componentType,
1638                                               Component parent) {
1639         Either<ArtifactDefinition, StorageOperationStatus> artifactById = artifactToscaOperation.getArtifactById(componentId, artifactId, componentType,
1640                 parent.getUniqueId());
1641         if (artifactById.isRight()) {
1642             throw new StorageException(artifactById.right().value());
1643         }
1644         ArtifactDefinition artifactDefinition = artifactById.left().value();
1645         if (artifactDefinition == null) {
1646             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactId);
1647         }
1648         return artifactDefinition;
1649     }
1650
1651     private Either<ActionStatus, ResponseFormat> handleArtifactLabel(String componentId, Component parentComponent, ArtifactOperationInfo operation, ArtifactDefinition artifactInfo, String operationName,
1652                                                                      ComponentTypeEnum componentType) {
1653
1654         String artifactLabel = artifactInfo.getArtifactLabel();
1655         if (operationName == null && (artifactInfo.getArtifactLabel() == null || artifactInfo.getArtifactLabel()
1656                 .isEmpty())) {
1657             BeEcompErrorManager.getInstance()
1658                     .logBeMissingArtifactInformationError("Artifact Update / Upload", "artifactLabel");
1659             log.debug("missing artifact logical name for component {}", componentId);
1660             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_LABEL));
1661         }
1662         if (operation.isCreateOrLink() && !artifactInfo.getMandatory()) {
1663
1664             if (operationName != null) {
1665                 if (artifactInfo.getArtifactLabel() != null && !operationName.equals(artifactInfo.getArtifactLabel())) {
1666                     log.debug("artifact label cannot be set {}", artifactLabel);
1667                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_LOGICAL_NAME_CANNOT_BE_CHANGED));
1668                 }
1669                 else {
1670                     artifactLabel = operationName;
1671                 }
1672             }
1673             String displayName = artifactInfo.getArtifactDisplayName();
1674             if (displayName == null || displayName.isEmpty()) {
1675                 displayName = artifactLabel;
1676             }
1677             displayName = ValidationUtils.cleanArtifactDisplayName(displayName);
1678             artifactInfo.setArtifactDisplayName(displayName);
1679
1680             if (!ValidationUtils.validateArtifactLabel(artifactLabel)) {
1681                 log.debug("Invalid format form Artifact label : {}", artifactLabel);
1682                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1683             }
1684             artifactLabel = ValidationUtils.normalizeArtifactLabel(artifactLabel);
1685
1686             if (artifactLabel.isEmpty()) {
1687                 log.debug("missing normalized artifact logical name for component {}", componentId);
1688                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_LABEL));
1689             }
1690
1691             if (!ValidationUtils.validateArtifactLabelLength(artifactLabel)) {
1692                 log.debug("Invalid lenght form Artifact label : {}", artifactLabel);
1693                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, ARTIFACT_LABEL, String
1694                         .valueOf(ValidationUtils.ARTIFACT_LABEL_LENGTH)));
1695             }
1696             if (!validateLabelUniqueness(componentId, parentComponent, artifactLabel, componentType)) {
1697                 log.debug("Non unique Artifact label : {}", artifactLabel);
1698                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_EXIST, artifactLabel));
1699             }
1700         }
1701         artifactInfo.setArtifactLabel(artifactLabel);
1702
1703         return Either.left(ActionStatus.OK);
1704     }
1705
1706     private boolean validateLabelUniqueness(String componentId, Component parentComponent, String artifactLabel, ComponentTypeEnum componentType) {
1707         boolean isUnique = true;
1708         Either<Map<String, ArtifactDefinition>, StorageOperationStatus> artifacts;
1709         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1710             artifacts = artifactToscaOperation.getAllInstanceArtifacts(parentComponent.getUniqueId(), componentId);
1711         }
1712         else {
1713             artifacts = artifactToscaOperation.getArtifacts(componentId);
1714         }
1715
1716         if (artifacts.isLeft()) {
1717             for (String label : artifacts.left().value().keySet()) {
1718                 if (label.equals(artifactLabel)) {
1719                     isUnique = false;
1720                     break;
1721                 }
1722             }
1723         }
1724         if (componentType == ComponentTypeEnum.RESOURCE && isUnique) {
1725             isUnique = isUniqueLabelInResourceInterfaces(componentId, artifactLabel);
1726         }
1727         return isUnique;
1728     }
1729
1730     boolean validateArtifactNameUniqueness(String componentId, Component parentComponent, ArtifactDefinition artifactInfo,
1731                                            ComponentTypeEnum componentType) {
1732         Either<Map<String, ArtifactDefinition>, StorageOperationStatus> artifacts = getArtifacts(componentType,
1733                 parentComponent, componentId, artifactInfo.getArtifactGroupType());
1734         String artifactName = artifactInfo.getArtifactName();
1735         if (artifacts.isLeft() && Objects.nonNull(artifacts.left().value())){
1736             if (artifacts.left().value().values().stream()
1737                     .anyMatch(ad -> artifactName.equals(ad.getArtifactName())
1738                             //check whether it is the same artifact we hold (by label)
1739                             && !artifactInfo.getArtifactLabel().equals(ad.getArtifactLabel()))){
1740                 return false;
1741             }
1742         }
1743         if (ComponentTypeEnum.RESOURCE == componentType) {
1744             return isUniqueArtifactNameInResourceInterfaces(componentId, artifactName, artifactInfo.getArtifactLabel());
1745         }
1746         return true;
1747     }
1748
1749     private boolean isUniqueArtifactNameInResourceInterfaces(String componentId, String artifactName, String artifactLabel) {
1750         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> allInterfacesOfResource = interfaceLifecycleOperation
1751                 .getAllInterfacesOfResource(componentId, true, true);
1752
1753         if (allInterfacesOfResource.isLeft()){
1754             return allInterfacesOfResource.left().value()
1755                     .values()
1756                     .stream().map(InterfaceDefinition :: getOperationsMap)
1757                     .flatMap(map -> map.values().stream())
1758                     .map(OperationDataDefinition::getImplementation)
1759                     .filter(Objects::nonNull)
1760                     .noneMatch(add -> artifactName.equals(add.getArtifactName())
1761                             && !artifactLabel.equals(add.getArtifactLabel()));
1762         }
1763         return true;
1764     }
1765
1766     private boolean isUniqueLabelInResourceInterfaces(String componentId, String artifactLabel) {
1767         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> allInterfacesOfResource = interfaceLifecycleOperation
1768                 .getAllInterfacesOfResource(componentId, true, true);
1769
1770         if (allInterfacesOfResource.isLeft()){
1771             return allInterfacesOfResource.left().value()
1772                     .values()
1773                     .stream().map(InterfaceDefinition :: getOperationsMap)
1774                     .flatMap(map -> map.values().stream())
1775                     .map(OperationDataDefinition::getImplementation)
1776                     .filter(Objects::nonNull)
1777                     .noneMatch(add -> artifactLabel.equals(add.getArtifactLabel()));
1778         }
1779         return true;
1780     }
1781
1782     private Either<Map<String, ArtifactDefinition>, StorageOperationStatus> getArtifacts(ComponentTypeEnum componentType, Component parentComponent,
1783                                                                                          String componentId, ArtifactGroupTypeEnum artifactGroupType) {
1784         Either<Map<String, ArtifactDefinition>, StorageOperationStatus> artifactsResponse;
1785         if (componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1786             artifactsResponse = artifactToscaOperation.getAllInstanceArtifacts(parentComponent.getUniqueId(), componentId);
1787         }
1788         else {
1789             artifactsResponse = artifactToscaOperation.getArtifacts(componentId);
1790         }
1791         if (artifactsResponse.isRight() && artifactsResponse.right().value() == StorageOperationStatus.NOT_FOUND) {
1792             log.debug("failed to retrieve artifacts for {} ", componentId);
1793             return Either.right(artifactsResponse.right().value());
1794         }
1795         return Either.left(artifactsResponse.left().value().entrySet()
1796                 .stream()
1797                 .filter(x -> artifactGroupType == x.getValue().getArtifactGroupType())
1798                 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
1799     }
1800
1801     // ***************************************************************
1802
1803     private Either<ArtifactDefinition, Operation> createArtifact(Component parent, String parentId, ArtifactDefinition artifactInfo, byte[] decodedPayload,
1804                                                                  ComponentTypeEnum componentTypeEnum, AuditingActionEnum auditingActionEnum, String interfaceType, String operationName) {
1805
1806         DAOArtifactData artifactData = createEsArtifactData(artifactInfo, decodedPayload);
1807         if (artifactData == null) {
1808             BeEcompErrorManager.getInstance().logBeDaoSystemError("Upload Artifact");
1809             log.debug("Failed to create artifact object for ES.");
1810             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
1811         }
1812         ComponentInstance foundInstance = findComponentInstance(parentId, parent);
1813         String instanceId = null;
1814         if (foundInstance != null) {
1815             if (foundInstance.isArtifactExists(artifactInfo.getArtifactGroupType(), artifactInfo.getArtifactLabel())) {
1816                 log.debug("Failed to create artifact, already exists");
1817                 throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_EXIST, artifactInfo.getArtifactLabel());
1818             }
1819             instanceId = foundInstance.getUniqueId();
1820         }
1821         // set on graph object id of artifact in ES!
1822         artifactInfo.setEsId(artifactData.getId());
1823
1824         Either<ArtifactDefinition, Operation> operationResult;
1825         if (interfaceType != null && operationName != null) {
1826             // lifecycle artifact
1827             Operation operation = convertToOperation(artifactInfo, operationName);
1828             Either<Operation, StorageOperationStatus> result = interfaceLifecycleOperation.updateInterfaceOperation(parentId, interfaceType, operationName, operation);
1829             if (result.isRight()) {
1830                 throw new StorageException(result.right().value());
1831             }
1832             operationResult = Either.right(result.left().value());
1833         }
1834         else {
1835             // information/deployment/api artifacts
1836             NodeTypeEnum nodeType = convertParentType(componentTypeEnum);
1837             Either<ArtifactDefinition, StorageOperationStatus> result = artifactToscaOperation.addArtifactToComponent(
1838                     artifactInfo, parent, nodeType, true, instanceId);
1839             if (result.isRight()) {
1840                 throw new StorageException(result.right().value());
1841             }
1842             ArtifactDefinition artifactDefinition = result.left().value();
1843             artifactData.setId(artifactDefinition.getEsId());
1844             operationResult = Either.left(artifactDefinition);
1845
1846             if (generateCustomizationUUIDOnInstance(parent.getUniqueId(), parentId, componentTypeEnum) != StorageOperationStatus.OK) {
1847                 throw new StorageException(generateCustomizationUUIDOnInstance(parent.getUniqueId(), parentId, componentTypeEnum));
1848             }
1849         }
1850         saveArtifactInCassandra(artifactData, parent, artifactInfo, "", "", auditingActionEnum, componentTypeEnum);
1851         return operationResult;
1852     }
1853
1854     private ComponentInstance findComponentInstance(String componentInstanceId, Component containerComponent) {
1855         ComponentInstance foundInstance = null;
1856         if (CollectionUtils.isNotEmpty(containerComponent.getComponentInstances())) {
1857             foundInstance = containerComponent.getComponentInstances()
1858                     .stream()
1859                     .filter(i -> i.getUniqueId().equals(componentInstanceId))
1860                     .findFirst()
1861                     .orElse(null);
1862         }
1863         return foundInstance;
1864     }
1865
1866     private void validateDeploymentArtifact(final ArtifactDefinition artifactInfo, final Component component) {
1867         final ComponentTypeEnum componentType = component.getComponentType();
1868         if (componentType != ComponentTypeEnum.RESOURCE &&
1869             componentType != ComponentTypeEnum.SERVICE &&
1870             componentType != ComponentTypeEnum.RESOURCE_INSTANCE) {
1871             log.debug("Invalid component type '{}' for artifact. "
1872                 + "Expected Resource, Component or Resource Instance", componentType.getValue());
1873             throw new ByActionStatusComponentException(MISMATCH_BETWEEN_ARTIFACT_TYPE_AND_COMPONENT_TYPE,
1874                 componentType.getValue(), "Service, Resource or ResourceInstance", componentType.getValue());
1875         }
1876         final String artifactType = artifactInfo.getArtifactType();
1877         final ArtifactConfiguration artifactConfiguration = loadArtifactTypeConfig(artifactType).orElse(null);
1878         if (artifactConfiguration == null) {
1879             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED, artifactType);
1880         }
1881         validateArtifactType(componentType, artifactInfo.getArtifactGroupType(), artifactConfiguration);
1882         if (componentType == ComponentTypeEnum.RESOURCE || componentType == ComponentTypeEnum.RESOURCE_INSTANCE) {
1883             final Resource resource = (Resource) component;
1884             final ResourceTypeEnum resourceType = resource.getResourceType();
1885
1886             validateResourceType(resourceType, artifactInfo, artifactConfiguration.getResourceTypes());
1887         }
1888
1889         validateArtifactExtension(artifactConfiguration, artifactInfo);
1890     }
1891
1892     private void validateHeatArtifact(final Component parentComponent, final String componentId,
1893                                       final ArtifactDefinition artifactDefinition) {
1894         final String artifactType = artifactDefinition.getArtifactType();
1895         final ArtifactTypeEnum artifactTypeEnum = ArtifactTypeEnum.parse(artifactType);
1896         if (artifactTypeEnum == null) {
1897             return;
1898         }
1899
1900         switch (artifactTypeEnum) {
1901             case HEAT:
1902             case HEAT_VOL:
1903             case HEAT_NET:
1904                 validateHeatTimeoutValue(artifactDefinition);
1905                 break;
1906             case HEAT_ENV:
1907                 validateHeatEnvDeploymentArtifact(parentComponent, componentId, artifactDefinition);
1908                 break;
1909             default:
1910                 break;
1911         }
1912     }
1913
1914     private void setArtifactTimeout(final ArtifactDefinition newArtifactInfo,
1915                                     final ArtifactDefinition existingArtifactInfo) {
1916
1917         final String artifactType = newArtifactInfo.getArtifactType();
1918         final ArtifactTypeEnum artifactTypeEnum = ArtifactTypeEnum.parse(artifactType);
1919         if (artifactTypeEnum == null) {
1920             newArtifactInfo.setTimeout(NodeTemplateOperation.NON_HEAT_TIMEOUT);
1921             return;
1922         }
1923         switch (artifactTypeEnum) {
1924             case HEAT:
1925             case HEAT_VOL:
1926             case HEAT_NET:
1927                 if (newArtifactInfo.getTimeout() == null) {
1928                     if (existingArtifactInfo == null) {
1929                         newArtifactInfo.setTimeout(NodeTemplateOperation.getDefaultHeatTimeout());
1930                     } else {
1931                         newArtifactInfo.setTimeout(existingArtifactInfo.getTimeout());
1932                     }
1933                 }
1934                 break;
1935             default:
1936                 newArtifactInfo.setTimeout(NodeTemplateOperation.NON_HEAT_TIMEOUT);
1937                 break;
1938         }
1939     }
1940
1941     @VisibleForTesting
1942     void validateDeploymentArtifactTypeIsLegalForParent(ArtifactDefinition artifactInfo, ArtifactTypeEnum artifactType, Map<String, ArtifactTypeConfig> resourceDeploymentArtifacts) {
1943         if ((resourceDeploymentArtifacts == null) || !resourceDeploymentArtifacts.containsKey(artifactType.name())) {
1944             log.debug("Artifact Type: {} Not found !", artifactInfo.getArtifactType());
1945             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED, artifactInfo.getArtifactType());
1946         }
1947     }
1948
1949     Optional<ArtifactConfiguration> loadArtifactTypeConfig(final String artifactType) {
1950         if (artifactType == null) {
1951             return Optional.empty();
1952         }
1953         final List<ArtifactConfiguration> artifactConfigurationList =
1954             ConfigurationManager.getConfigurationManager().getConfiguration().getArtifacts();
1955         if (CollectionUtils.isEmpty(artifactConfigurationList)) {
1956             return Optional.empty();
1957         }
1958
1959         return artifactConfigurationList.stream()
1960             .filter(artifactConfiguration -> artifactConfiguration.getType().equalsIgnoreCase(artifactType))
1961             .findFirst();
1962     }
1963
1964     private Either<Boolean, ResponseFormat> extractHeatParameters(ArtifactDefinition artifactInfo) {
1965         // extract heat parameters
1966         if (artifactInfo.getPayloadData() != null) {
1967             String heatDecodedPayload = new String(Base64.decodeBase64(artifactInfo.getPayloadData()));
1968             Either<List<HeatParameterDefinition>, ResultStatusEnum> heatParameters = ImportUtils.getHeatParamsWithoutImplicitTypes(heatDecodedPayload, artifactInfo
1969                     .getArtifactType());
1970             if (heatParameters.isRight() && (heatParameters.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND)) {
1971                 log.info("failed to parse heat parameters ");
1972                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_DEPLOYMENT_ARTIFACT_HEAT, artifactInfo
1973                         .getArtifactType());
1974                 return Either.right(responseFormat);
1975             }
1976             else if (heatParameters.isLeft() && heatParameters.left().value() != null) {
1977                 artifactInfo.setListHeatParameters(heatParameters.left().value());
1978             }
1979         }
1980         return Either.left(true);
1981
1982     }
1983
1984     @VisibleForTesting
1985     void validateArtifactExtension(final ArtifactConfiguration artifactConfiguration,
1986                                    final ArtifactDefinition artifactDefinition) {
1987         final List<String> acceptedTypes = artifactConfiguration.getAcceptedTypes();
1988         /*
1989          * No need to check specific types. In case there are no acceptedTypes in configuration, then any type is accepted.
1990          */
1991         if (CollectionUtils.isEmpty(acceptedTypes)) {
1992             return;
1993         }
1994         final String artifactName = artifactDefinition.getArtifactName();
1995         final String fileExtension = FilenameUtils.getExtension(artifactName);
1996
1997         if (fileExtension == null || !acceptedTypes.contains(fileExtension.toLowerCase())) {
1998             final String artifactType = artifactDefinition.getArtifactType();
1999             log.debug("File extension \"{}\" is not allowed for artifact type \"{}\"", fileExtension, artifactType);
2000             throw new ByActionStatusComponentException(ActionStatus.WRONG_ARTIFACT_FILE_EXTENSION, artifactType);
2001         }
2002     }
2003
2004     @VisibleForTesting
2005     void validateHeatEnvDeploymentArtifact(final Component parentComponent, final String parentId,
2006                                            final ArtifactDefinition artifactInfo) {
2007         final Wrapper<ArtifactDefinition> heatMDWrapper = new Wrapper<>();
2008         final Wrapper<byte[]> payloadWrapper = new Wrapper<>();
2009
2010         validateYaml(artifactInfo);
2011         validateHeatExist(parentComponent.getUniqueId(), parentId, heatMDWrapper, artifactInfo, parentComponent.getComponentType());
2012
2013         if (!heatMDWrapper.isEmpty()) {
2014             fillArtifactPayload(payloadWrapper, heatMDWrapper.getInnerElement());
2015         }
2016
2017         if (!heatMDWrapper.isEmpty()) {
2018             validateEnvVsHeat(artifactInfo, heatMDWrapper.getInnerElement(), payloadWrapper.getInnerElement());
2019         }
2020     }
2021
2022     public void fillArtifactPayload(Wrapper<byte[]> payloadWrapper, ArtifactDefinition artifactDefinition) {
2023         if (ArrayUtils.isEmpty(artifactDefinition.getPayloadData())) {
2024             Either<DAOArtifactData, CassandraOperationStatus> eitherArtifactData = artifactCassandraDao.getArtifact(artifactDefinition.getEsId());
2025             if (eitherArtifactData.isLeft()) {
2026                 byte[] data = eitherArtifactData.left().value().getDataAsArray();
2027                 payloadWrapper.setInnerElement(Base64.encodeBase64(data));
2028             }
2029             else {
2030                 log.debug("Error getting payload for artifact:{}", artifactDefinition.getArtifactName());
2031                 throw new StorageException(DaoStatusConverter.convertCassandraStatusToStorageStatus(eitherArtifactData.right().value()));
2032             }
2033         }
2034         else {
2035             payloadWrapper.setInnerElement(artifactDefinition.getPayloadData());
2036         }
2037     }
2038
2039     private void validateEnvVsHeat(ArtifactDefinition envArtifact, ArtifactDefinition heatArtifact, byte[] heatPayloadData) {
2040         String envPayload = new String(Base64.decodeBase64(envArtifact.getPayloadData()));
2041         Map<String, Object> heatEnvToscaJson = (Map<String, Object>) new Yaml().load(envPayload);
2042         String heatDecodedPayload = new String(Base64.decodeBase64(heatPayloadData));
2043         Map<String, Object> heatToscaJson = (Map<String, Object>) new Yaml().load(heatDecodedPayload);
2044
2045         Either<Map<String, Object>, ResultStatusEnum> eitherHeatEnvProperties = ImportUtils.findFirstToscaMapElement(heatEnvToscaJson, TypeUtils.ToscaTagNamesEnum.PARAMETERS);
2046         if (eitherHeatEnvProperties.isRight()) {
2047             log.debug("Invalid heat env format for file:{}", envArtifact.getArtifactName());
2048             throw new ByActionStatusComponentException(ActionStatus.CORRUPTED_FORMAT, "Heat Env");
2049         }
2050         Either<Map<String, Object>, ResultStatusEnum> eitherHeatProperties = ImportUtils.findFirstToscaMapElement(heatToscaJson, TypeUtils.ToscaTagNamesEnum.PARAMETERS);
2051         if (eitherHeatProperties.isRight()) {
2052             log.debug("Invalid heat format for file:{}", heatArtifact.getArtifactName());
2053             throw new ByActionStatusComponentException(ActionStatus.CORRUPTED_FORMAT, "Heat");
2054         }
2055         Set<String> heatPropertiesKeys = eitherHeatProperties.left().value().keySet();
2056         Set<String> heatEnvPropertiesKeys = eitherHeatEnvProperties.left().value().keySet();
2057         heatEnvPropertiesKeys.removeAll(heatPropertiesKeys);
2058         if (!heatEnvPropertiesKeys.isEmpty()) {
2059             log.debug("Validation of heat_env for artifact:{} vs heat artifact for artifact :{} failed", envArtifact.getArtifactName(), heatArtifact.getArtifactName());
2060             throw new ByActionStatusComponentException(ActionStatus.MISMATCH_HEAT_VS_HEAT_ENV, envArtifact.getArtifactName(), heatArtifact.getArtifactName());
2061         }
2062     }
2063
2064     private void validateYaml(ArtifactDefinition artifactInfo) {
2065         YamlToObjectConverter yamlConverter = new YamlToObjectConverter();
2066         boolean isYamlValid = yamlConverter.isValidYamlEncoded64(artifactInfo.getPayloadData());
2067         if (!isYamlValid) {
2068             log.debug("Yaml is not valid for artifact : {}", artifactInfo.getArtifactName());
2069             throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML, artifactInfo.getArtifactType());
2070         }
2071     }
2072
2073     private boolean isValidXml(byte[] xmlToParse) {
2074         boolean isXmlValid = true;
2075         try {
2076             SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
2077             saxParser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
2078             saxParser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
2079             XMLReader reader = saxParser.getXMLReader();
2080             setFeatures(reader);
2081             reader.parse(new InputSource(new ByteArrayInputStream(xmlToParse)));
2082         }
2083         catch (ParserConfigurationException | IOException | SAXException e) {
2084             log.debug("Xml is invalid : {}", e.getMessage(), e);
2085             isXmlValid = false;
2086         }
2087         return isXmlValid;
2088     }
2089
2090     private void setFeatures(XMLReader reader) throws SAXNotSupportedException {
2091         try {
2092             reader.setFeature("http://apache.org/xml/features/validation/schema", false);
2093             reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
2094         }
2095         catch (SAXNotRecognizedException e) {
2096             log.debug("Xml parser couldn't set feature: \"http://apache.org/xml/features/validation/schema\", false", e.getMessage(), e);
2097         }
2098     }
2099
2100     private void validateSingleDeploymentArtifactName(final String artifactName, final Component parentComponent) {
2101         boolean artifactNameFound = false;
2102         final Iterator<ArtifactDefinition> parentDeploymentArtifactsItr =
2103             getDeploymentArtifacts(parentComponent, null).iterator();
2104
2105         while (!artifactNameFound && parentDeploymentArtifactsItr.hasNext()) {
2106             artifactNameFound = artifactName.equalsIgnoreCase(parentDeploymentArtifactsItr.next().getArtifactName());
2107         }
2108         if (artifactNameFound) {
2109             final ComponentTypeEnum componentType = parentComponent.getComponentType();
2110             log.debug("Can't upload artifact: {}, because another artifact with this name already exist.", artifactName);
2111             throw new ByActionStatusComponentException(ActionStatus.DEPLOYMENT_ARTIFACT_NAME_ALREADY_EXISTS,
2112                 componentType.getValue(), parentComponent.getName(), artifactName);
2113         }
2114     }
2115
2116     private void validateHeatExist(String componentId, String parentRiId, Wrapper<ArtifactDefinition> heatArtifactMDWrapper, ArtifactDefinition heatEnvArtifact,
2117                                    ComponentTypeEnum componentType) {
2118         final Either<ArtifactDefinition, StorageOperationStatus> res = artifactToscaOperation
2119             .getHeatArtifactByHeatEnvId(parentRiId, heatEnvArtifact, componentId, componentType);
2120         if (res.isRight()) {
2121             throw new ByActionStatusComponentException(ActionStatus.MISSING_HEAT);
2122         }
2123
2124         heatArtifactMDWrapper.setInnerElement(res.left().value());
2125     }
2126
2127     @VisibleForTesting
2128     void validateHeatTimeoutValue(final ArtifactDefinition artifactInfo) {
2129         log.trace("Started HEAT pre-payload validation for artifact {}", artifactInfo.getArtifactLabel());
2130         // timeout > 0 for HEAT artifacts
2131         if (artifactInfo.getTimeout() == null || artifactInfo.getTimeout() < 1) {
2132             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_INVALID_TIMEOUT);
2133         }
2134         // US649856 - Allow several HEAT files on Resource
2135         log.trace("Ended HEAT validation for artifact {}", artifactInfo.getArtifactLabel());
2136     }
2137
2138     @VisibleForTesting
2139     void validateResourceType(final ResourceTypeEnum resourceType, final ArtifactDefinition artifactInfo,
2140                               final List<String> typeList) {
2141         if (CollectionUtils.isEmpty(typeList) || typeList.contains(resourceType.getValue())) {
2142             return;
2143         }
2144         final String listToString = typeList.stream().collect(Collectors.joining(", "));
2145         throw new ByActionStatusComponentException(MISMATCH_BETWEEN_ARTIFACT_TYPE_AND_COMPONENT_TYPE,
2146             artifactInfo.getArtifactGroupType().getType(), listToString, resourceType.getValue());
2147     }
2148
2149     @VisibleForTesting
2150     Either<ArtifactDefinition, ResponseFormat> validateAndConvertHeatParameters(ArtifactDefinition artifactInfo, String artifactType) {
2151         if (artifactInfo.getHeatParameters() != null) {
2152             for (HeatParameterDefinition heatParam : artifactInfo.getListHeatParameters()) {
2153                 String parameterType = heatParam.getType();
2154                 HeatParameterType heatParameterType = HeatParameterType.isValidType(parameterType);
2155                 String artifactTypeStr = artifactType != null ? artifactType : ArtifactTypeEnum.HEAT.getType();
2156                 if (heatParameterType == null) {
2157                     ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_HEAT_PARAMETER_TYPE, artifactTypeStr, heatParam
2158                             .getType());
2159                     return Either.right(responseFormat);
2160                 }
2161
2162                 StorageOperationStatus validateAndUpdateProperty = heatParametersOperation.validateAndUpdateProperty(heatParam);
2163                 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
2164                     log.debug("Heat parameter {} is invalid. Status is {}", heatParam.getName(), validateAndUpdateProperty);
2165                     ActionStatus status = ActionStatus.INVALID_HEAT_PARAMETER_VALUE;
2166                     ResponseFormat responseFormat = componentsUtils.getResponseFormat(status, artifactTypeStr, heatParam
2167                             .getType(), heatParam.getName());
2168                     return Either.right(responseFormat);
2169                 }
2170             }
2171         }
2172         return Either.left(artifactInfo);
2173     }
2174
2175     public List<ArtifactDefinition> getDeploymentArtifacts(final Component component, final String ciId) {
2176         final ComponentTypeEnum componentType = component.getComponentType();
2177         if (component.getDeploymentArtifacts() == null) {
2178             return Collections.emptyList();
2179         }
2180         final List<ArtifactDefinition> deploymentArtifacts = new ArrayList<>();
2181         if (ComponentTypeEnum.RESOURCE == componentType && ciId != null) {
2182             final Either<ComponentInstance, ResponseFormat> getRI =
2183                 getRIFromComponent(component, ciId, null, null, null);
2184             if (getRI.isRight()) {
2185                 return Collections.emptyList();
2186             }
2187             final ComponentInstance ri = getRI.left().value();
2188             if (ri.getDeploymentArtifacts() != null) {
2189                 deploymentArtifacts.addAll(ri.getDeploymentArtifacts().values());
2190             }
2191         } else {
2192             deploymentArtifacts.addAll(component.getDeploymentArtifacts().values());
2193         }
2194         return deploymentArtifacts;
2195     }
2196
2197     private void checkCreateFields(User user, ArtifactDefinition artifactInfo, ArtifactGroupTypeEnum type) {
2198         // on create if null add informational to current
2199         if (artifactInfo.getArtifactGroupType() == null) {
2200             artifactInfo.setArtifactGroupType(type);
2201         }
2202         if (artifactInfo.getUniqueId() != null) {
2203             log.error("artifact uniqid cannot be set ignoring");
2204         }
2205         artifactInfo.setUniqueId(null);
2206
2207         if (artifactInfo.getArtifactRef() != null) {
2208             log.error("artifact ref cannot be set ignoring");
2209         }
2210         artifactInfo.setArtifactRef(null);
2211
2212         if (artifactInfo.getArtifactRepository() != null) {
2213             log.error("artifact repository cannot be set ignoring");
2214         }
2215         artifactInfo.setArtifactRepository(null);
2216
2217         if (artifactInfo.getUserIdCreator() != null) {
2218             log.error("creator uuid cannot be set ignoring");
2219         }
2220         artifactInfo.setArtifactCreator(user.getUserId());
2221
2222         if (artifactInfo.getUserIdLastUpdater() != null) {
2223             log.error("userId of last updater cannot be set ignoring");
2224         }
2225         artifactInfo.setUserIdLastUpdater(user.getUserId());
2226
2227         if (artifactInfo.getCreatorFullName() != null) {
2228             log.error("creator Full name cannot be set ignoring");
2229         }
2230         String fullName = user.getFirstName() + " " + user.getLastName();
2231         artifactInfo.setUpdaterFullName(fullName);
2232
2233         if (artifactInfo.getUpdaterFullName() != null) {
2234             log.error("updater Full name cannot be set ignoring");
2235         }
2236         artifactInfo.setUpdaterFullName(fullName);
2237
2238         if (artifactInfo.getCreationDate() != null) {
2239             log.error("Creation Date cannot be set ignoring");
2240         }
2241         long time = System.currentTimeMillis();
2242         artifactInfo.setCreationDate(time);
2243
2244         if (artifactInfo.getLastUpdateDate() != null) {
2245             log.error("Last Update Date cannot be set ignoring");
2246         }
2247         artifactInfo.setLastUpdateDate(time);
2248
2249         if (artifactInfo.getEsId() != null) {
2250             log.error("es id cannot be set ignoring");
2251         }
2252         artifactInfo.setEsId(null);
2253
2254     }
2255
2256
2257     private String composeArtifactId(String resourceId, String artifactId, ArtifactDefinition artifactInfo, String interfaceName, String operationName) {
2258         String id = artifactId;
2259         if (artifactId == null || artifactId.isEmpty()) {
2260             String uniqueId = null;
2261             if (interfaceName != null && operationName != null) {
2262                 uniqueId = UniqueIdBuilder.buildArtifactByInterfaceUniqueId(resourceId, interfaceName, operationName, artifactInfo
2263                         .getArtifactLabel());
2264             }
2265             else {
2266                 uniqueId = UniqueIdBuilder.buildPropertyUniqueId(resourceId, artifactInfo.getArtifactLabel());
2267             }
2268             artifactInfo.setUniqueId(uniqueId);
2269             artifactInfo.setEsId(uniqueId);
2270             id = uniqueId;
2271         }
2272         else {
2273             artifactInfo.setUniqueId(artifactId);
2274             artifactInfo.setEsId(artifactId);
2275         }
2276         return id;
2277     }
2278
2279     private Either<Boolean, ResponseFormat> validateFirstUpdateHasPayload(ArtifactDefinition artifactInfo, ArtifactDefinition currentArtifact) {
2280         if (currentArtifact.getEsId() == null && (artifactInfo.getPayloadData() == null || artifactInfo.getPayloadData().length == 0)) {
2281             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_PAYLOAD));
2282         }
2283         return Either.left(true);
2284
2285     }
2286
2287     @VisibleForTesting
2288     Either<Boolean, ResponseFormat> validateAndSetArtifactName(ArtifactDefinition artifactInfo) {
2289         if (artifactInfo.getArtifactName() == null || artifactInfo.getArtifactName().isEmpty()) {
2290             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_ARTIFACT_NAME));
2291         }
2292         String normalizeFileName = ValidationUtils.normalizeFileName(artifactInfo.getArtifactName());
2293         if (normalizeFileName == null || normalizeFileName.isEmpty()) {
2294             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_ARTIFACT_NAME));
2295         }
2296         artifactInfo.setArtifactName(normalizeFileName);
2297
2298         if (!ValidationUtils.validateArtifactNameLength(artifactInfo.getArtifactName())) {
2299             return Either.right(componentsUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, ARTIFACT_NAME, String.valueOf(ValidationUtils.ARTIFACT_NAME_LENGTH)));
2300         }
2301
2302         return Either.left(true);
2303     }
2304
2305     private void validateArtifactTypeNotChanged(ArtifactDefinition artifactInfo, ArtifactDefinition currentArtifact) {
2306         if (StringUtils.isEmpty(artifactInfo.getArtifactType())) {
2307             log.info("artifact type is missing operation ignored");
2308             throw new ByActionStatusComponentException(ActionStatus.MISSING_ARTIFACT_TYPE);
2309         }
2310
2311         if (!currentArtifact.getArtifactType().equalsIgnoreCase(artifactInfo.getArtifactType())) {
2312             log.info("artifact type cannot be changed operation ignored");
2313             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
2314         }
2315     }
2316
2317     private Either<ArtifactDefinition, ResponseFormat> validateOrSetArtifactGroupType(ArtifactDefinition artifactInfo, ArtifactDefinition currentArtifact) {
2318
2319         if (Objects.nonNull(artifactInfo) && Objects.nonNull(currentArtifact)) {
2320             if (artifactInfo.getArtifactGroupType() == null) {
2321                 artifactInfo.setArtifactGroupType(currentArtifact.getArtifactGroupType());
2322             } else if (!currentArtifact.getArtifactGroupType()
2323                     .getType()
2324                     .equalsIgnoreCase(artifactInfo.getArtifactGroupType().getType())) {
2325                 log.info("artifact group type cannot be changed. operation failed");
2326                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
2327             }
2328         }
2329         return Either.left(artifactInfo);
2330     }
2331
2332     private void checkAndSetUnUpdatableFields(User user, ArtifactDefinition artifactInfo, ArtifactDefinition currentArtifact, ArtifactGroupTypeEnum type) {
2333
2334         // on update if null add informational to current
2335         if (currentArtifact.getArtifactGroupType() == null && type != null) {
2336             currentArtifact.setArtifactGroupType(type);
2337         }
2338
2339         if (artifactInfo.getUniqueId() != null && !currentArtifact.getUniqueId().equals(artifactInfo.getUniqueId())) {
2340             log.error("artifact uniqid cannot be set ignoring");
2341         }
2342         artifactInfo.setUniqueId(currentArtifact.getUniqueId());
2343
2344         if (artifactInfo.getArtifactRef() != null && !currentArtifact.getArtifactRef()
2345                 .equals(artifactInfo.getArtifactRef())) {
2346             log.error("artifact ref cannot be set ignoring");
2347         }
2348         artifactInfo.setArtifactRef(currentArtifact.getArtifactRef());
2349
2350         if (artifactInfo.getArtifactRepository() != null && !currentArtifact.getArtifactRepository()
2351                 .equals(artifactInfo.getArtifactRepository())) {
2352             log.error("artifact repository cannot be set ignoring");
2353         }
2354         artifactInfo.setArtifactRepository(currentArtifact.getArtifactRepository());
2355
2356         if (artifactInfo.getUserIdCreator() != null && !currentArtifact.getUserIdCreator()
2357                 .equals(artifactInfo.getUserIdCreator())) {
2358             log.error("creator uuid cannot be set ignoring");
2359         }
2360         artifactInfo.setUserIdCreator(currentArtifact.getUserIdCreator());
2361
2362         if (artifactInfo.getArtifactCreator() != null && !currentArtifact.getArtifactCreator()
2363                 .equals(artifactInfo.getArtifactCreator())) {
2364             log.error("artifact creator cannot be set ignoring");
2365         }
2366         artifactInfo.setArtifactCreator(currentArtifact.getArtifactCreator());
2367
2368         if (artifactInfo.getUserIdLastUpdater() != null && !currentArtifact.getUserIdLastUpdater()
2369                 .equals(artifactInfo.getUserIdLastUpdater())) {
2370             log.error("userId of last updater cannot be set ignoring");
2371         }
2372         artifactInfo.setUserIdLastUpdater(user.getUserId());
2373
2374         if (artifactInfo.getCreatorFullName() != null && !currentArtifact.getCreatorFullName()
2375                 .equals(artifactInfo.getCreatorFullName())) {
2376             log.error("creator Full name cannot be set ignoring");
2377         }
2378         artifactInfo.setCreatorFullName(currentArtifact.getCreatorFullName());
2379
2380         if (artifactInfo.getUpdaterFullName() != null && !currentArtifact.getUpdaterFullName()
2381                 .equals(artifactInfo.getUpdaterFullName())) {
2382             log.error("updater Full name cannot be set ignoring");
2383         }
2384         String fullName = user.getFirstName() + " " + user.getLastName();
2385         artifactInfo.setUpdaterFullName(fullName);
2386
2387         if (artifactInfo.getCreationDate() != null && !currentArtifact.getCreationDate()
2388                 .equals(artifactInfo.getCreationDate())) {
2389             log.error("Creation Date cannot be set ignoring");
2390         }
2391         artifactInfo.setCreationDate(currentArtifact.getCreationDate());
2392
2393         if (artifactInfo.getLastUpdateDate() != null && !currentArtifact.getLastUpdateDate()
2394                 .equals(artifactInfo.getLastUpdateDate())) {
2395             log.error("Last Update Date cannot be set ignoring");
2396         }
2397         long time = System.currentTimeMillis();
2398         artifactInfo.setLastUpdateDate(time);
2399
2400         if (artifactInfo.getEsId() != null && !currentArtifact.getEsId().equals(artifactInfo.getEsId())) {
2401             log.error("es id cannot be set ignoring");
2402         }
2403         artifactInfo.setEsId(currentArtifact.getUniqueId());
2404
2405         if (artifactInfo.getArtifactDisplayName() != null && !currentArtifact.getArtifactDisplayName()
2406                 .equals(artifactInfo.getArtifactDisplayName())) {
2407             log.error(" Artifact Display Name cannot be set ignoring");
2408         }
2409         artifactInfo.setArtifactDisplayName(currentArtifact.getArtifactDisplayName());
2410
2411         if (artifactInfo.getServiceApi() != null && !currentArtifact.getServiceApi()
2412                 .equals(artifactInfo.getServiceApi())) {
2413             log.debug("serviceApi cannot be set. ignoring.");
2414         }
2415         artifactInfo.setServiceApi(currentArtifact.getServiceApi());
2416
2417         if (artifactInfo.getArtifactGroupType() != null && currentArtifact.getArtifactGroupType() != artifactInfo.getArtifactGroupType()) {
2418             log.debug("artifact group cannot be set. ignoring.");
2419         }
2420         artifactInfo.setArtifactGroupType(currentArtifact.getArtifactGroupType());
2421
2422         artifactInfo.setArtifactVersion(currentArtifact.getArtifactVersion());
2423
2424         if (artifactInfo.getArtifactUUID() != null && !artifactInfo.getArtifactUUID()
2425                 .isEmpty() && !currentArtifact.getArtifactUUID()
2426                 .equals(artifactInfo.getArtifactUUID())) {
2427             log.debug("artifact UUID cannot be set. ignoring.");
2428         }
2429         artifactInfo.setArtifactUUID(currentArtifact.getArtifactUUID());
2430
2431         if ((artifactInfo.getHeatParameters() != null) && (currentArtifact.getHeatParameters() != null) && !artifactInfo
2432                 .getHeatParameters()
2433                 .isEmpty() && !currentArtifact.getHeatParameters().isEmpty()) {
2434             checkAndSetUnupdatableHeatParams(artifactInfo.getListHeatParameters(), currentArtifact.getListHeatParameters());
2435         }
2436     }
2437
2438     private void checkAndSetUnupdatableHeatParams(List<HeatParameterDefinition> heatParameters, List<HeatParameterDefinition> currentParameters) {
2439
2440         Map<String, HeatParameterDefinition> currentParametersMap = getMapOfParameters(currentParameters);
2441         for (HeatParameterDefinition parameter : heatParameters) {
2442             HeatParameterDefinition currentParam = currentParametersMap.get(parameter.getUniqueId());
2443
2444             if (currentParam != null) {
2445
2446                 if (parameter.getName() != null && !parameter.getName().equalsIgnoreCase(currentParam.getName())) {
2447                     log.debug("heat parameter name cannot be updated  ({}). ignoring.", parameter.getName());
2448                     parameter.setName(currentParam.getName());
2449                 }
2450                 if (parameter.getDefaultValue() != null && !parameter.getDefaultValue()
2451                         .equalsIgnoreCase(currentParam.getDefaultValue())) {
2452                     log.debug("heat parameter defaultValue cannot be updated  ({}). ignoring.", parameter.getDefaultValue());
2453                     parameter.setDefaultValue(currentParam.getDefaultValue());
2454                 }
2455                 if (parameter.getType() != null && !parameter.getType().equalsIgnoreCase(currentParam.getType())) {
2456                     log.debug("heat parameter type cannot be updated  ({}). ignoring.", parameter.getType());
2457                     parameter.setType(currentParam.getType());
2458                 }
2459                 if (parameter.getDescription() != null && !parameter.getDescription()
2460                         .equalsIgnoreCase(currentParam.getDescription())) {
2461                     log.debug("heat parameter description cannot be updated  ({}). ignoring.", parameter.getDescription());
2462                     parameter.setDescription(currentParam.getDescription());
2463                 }
2464
2465                 // check and set current value
2466                 if ((parameter.getCurrentValue() == null) && (currentParam.getDefaultValue() != null)) {
2467                     log.debug("heat parameter current value is null. set it to default value {}). ignoring.", parameter.getDefaultValue());
2468                     parameter.setCurrentValue(currentParam.getDefaultValue());
2469                 }
2470             }
2471         }
2472     }
2473
2474     private Map<String, HeatParameterDefinition> getMapOfParameters(List<HeatParameterDefinition> currentParameters) {
2475
2476         Map<String, HeatParameterDefinition> currentParamsMap = new HashMap<>();
2477         for (HeatParameterDefinition param : currentParameters) {
2478             currentParamsMap.put(param.getUniqueId(), param);
2479         }
2480         return currentParamsMap;
2481     }
2482
2483     private Either<Boolean, ResponseFormat> validateAndServiceApiUrl(ArtifactDefinition artifactInfo) {
2484         if (!ValidationUtils.validateStringNotEmpty(artifactInfo.getApiUrl())) {
2485             log.debug("Artifact url cannot be empty.");
2486             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_URL));
2487         }
2488         artifactInfo.setApiUrl(artifactInfo.getApiUrl().toLowerCase());
2489
2490         if (!ValidationUtils.validateUrl(artifactInfo.getApiUrl())) {
2491             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_SERVICE_API_URL));
2492         }
2493         if (!ValidationUtils.validateUrlLength(artifactInfo.getApiUrl())) {
2494             return Either.right(componentsUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, ARTIFACT_URL, String.valueOf(ValidationUtils.API_URL_LENGTH)));
2495         }
2496
2497         return Either.left(true);
2498     }
2499
2500     private Either<Boolean, ResponseFormat> validateAndCleanDescription(ArtifactDefinition artifactInfo) {
2501         if (artifactInfo.getDescription() == null || artifactInfo.getDescription().isEmpty()) {
2502             log.debug("Artifact description cannot be empty.");
2503             return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_DESCRIPTION));
2504         }
2505         String description = artifactInfo.getDescription();
2506         description = ValidationUtils.removeNoneUtf8Chars(description);
2507         description = ValidationUtils.normaliseWhitespace(description);
2508         description = ValidationUtils.stripOctets(description);
2509         description = ValidationUtils.removeHtmlTagsOnly(description);
2510         if (!ValidationUtils.validateIsEnglish(description)) {
2511             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
2512         }
2513         if (!ValidationUtils.validateLength(description, ValidationUtils.ARTIFACT_DESCRIPTION_MAX_LENGTH)) {
2514             return Either.right(componentsUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, ARTIFACT_DESCRIPTION, String
2515                     .valueOf(ValidationUtils.ARTIFACT_DESCRIPTION_MAX_LENGTH)));
2516         }
2517         artifactInfo.setDescription(description);
2518         return Either.left(true);
2519     }
2520
2521     private <T> Either<ArtifactDefinition, T> updateArtifactFlow(Component parent, String parentId, String artifactId,
2522         ArtifactDefinition artifactInfo, byte[] decodedPayload,
2523         ComponentTypeEnum componentType, AuditingActionEnum auditingAction) {
2524         DAOArtifactData artifactData = createEsArtifactData(artifactInfo, decodedPayload);
2525         if (artifactData == null) {
2526             BeEcompErrorManager.getInstance().logBeDaoSystemError(UPDATE_ARTIFACT);
2527             log.debug("Failed to create artifact object for ES.");
2528             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
2529         }
2530         log.debug("Entry on graph is updated. Update artifact in ES");
2531         // Changing previous and current artifactId for auditing
2532         String currArtifactId = artifactInfo.getUniqueId();
2533
2534         NodeTypeEnum parentType = convertParentType(componentType);
2535
2536         if (decodedPayload == null) {
2537             if (!artifactInfo.getMandatory() || artifactInfo.getEsId() != null) {
2538                 Either<DAOArtifactData, CassandraOperationStatus> artifactFromCassandra = artifactCassandraDao.getArtifact(artifactInfo.getEsId());
2539                 if (artifactFromCassandra.isRight()) {
2540                     throw new StorageException(artifactFromCassandra.right().value());
2541                 }
2542                 // clone data to new artifact
2543                 artifactData.setData(artifactFromCassandra.left().value().getData());
2544                 artifactData.setId(artifactFromCassandra.left().value().getId());
2545             }
2546         } else if (artifactInfo.getEsId() == null) {
2547             artifactInfo.setEsId(artifactInfo.getUniqueId());
2548             artifactData.setId(artifactInfo.getUniqueId());
2549         }
2550
2551         Either<ArtifactDefinition, StorageOperationStatus> result = artifactToscaOperation.updateArtifactOnResource(artifactInfo,
2552                 parent, artifactId, parentType, parentId, true);
2553         if (result.isRight()) {
2554             throw new StorageException(result.right().value());
2555         }
2556         ArtifactDefinition artifactDefinition = result.left().value();
2557         updateGeneratedIdInHeatEnv(parent, parentId, artifactId, artifactInfo, artifactDefinition, parentType);
2558
2559         StorageOperationStatus storageOperationStatus = generateCustomizationUUIDOnInstance(parent.getUniqueId(), parentId, componentType);
2560         if (storageOperationStatus != StorageOperationStatus.OK) {
2561             throw new StorageException(storageOperationStatus);
2562         }
2563         if (artifactData.getData() != null) {
2564             if (!artifactDefinition.getDuplicated() || artifactData.getId() == null) {
2565                 artifactData.setId(artifactDefinition.getEsId());
2566             }
2567             saveArtifactInCassandra(artifactData, parent, artifactInfo, currArtifactId, artifactId, auditingAction, componentType);
2568         }
2569         return Either.left(artifactDefinition);
2570     }
2571
2572     private String updateGeneratedIdInHeatEnv(Component parent, String parentId, String artifactId, ArtifactDefinition artifactInfo, ArtifactDefinition artifactDefinition, NodeTypeEnum parentType) {
2573         if (NodeTypeEnum.Resource == parentType) {
2574             return updateGeneratedIdInHeatEnv(parent.getDeploymentArtifacts(), parent, parentId, artifactId, artifactInfo, artifactDefinition, parentType, false);
2575         }
2576         return artifactDefinition.getUniqueId();
2577     }
2578
2579     private String updateGeneratedIdInHeatEnv(Map<String, ArtifactDefinition> deploymentArtifacts, Component parentComponent, String parentId, String artifactId, ArtifactDefinition artifactInfo, ArtifactDefinition artifactDefinition, NodeTypeEnum parentType, boolean isInstanceArtifact) {
2580         String artifactUniqueId;
2581         artifactUniqueId = artifactDefinition.getUniqueId();
2582         String artifactType = artifactInfo.getArtifactType();
2583         if ((ArtifactTypeEnum.HEAT.getType().equalsIgnoreCase(artifactType) ||
2584                 ArtifactTypeEnum.HEAT_VOL.getType().equalsIgnoreCase(artifactType) ||
2585                 ArtifactTypeEnum.HEAT_NET.getType().equalsIgnoreCase(artifactType))
2586                 && !artifactUniqueId.equals(artifactId)) {
2587             // need to update the generated id in heat env
2588             Optional<Entry<String, ArtifactDefinition>> findFirst = deploymentArtifacts.entrySet()
2589                     .stream()
2590                     .filter(a -> artifactId.equals(a.getValue().getGeneratedFromId()))
2591                     .findFirst();
2592             if (findFirst.isPresent()) {
2593                 ArtifactDefinition artifactEnvInfo = findFirst.get().getValue();
2594                 artifactEnvInfo.setIsFromCsar(artifactDefinition.getIsFromCsar());
2595                 artifactEnvInfo.setArtifactChecksum(null);
2596                 if (isInstanceArtifact) {
2597                     artifactToscaOperation.updateHeatEnvArtifactOnInstance(parentComponent, artifactEnvInfo, artifactId, artifactUniqueId, parentType, parentId);
2598                 } else {
2599                     artifactToscaOperation.updateHeatEnvArtifact(parentComponent, artifactEnvInfo, artifactId, artifactUniqueId, parentType, parentId);
2600                 }
2601             }
2602         }
2603         return artifactUniqueId;
2604     }
2605
2606     private String updateGeneratedIdInHeatEnvOnInstance(ComponentInstance parent, Component parentComponent, String artifactId, ArtifactDefinition artifactInfo, ArtifactDefinition artifactDefinition, NodeTypeEnum parentType) {
2607         return updateGeneratedIdInHeatEnv(parent.getDeploymentArtifacts(), parentComponent, parent.getUniqueId(),artifactId, artifactInfo, artifactDefinition, parentType, true);
2608     }
2609
2610     @VisibleForTesting
2611     private Either<byte[], ResponseFormat> handlePayload(ArtifactDefinition artifactInfo, boolean isArtifactMetadataUpdate) {
2612         log.trace("Starting payload handling");
2613         byte[] payload = artifactInfo.getPayloadData();
2614         byte[] decodedPayload = null;
2615
2616         if (payload != null && payload.length != 0) {
2617             // the generated artifacts were already decoded by the handler
2618             decodedPayload = artifactInfo.getGenerated() ? payload : Base64.decodeBase64(payload);
2619             if (decodedPayload.length == 0) {
2620                 log.debug("Failed to decode the payload.");
2621                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
2622                 return Either.right(responseFormat);
2623             }
2624
2625             String checkSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(decodedPayload);
2626             artifactInfo.setArtifactChecksum(checkSum);
2627             log.trace("Calculated checksum, base64 payload: {},  checksum: {}", payload, checkSum);
2628
2629             // Specific payload validations of different types
2630             Either<Boolean, ResponseFormat> result = Either.left(true);
2631             if (isDeploymentArtifact(artifactInfo)) {
2632                 log.trace("Starting deployment artifacts payload validation");
2633                 String artifactType = artifactInfo.getArtifactType();
2634                 String fileExtension = GeneralUtility.getFilenameExtension(artifactInfo.getArtifactName());
2635                 PayloadTypeEnum payloadType = ArtifactTypeToPayloadTypeSelector.getPayloadType(artifactType, fileExtension);
2636                 Either<Boolean, ActionStatus> isPayloadValid = payloadType.isValid(decodedPayload);
2637                 if (isPayloadValid.isRight()) {
2638                     ResponseFormat responseFormat = componentsUtils.getResponseFormat(isPayloadValid.right().value(), artifactType);
2639                     return Either.right(responseFormat);
2640                 }
2641
2642                 if (payloadType.isHeatRelated()) {
2643                     log.trace("Payload is heat related so going to extract heat parameters for artifact type {}", artifactType);
2644                     result = extractHeatParameters(artifactInfo);
2645                 }
2646             }
2647             if (result.isRight()) {
2648                 return Either.right(result.right().value());
2649             }
2650
2651         } // null/empty payload is normal if called from metadata update ONLY.
2652         // The validation of whether this is metadata/payload update case is
2653         // currently done separately
2654         else {
2655             if (!isArtifactMetadataUpdate) {
2656                 log.debug("In artifact: {} Payload is missing.",artifactInfo.getArtifactName());
2657                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_DATA, ARTIFACT_PAYLOAD);
2658                 return Either.right(responseFormat);
2659             }
2660         }
2661         log.trace("Ended payload handling");
2662         return Either.left(decodedPayload);
2663     }
2664
2665     public Either<ArtifactDefinition, ResponseFormat> deleteArtifactByInterface(
2666         String resourceId, String userUserId, String artifactId, boolean inTransaction) {
2667
2668         return toscaOperationFacade
2669             .getToscaElement(resourceId, JsonParseFlagEnum.ParseMetadata)
2670             .right().map(componentsUtils.toResponseFormat())
2671             .left().bind(parentComponent -> {
2672                 User user = new User(userUserId);
2673                 return handleDelete(resourceId, artifactId, user,
2674                     parentComponent,
2675                     false, inTransaction);
2676             });
2677     }
2678
2679     private Operation convertToOperation(ArtifactDefinition artifactInfo, String operationName) {
2680         Operation op = new Operation();
2681         long time = System.currentTimeMillis();
2682         op.setCreationDate(time);
2683
2684         String artifactName = artifactInfo.getArtifactName();
2685         artifactInfo.setArtifactName(createInterfaceArtifactNameFromOperation(operationName, artifactName));
2686
2687         op.setImplementation(artifactInfo);
2688         op.setLastUpdateDate(time);
2689         return op;
2690     }
2691
2692     private String createInterfaceArtifactNameFromOperation(String operationName, String artifactName) {
2693         String newArtifactName = operationName + "_" + artifactName;
2694         log.trace("converting artifact name {} to {}", artifactName, newArtifactName);
2695         return newArtifactName;
2696     }
2697
2698     // download by MSO
2699     public byte[] downloadRsrcArtifactByNames(String serviceName, String serviceVersion, String resourceName, String resourceVersion, String artifactName) {
2700
2701         // General validation
2702         if (serviceName == null || serviceVersion == null || resourceName == null || resourceVersion == null || artifactName == null) {
2703             log.debug(NULL_PARAMETER);
2704             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
2705         }
2706
2707         // Normalizing artifact name
2708         artifactName = ValidationUtils.normalizeFileName(artifactName);
2709
2710         // Resource validation
2711         Resource resource = validateResourceNameAndVersion(resourceName, resourceVersion);
2712         String resourceId = resource.getUniqueId();
2713
2714         // Service validation
2715         Service validateServiceNameAndVersion = validateServiceNameAndVersion(serviceName, serviceVersion);
2716
2717         Map<String, ArtifactDefinition> artifacts = resource.getDeploymentArtifacts();
2718         if (artifacts == null || artifacts.isEmpty()) {
2719             log.debug("Deployment artifacts of resource {} are not found", resourceId);
2720             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactName);
2721         }
2722
2723         ArtifactDefinition deploymentArtifact = null;
2724
2725         for (ArtifactDefinition artifactDefinition : artifacts.values()) {
2726             if (artifactDefinition.getArtifactName() != null && artifactDefinition.getArtifactName()
2727                     .equals(artifactName)) {
2728                 log.debug(FOUND_DEPLOYMENT_ARTIFACT, artifactName);
2729                 deploymentArtifact = artifactDefinition;
2730                 break;
2731             }
2732         }
2733
2734         if (deploymentArtifact == null) {
2735             log.debug("No deployment artifact {} was found for resource {}", artifactName, resourceId);
2736             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactName);
2737         }
2738
2739         // Downloading the artifact
2740         ImmutablePair<String, byte[]> downloadArtifactEither = downloadArtifact(deploymentArtifact);
2741         log.trace("Download of resource artifact succeeded, uniqueId {}", deploymentArtifact.getUniqueId());
2742         return downloadArtifactEither.getRight();
2743     }
2744
2745     // download by MSO
2746     public byte[] downloadRsrcInstArtifactByNames(String serviceName, String serviceVersion, String resourceInstanceName, String artifactName) {
2747
2748         // General validation
2749         if (serviceName == null || serviceVersion == null || resourceInstanceName == null || artifactName == null) {
2750             log.debug(NULL_PARAMETER);
2751             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
2752         }
2753
2754         // Normalizing artifact name
2755         artifactName = ValidationUtils.normalizeFileName(artifactName);
2756
2757         // Service validation
2758         Service service = validateServiceNameAndVersion(serviceName, serviceVersion);
2759
2760         // ResourceInstance validation
2761         ComponentInstance resourceInstance = validateResourceInstance(service, resourceInstanceName);
2762
2763         Map<String, ArtifactDefinition> artifacts = resourceInstance.getDeploymentArtifacts();
2764
2765         final String finalArtifactName = artifactName;
2766         Predicate<ArtifactDefinition> filterArtifactByName = p -> p.getArtifactName().equals(finalArtifactName);
2767
2768         ArtifactDefinition deployableArtifact = artifacts==null ? null :
2769                 artifacts.values().stream()
2770                         .filter(filterArtifactByName)
2771                         .findFirst()
2772                         .orElse(null);
2773
2774         if (deployableArtifact == null) {
2775             log.debug("Deployment artifact with name {} not found", artifactName);
2776             throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND, artifactName));
2777         }
2778
2779         log.debug(FOUND_DEPLOYMENT_ARTIFACT, artifactName);
2780         ImmutablePair<String, byte[]> downloadArtifactEither = downloadArtifact(deployableArtifact);
2781
2782         log.trace("Download of resource artifact succeeded, uniqueId {}", deployableArtifact.getUniqueId());
2783         return downloadArtifactEither.getRight();
2784     }
2785
2786     private ComponentInstance validateResourceInstance(Service service, String resourceInstanceName) {
2787
2788         List<ComponentInstance> riList = service.getComponentInstances();
2789         for (ComponentInstance ri : riList) {
2790             if (ri.getNormalizedName().equals(resourceInstanceName)) {
2791                 return ri;
2792             }
2793         }
2794         throw new ByActionStatusComponentException(ActionStatus.RESOURCE_INSTANCE_NOT_FOUND, resourceInstanceName);
2795     }
2796
2797     private ComponentInstance validateResourceInstanceById(Component component, String resourceInstanceId) {
2798
2799         List<ComponentInstance> riList = component.getComponentInstances();
2800         for (ComponentInstance ri : riList) {
2801             if (ri.getUniqueId().equals(resourceInstanceId)) {
2802                 return ri;
2803             }
2804         }
2805         throw new ByActionStatusComponentException(ActionStatus.RESOURCE_NOT_FOUND, resourceInstanceId);
2806     }
2807
2808     private Service validateServiceNameAndVersion(String serviceName, String serviceVersion) {
2809
2810         Either<List<Service>, StorageOperationStatus> serviceListBySystemName = toscaOperationFacade.getBySystemName(ComponentTypeEnum.SERVICE, serviceName);
2811         if (serviceListBySystemName.isRight()) {
2812             log.debug("Couldn't fetch any service with name {}", serviceName);
2813             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(serviceListBySystemName
2814                     .right()
2815                     .value(), ComponentTypeEnum.SERVICE), serviceName);
2816         }
2817         List<Service> serviceList = serviceListBySystemName.left().value();
2818         if (serviceList == null || serviceList.isEmpty()) {
2819             log.debug("Couldn't fetch any service with name {}", serviceName);
2820             throw new ByActionStatusComponentException(ActionStatus.SERVICE_NOT_FOUND, serviceName);
2821         }
2822
2823         Service foundService = null;
2824         for (Service service : serviceList) {
2825             if (service.getVersion().equals(serviceVersion)) {
2826                 log.trace("Found service with version {}", serviceVersion);
2827                 foundService = service;
2828                 break;
2829             }
2830         }
2831
2832         if (foundService == null) {
2833             log.debug("Couldn't find version {} for service {}", serviceVersion, serviceName);
2834             throw new ByActionStatusComponentException(ActionStatus.COMPONENT_VERSION_NOT_FOUND, ComponentTypeEnum.SERVICE
2835                     .getValue(), serviceVersion);
2836         }
2837         return foundService;
2838     }
2839
2840     private Resource validateResourceNameAndVersion(String resourceName, String resourceVersion) {
2841
2842         Either<Resource, StorageOperationStatus> resourceListBySystemName = toscaOperationFacade.getComponentByNameAndVersion(ComponentTypeEnum.RESOURCE, resourceName, resourceVersion, JsonParseFlagEnum.ParseMetadata);
2843         if (resourceListBySystemName.isRight()) {
2844             log.debug("Couldn't fetch any resource with name {} and version {}. ", resourceName, resourceVersion);
2845             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(resourceListBySystemName
2846                     .right()
2847                     .value()), resourceName);
2848         }
2849         return resourceListBySystemName.left().value();
2850     }
2851
2852     public byte[] downloadServiceArtifactByNames(String serviceName, String serviceVersion, String artifactName) {
2853         // Validation
2854         log.trace("Starting download of service interface artifact, serviceName {}, serviceVersion {}, artifact name {}", serviceName, serviceVersion, artifactName);
2855         if (serviceName == null || serviceVersion == null || artifactName == null) {
2856             log.debug(NULL_PARAMETER);
2857             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
2858         }
2859
2860         // Normalizing artifact name
2861         final String normalizedArtifactName = ValidationUtils.normalizeFileName(artifactName);
2862
2863         // Service validation
2864         Service service = validateServiceNameAndVersion(serviceName, serviceVersion);
2865         // Looking for deployment or tosca artifacts
2866         String serviceId = service.getUniqueId();
2867
2868         if (MapUtils.isEmpty(service.getDeploymentArtifacts()) && MapUtils.isEmpty(service.getToscaArtifacts())) {
2869             log.debug("Neither Deployment nor Tosca artifacts of service {} are found", serviceId);
2870             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, normalizedArtifactName);
2871         }
2872
2873         Optional<ArtifactDefinition> foundArtifactOptl = Optional.empty();
2874
2875         if (!MapUtils.isEmpty(service.getDeploymentArtifacts())) {
2876             foundArtifactOptl = service.getDeploymentArtifacts().values().stream()
2877                     // filters artifact by name
2878                     .filter(a -> a.getArtifactName().equals(normalizedArtifactName)).findAny();
2879         }
2880         if ((!foundArtifactOptl.isPresent()) && !MapUtils.isEmpty(service.getToscaArtifacts())) {
2881             foundArtifactOptl = service.getToscaArtifacts().values().stream()
2882                     // filters TOSCA artifact by name
2883                     .filter(a -> a.getArtifactName().equals(normalizedArtifactName)).findAny();
2884         }
2885         if (!foundArtifactOptl.isPresent()) {
2886             log.debug("The artifact {} was not found for service {}", normalizedArtifactName, serviceId);
2887             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, normalizedArtifactName);
2888         }
2889         log.debug(FOUND_DEPLOYMENT_ARTIFACT, normalizedArtifactName);
2890         // Downloading the artifact
2891         ImmutablePair<String, byte[]> downloadArtifactEither = downloadArtifact(foundArtifactOptl
2892                 .get());
2893         log.trace("Download of service artifact succeeded, uniqueId {}", foundArtifactOptl.get().getUniqueId());
2894         return downloadArtifactEither.getRight();
2895     }
2896
2897     public ImmutablePair<String, byte[]> downloadArtifact(String parentId, String artifactUniqueId) {
2898         log.trace("Starting download of artifact, uniqueId {}", artifactUniqueId);
2899         Either<ArtifactDefinition, StorageOperationStatus> artifactById = artifactToscaOperation.getArtifactById(parentId, artifactUniqueId);
2900         if (artifactById.isRight()) {
2901             ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(artifactById.right().value());
2902             log.debug("Error when getting artifact info by id{}, error: {}", artifactUniqueId, actionStatus);
2903             throw new ByResponseFormatComponentException(componentsUtils.getResponseFormatByArtifactId(actionStatus, ""));
2904         }
2905         ArtifactDefinition artifactDefinition = artifactById.left().value();
2906         if (artifactDefinition == null) {
2907             log.debug("Empty artifact definition returned from DB by artifact id {}", artifactUniqueId);
2908             throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND, ""));
2909         }
2910
2911         return downloadArtifact(artifactDefinition);
2912     }
2913
2914     private Component validateComponentExists(String componentId, AuditingActionEnum auditingAction, User user, String artifactId, ComponentTypeEnum componentType,
2915                                               String containerComponentType) {
2916
2917         ComponentTypeEnum componentForAudit = null == containerComponentType ? componentType : ComponentTypeEnum.findByParamName(containerComponentType);
2918         componentForAudit.getNodeType();
2919
2920         Either<? extends Component, StorageOperationStatus> componentResult = toscaOperationFacade
2921                 .getToscaFullElement(componentId);
2922
2923         if (componentResult.isRight()) {
2924             ActionStatus status = componentForAudit == ComponentTypeEnum.RESOURCE ? ActionStatus.RESOURCE_NOT_FOUND : componentForAudit == ComponentTypeEnum.SERVICE ? ActionStatus.SERVICE_NOT_FOUND : ActionStatus.PRODUCT_NOT_FOUND;
2925             ResponseFormat responseFormat = componentsUtils.getResponseFormat(status, componentId);
2926             log.debug("Service not found, serviceId {}", componentId);
2927             handleAuditing(auditingAction, null, componentId, user, null, null, artifactId, responseFormat, componentForAudit, null);
2928             throw new ByActionStatusComponentException(status, componentId);
2929         }
2930         return componentResult.left().value();
2931     }
2932
2933     private void validateWorkOnComponent(Component component, String userId, AuditingActionEnum auditingAction, User user, String artifactId, ArtifactOperationInfo operation) {
2934         if (operation.getArtifactOperationEnum() != ArtifactOperationEnum.DOWNLOAD && !operation.ignoreLifecycleState()) {
2935             try {
2936                 validateCanWorkOnComponent(component, userId);
2937             }catch (ComponentException e) {
2938                 String uniqueId = component.getUniqueId();
2939                 log.debug("Service status isn't  CHECKOUT or user isn't owner, serviceId {}", uniqueId);
2940                 handleAuditing(auditingAction, component, uniqueId, user, null, null, artifactId, e.getResponseFormat(),
2941                         component.getComponentType(), null);
2942                 throw e;
2943             }
2944         }
2945     }
2946
2947     private void validateUserRole(User user, AuditingActionEnum auditingAction, String componentId, String artifactId, ComponentTypeEnum componentType, ArtifactOperationInfo operation) {
2948
2949         if (operation.isNotDownload()) {
2950             String role = user.getRole();
2951             if (!role.equals(Role.ADMIN.name()) && !role.equals(Role.DESIGNER.name())) {
2952                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
2953                 log.debug("addArtifact - user isn't permitted to perform operation, userId {}, role {}", user.getUserId(), role);
2954                 handleAuditing(auditingAction, null, componentId, user, null, null, artifactId, responseFormat, componentType, null);
2955                 throw new ByActionStatusComponentException(ActionStatus.RESTRICTED_OPERATION);
2956             }
2957         }
2958     }
2959
2960     private User validateUserExists(String userId, AuditingActionEnum auditingAction, String componentId, String artifactId, ComponentTypeEnum componentType, boolean inTransaction) {
2961         User user;
2962         try{
2963             user = validateUserExists(userId);
2964         } catch(ByResponseFormatComponentException e){
2965             ResponseFormat responseFormat = e.getResponseFormat();
2966             handleComponentException(auditingAction, componentId, artifactId, responseFormat, componentType, userId);
2967             throw e;
2968         } catch(ByActionStatusComponentException e){
2969             ResponseFormat responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
2970             handleComponentException(auditingAction, componentId, artifactId, responseFormat, componentType, userId);
2971             throw e;
2972         }
2973         return user;
2974     }
2975
2976     private void handleComponentException(AuditingActionEnum auditingAction, String componentId, String artifactId,
2977         ResponseFormat responseFormat, ComponentTypeEnum componentType, String userId){
2978         User user = new User();
2979         user.setUserId(userId);
2980         handleAuditing(auditingAction, null, componentId, user, null, null, artifactId, responseFormat, componentType, null);
2981     }
2982
2983     protected AuditingActionEnum detectAuditingType(ArtifactOperationInfo operation, String origMd5) {
2984         AuditingActionEnum auditingAction = null;
2985         switch (operation.getArtifactOperationEnum()) {
2986             case CREATE:
2987                 auditingAction = operation.isExternalApi() ? AuditingActionEnum.ARTIFACT_UPLOAD_BY_API : AuditingActionEnum.ARTIFACT_UPLOAD;
2988                 break;
2989             case UPDATE:
2990                 auditingAction = operation.isExternalApi() ? AuditingActionEnum.ARTIFACT_UPLOAD_BY_API : origMd5 == null ? AuditingActionEnum.ARTIFACT_METADATA_UPDATE : AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE;
2991                 break;
2992             case DELETE:
2993                 auditingAction = operation.isExternalApi() ? AuditingActionEnum.ARTIFACT_DELETE_BY_API : AuditingActionEnum.ARTIFACT_DELETE;
2994                 break;
2995             case DOWNLOAD:
2996                 auditingAction = operation.isExternalApi() ? AuditingActionEnum.DOWNLOAD_ARTIFACT : AuditingActionEnum.ARTIFACT_DOWNLOAD;
2997                 break;
2998             default:
2999                 break;
3000         }
3001         return auditingAction;
3002     }
3003
3004     private ImmutablePair<String, byte[]> downloadArtifact(ArtifactDefinition artifactDefinition) {
3005         String esArtifactId = artifactDefinition.getEsId();
3006         Either<DAOArtifactData, CassandraOperationStatus> artifactfromES = artifactCassandraDao.getArtifact(esArtifactId);
3007         if (artifactfromES.isRight()) {
3008             CassandraOperationStatus resourceUploadStatus = artifactfromES.right().value();
3009             StorageOperationStatus storageResponse = DaoStatusConverter.convertCassandraStatusToStorageStatus(resourceUploadStatus);
3010             ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(storageResponse);
3011             log.debug("Error when getting artifact from ES, error: {}", actionStatus);
3012             throw new ByActionStatusComponentException(actionStatus, artifactDefinition.getArtifactDisplayName());
3013         }
3014
3015         DAOArtifactData DAOArtifactData = artifactfromES.left().value();
3016         byte[] data = DAOArtifactData.getDataAsArray();
3017         if (data == null) {
3018             log.debug("Artifact data from cassandra is null");
3019             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactDefinition.getArtifactDisplayName());
3020         }
3021         String artifactName = artifactDefinition.getArtifactName();
3022         log.trace("Download of artifact succeeded, uniqueId {}, artifact file name {}", artifactDefinition.getUniqueId(), artifactName);
3023         return new ImmutablePair<>(artifactName, data);
3024     }
3025
3026     public DAOArtifactData createEsArtifactData(ArtifactDataDefinition artifactInfo, byte[] artifactPayload) {
3027         return new DAOArtifactData(artifactInfo.getEsId(), artifactPayload);
3028     }
3029
3030     private void saveArtifactInCassandra(DAOArtifactData artifactData, Component parent, ArtifactDefinition artifactInfo,
3031                                          String currArtifactId, String prevArtifactId, AuditingActionEnum auditingAction, ComponentTypeEnum componentType) {
3032         CassandraOperationStatus resourceUploadStatus = artifactCassandraDao.saveArtifact(artifactData);
3033
3034         if (resourceUploadStatus == CassandraOperationStatus.OK) {
3035             log.debug("Artifact {} was saved in component {}.", artifactData.getId(), parent.getUniqueId());
3036             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
3037             handleAuditing(auditingAction, parent, parent.getUniqueId(), null, artifactInfo, prevArtifactId,
3038                     currArtifactId, responseFormat, componentType, null);
3039         }
3040         else {
3041             BeEcompErrorManager.getInstance().logBeDaoSystemError(UPDATE_ARTIFACT);
3042             log.info(FAILED_SAVE_ARTIFACT);
3043             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
3044             handleAuditing(auditingAction, parent, parent.getUniqueId(), null, artifactInfo, prevArtifactId, currArtifactId, responseFormat, componentType, null);
3045             throw new StorageException(resourceUploadStatus);
3046         }
3047     }
3048
3049     private boolean isArtifactMetadataUpdate(AuditingActionEnum auditingActionEnum) {
3050         return auditingActionEnum == AuditingActionEnum.ARTIFACT_METADATA_UPDATE;
3051     }
3052
3053     private boolean isDeploymentArtifact(ArtifactDefinition artifactInfo) {
3054         return ArtifactGroupTypeEnum.DEPLOYMENT == artifactInfo.getArtifactGroupType();
3055     }
3056
3057     private boolean isInformationalArtifact(final ArtifactDefinition artifactInfo) {
3058         return ArtifactGroupTypeEnum.INFORMATIONAL == artifactInfo.getArtifactGroupType();
3059     }
3060
3061     private boolean isHeatArtifact(final ArtifactDefinition artifactInfo) {
3062         final String artifactType = artifactInfo.getArtifactType();
3063         final ArtifactTypeEnum artifactTypeEnum = ArtifactTypeEnum.parse(artifactType);
3064         if (artifactTypeEnum == null) {
3065             artifactInfo.setTimeout(NodeTemplateOperation.NON_HEAT_TIMEOUT);
3066             return false;
3067         }
3068         switch (artifactTypeEnum) {
3069             case HEAT:
3070             case HEAT_VOL:
3071             case HEAT_NET:
3072             case HEAT_ENV:
3073                 return true;
3074             default:
3075                 return false;
3076         }
3077     }
3078
3079
3080     public ArtifactDefinition createArtifactPlaceHolderInfo(String resourceId, String logicalName, Map<String, Object> artifactInfoMap, String userUserId, ArtifactGroupTypeEnum groupType, boolean inTransaction) {
3081         User user = userBusinessLogic.getUser(userUserId, inTransaction);
3082         return createArtifactPlaceHolderInfo(resourceId, logicalName, artifactInfoMap, user, groupType);
3083     }
3084
3085     public ArtifactDefinition createArtifactPlaceHolderInfo(String resourceId, String logicalName, Map<String, Object> artifactInfoMap, User user, ArtifactGroupTypeEnum groupType) {
3086         ArtifactDefinition artifactInfo = new ArtifactDefinition();
3087
3088         String artifactName = (String) artifactInfoMap.get(ARTIFACT_PLACEHOLDER_DISPLAY_NAME);
3089         String artifactType = (String) artifactInfoMap.get(ARTIFACT_PLACEHOLDER_TYPE);
3090         String artifactDescription = (String) artifactInfoMap.get(ARTIFACT_PLACEHOLDER_DESCRIPTION);
3091
3092         artifactInfo.setArtifactDisplayName(artifactName);
3093         artifactInfo.setArtifactLabel(logicalName.toLowerCase());
3094         artifactInfo.setArtifactType(artifactType);
3095         artifactInfo.setDescription(artifactDescription);
3096         artifactInfo.setArtifactGroupType(groupType);
3097         nodeTemplateOperation.setDefaultArtifactTimeout(groupType, artifactInfo);
3098
3099         setArtifactPlaceholderCommonFields(resourceId, user, artifactInfo);
3100
3101         return artifactInfo;
3102     }
3103
3104     private void setArtifactPlaceholderCommonFields(String resourceId, User user, ArtifactDefinition artifactInfo) {
3105         String uniqueId = null;
3106
3107         if (resourceId != null) {
3108             uniqueId = UniqueIdBuilder.buildPropertyUniqueId(resourceId.toLowerCase(), artifactInfo.getArtifactLabel()
3109                     .toLowerCase());
3110             artifactInfo.setUniqueId(uniqueId);
3111         }
3112         artifactInfo.setUserIdCreator(user.getUserId());
3113         String fullName = user.getFullName();
3114         artifactInfo.setUpdaterFullName(fullName);
3115
3116         long time = System.currentTimeMillis();
3117
3118         artifactInfo.setCreatorFullName(fullName);
3119         artifactInfo.setCreationDate(time);
3120
3121         artifactInfo.setLastUpdateDate(time);
3122         artifactInfo.setUserIdLastUpdater(user.getUserId());
3123
3124         artifactInfo.setMandatory(true);
3125     }
3126
3127     public Either<Map<String, ArtifactDefinition>, StorageOperationStatus> getArtifacts(String parentId, NodeTypeEnum parentType, ArtifactGroupTypeEnum groupType, String instanceId) {
3128         return artifactToscaOperation.getArtifacts(parentId, parentType, groupType, instanceId);
3129     }
3130
3131     public Either<ArtifactDefinition, StorageOperationStatus> addHeatEnvArtifact(ArtifactDefinition artifactHeatEnv, ArtifactDefinition artifact, Component component, NodeTypeEnum parentType, String instanceId) {
3132         return artifactToscaOperation.addHeatEnvArtifact(artifactHeatEnv, artifact, component, parentType, true, instanceId);
3133     }
3134
3135     private Either<DAOArtifactData, ResponseFormat> createEsHeatEnvArtifactDataFromString(ArtifactDefinition artifactDefinition, String payloadStr) {
3136
3137         byte[] payload = payloadStr.getBytes();
3138
3139         DAOArtifactData artifactData = createEsArtifactData(artifactDefinition, payload);
3140         return Either.left(artifactData);
3141     }
3142
3143     /**
3144      * @param artifactDefinition
3145      * @return
3146      */
3147     public Either<ArtifactDefinition, ResponseFormat> generateHeatEnvArtifact(ArtifactDefinition artifactDefinition, ComponentTypeEnum componentType, Component component, String resourceInstanceName, User modifier,
3148                                                                               String instanceId, boolean shouldLock, boolean inTransaction) {
3149         String payload = generateHeatEnvPayload(artifactDefinition);
3150         String prevUUID = artifactDefinition.getArtifactUUID();
3151         ArtifactDefinition clonedBeforeGenerate = new ArtifactDefinition(artifactDefinition);
3152         return generateAndSaveHeatEnvArtifact(artifactDefinition, payload, componentType, component, resourceInstanceName, modifier, instanceId, shouldLock, inTransaction)
3153                 .left()
3154                 .bind(artifactDef -> updateArtifactOnGroupInstance(component, instanceId, prevUUID, clonedBeforeGenerate, artifactDef));
3155     }
3156
3157     public Either<ArtifactDefinition, ResponseFormat> forceGenerateHeatEnvArtifact(ArtifactDefinition artifactDefinition, ComponentTypeEnum componentType, Component component, String resourceInstanceName, User modifier,
3158                                                                                    boolean shouldLock, boolean inTransaction, String instanceId) {
3159         String payload = generateHeatEnvPayload(artifactDefinition);
3160         String prevUUID = artifactDefinition.getArtifactUUID();
3161         ArtifactDefinition clonedBeforeGenerate = new ArtifactDefinition(artifactDefinition);
3162         return forceGenerateAndSaveHeatEnvArtifact(artifactDefinition, payload, componentType, component, resourceInstanceName, modifier, instanceId, shouldLock, inTransaction)
3163                 .left()
3164                 .bind(artifactDef -> updateArtifactOnGroupInstance(component, instanceId, prevUUID, clonedBeforeGenerate, artifactDef));
3165     }
3166
3167     @VisibleForTesting
3168     Either<ArtifactDefinition, ResponseFormat> updateArtifactOnGroupInstance(Component component, String instanceId, String prevUUID, ArtifactDefinition clonedBeforeGenerate, ArtifactDefinition updatedArtDef) {
3169         if (prevUUID == null || !prevUUID.equals(updatedArtDef.getArtifactUUID())) {
3170             List<ComponentInstance> componentInstances = component.getComponentInstances();
3171             if (componentInstances != null) {
3172                 Optional<ComponentInstance> findFirst = componentInstances.stream()
3173                         .filter(ci -> ci.getUniqueId()
3174                                 .equals(instanceId))
3175                         .findFirst();
3176                 if (findFirst.isPresent()) {
3177                     ComponentInstance relevantInst = findFirst.get();
3178                     List<GroupInstance> updatedGroupInstances = getUpdatedGroupInstances(updatedArtDef.getUniqueId(), clonedBeforeGenerate, relevantInst
3179                             .getGroupInstances());
3180
3181                     if (CollectionUtils.isNotEmpty(updatedGroupInstances)) {
3182                         updatedGroupInstances.forEach(gi -> {
3183                             gi.getGroupInstanceArtifacts().add(updatedArtDef.getUniqueId());
3184                             gi.getGroupInstanceArtifactsUuid().add(updatedArtDef.getArtifactUUID());
3185                         });
3186                         Either<List<GroupInstance>, StorageOperationStatus> status = toscaOperationFacade.updateGroupInstancesOnComponent(component, instanceId, updatedGroupInstances);
3187                         if (status.isRight()) {
3188                             log.debug(FAILED_UPDATE_GROUPS, component.getUniqueId());
3189                             ResponseFormat responseFormat = componentsUtils.getResponseFormatByArtifactId(componentsUtils
3190                                     .convertFromStorageResponse(status.right()
3191                                             .value()), clonedBeforeGenerate.getArtifactDisplayName());
3192                             return Either.right(responseFormat);
3193                         }
3194                     }
3195                 }
3196             }
3197         }
3198         return Either.left(updatedArtDef);
3199     }
3200
3201     private String generateHeatEnvPayload(ArtifactDefinition artifactDefinition) {
3202         List<HeatParameterDefinition> heatParameters = artifactDefinition.getListHeatParameters();
3203         StringBuilder sb = new StringBuilder();
3204         sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactHeader());
3205         sb.append("parameters:\n");
3206         if (heatParameters != null) {
3207             heatParameters.sort(Comparator.comparing(HeatParameterDataDefinition::getName));
3208
3209             List<HeatParameterDefinition> empltyHeatValues = new ArrayList<>();
3210
3211             for (HeatParameterDefinition heatParameterDefinition : heatParameters) {
3212
3213                 String heatValue = heatParameterDefinition.getCurrentValue();
3214                 if (!ValidationUtils.validateStringNotEmpty(heatValue)) {
3215                     heatValue = heatParameterDefinition.getDefaultValue();
3216                     if (!ValidationUtils.validateStringNotEmpty(heatValue)) {
3217                         empltyHeatValues.add(heatParameterDefinition);
3218                         continue;
3219                     }
3220                 }
3221                 HeatParameterType type = HeatParameterType.isValidType(heatParameterDefinition.getType());
3222                 if (type != null) {
3223                     switch (type) {
3224                         case BOOLEAN:
3225                             sb.append("  ")
3226                                     .append(heatParameterDefinition.getName())
3227                                     .append(":")
3228                                     .append(" ")
3229                                     .append(Boolean.parseBoolean(heatValue))
3230                                     .append("\n");
3231                             break;
3232                         case NUMBER:
3233                             sb.append("  ")
3234                                     .append(heatParameterDefinition.getName())
3235                                     .append(":")
3236                                     .append(" ")
3237                                     .append(new BigDecimal(heatValue).toPlainString())
3238                                     .append("\n");
3239                             break;
3240                         case COMMA_DELIMITED_LIST:
3241                         case JSON:
3242                             sb.append("  ")
3243                                     .append(heatParameterDefinition.getName())
3244                                     .append(":")
3245                                     .append(" ")
3246                                     .append(heatValue)
3247                                     .append("\n");
3248                             break;
3249                         default:
3250                             String value = heatValue;
3251                             boolean starts = value.startsWith("\"");
3252                             boolean ends = value.endsWith("\"");
3253                             if (!(starts && ends)) {
3254                                 starts = value.startsWith("'");
3255                                 ends = value.endsWith("'");
3256                                 if (!(starts && ends)) {
3257                                     value = "\"" + value + "\"";
3258                                 }
3259                             }
3260                             sb.append("  ")
3261                                     .append(heatParameterDefinition.getName())
3262                                     .append(":")
3263                                     .append(" ")
3264                                     .append(value);
3265                             sb.append("\n");
3266                             break;
3267
3268                     }
3269                 }
3270             }
3271             if (!empltyHeatValues.isEmpty()) {
3272                 empltyHeatValues.sort(Comparator.comparing(HeatParameterDataDefinition::getName));
3273                 empltyHeatValues.forEach(hv -> {
3274                     sb.append("  ").append(hv.getName()).append(":");
3275                     HeatParameterType type = HeatParameterType.isValidType(hv.getType());
3276                     if (type != null && type == HeatParameterType.STRING && (hv.getCurrentValue() != null && "".equals(hv
3277                             .getCurrentValue()) || hv.getDefaultValue() != null && "".equals(hv.getDefaultValue()))) {
3278                         sb.append(" \"\"").append("\n");
3279                     }
3280                     else {
3281                         sb.append(" ").append("\n");
3282                     }
3283                 });
3284             }
3285         }
3286         sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactFooter());
3287
3288         // DE265919 fix
3289         return sb.toString().replaceAll("\\\\n", "\n");
3290     }
3291
3292     /**
3293      * @param artifactDefinition
3294      * @param payload
3295      * @return
3296      */
3297     public Either<ArtifactDefinition, ResponseFormat> generateAndSaveHeatEnvArtifact(ArtifactDefinition artifactDefinition, String payload, ComponentTypeEnum componentType, Component component, String resourceInstanceName,
3298                                                                                      User modifier, String instanceId, boolean shouldLock, boolean inTransaction) {
3299         return generateArtifactPayload(artifactDefinition, componentType, component, resourceInstanceName, modifier, shouldLock, inTransaction, artifactDefinition::getHeatParamsUpdateDate,
3300                 () -> createEsHeatEnvArtifactDataFromString(artifactDefinition, payload), instanceId);
3301
3302     }
3303
3304     public Either<ArtifactDefinition, ResponseFormat> forceGenerateAndSaveHeatEnvArtifact(ArtifactDefinition artifactDefinition, String payload, ComponentTypeEnum componentType, Component component, String resourceInstanceName,
3305                                                                                           User modifier, String instanceId, boolean shouldLock, boolean inTransaction) {
3306         return generateArtifactPayload(artifactDefinition, componentType, component, resourceInstanceName, modifier, shouldLock, inTransaction, System::currentTimeMillis,
3307                 () -> createEsHeatEnvArtifactDataFromString(artifactDefinition, payload), instanceId);
3308
3309     }
3310
3311     protected Either<ArtifactDefinition, ResponseFormat> generateArtifactPayload(ArtifactDefinition artifactDefinition, ComponentTypeEnum componentType, Component component, String resourceInstanceName, User modifier,
3312                                                                                  boolean shouldLock, boolean inTransaction, Supplier<Long> payloadUpdateDateGen, Supplier<Either<DAOArtifactData, ResponseFormat>> esDataCreator, String instanceId) {
3313
3314         log.trace("Start generating payload for {} artifact {}", artifactDefinition.getArtifactType(), artifactDefinition
3315                 .getEsId());
3316         if (artifactDefinition.getPayloadUpdateDate() == null || artifactDefinition.getPayloadUpdateDate() == 0 || artifactDefinition
3317                 .getPayloadUpdateDate() <= payloadUpdateDateGen.get()) {
3318
3319             log.trace("Generating payload for {} artifact {}", artifactDefinition.getArtifactType(), artifactDefinition.getEsId());
3320             Either<DAOArtifactData, ResponseFormat> artifactDataRes = esDataCreator.get();
3321             DAOArtifactData artifactData = null;
3322
3323             if (artifactDataRes.isLeft()) {
3324                 artifactData = artifactDataRes.left().value();
3325             }
3326             else {
3327                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
3328                 handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition, artifactDefinition
3329                                 .getUniqueId(), artifactDefinition.getUniqueId(), responseFormat,
3330                         ComponentTypeEnum.RESOURCE_INSTANCE, resourceInstanceName);
3331
3332                 return Either.right(artifactDataRes.right().value());
3333             }
3334             String newCheckSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(artifactData.getDataAsArray());
3335             String oldCheckSum;
3336             String esArtifactId = artifactDefinition.getEsId();
3337             Either<DAOArtifactData, CassandraOperationStatus> artifactfromES;
3338             DAOArtifactData DAOArtifactData;
3339             if (esArtifactId != null && !esArtifactId.isEmpty() && artifactDefinition.getPayloadData() == null) {
3340                 log.debug("Try to fetch artifact from cassandra with id : {}", esArtifactId);
3341                 artifactfromES = artifactCassandraDao.getArtifact(esArtifactId);
3342                 if (artifactfromES.isRight()) {
3343                     CassandraOperationStatus resourceUploadStatus = artifactfromES.right().value();
3344                     StorageOperationStatus storageResponse = DaoStatusConverter.convertCassandraStatusToStorageStatus(resourceUploadStatus);
3345                     ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(storageResponse);
3346                     log.debug("Error when getting artifact from ES, error: {} esid : {}", actionStatus, esArtifactId);
3347                     return Either.right(componentsUtils.getResponseFormatByArtifactId(actionStatus, artifactDefinition.getArtifactDisplayName()));
3348                 }
3349                 DAOArtifactData = artifactfromES.left().value();
3350                 oldCheckSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(DAOArtifactData.getDataAsArray());
3351             }
3352             else {
3353                 oldCheckSum = artifactDefinition.getArtifactChecksum();
3354
3355             }
3356             Either<ArtifactDefinition, StorageOperationStatus> updateArifactDefinitionStatus = null;
3357
3358             if (shouldLock) {
3359                 try {
3360                     lockComponent(component, "Update Artifact - lock resource: ");
3361                 }catch (ComponentException e){
3362                     handleAuditing(AuditingActionEnum.ARTIFACT_METADATA_UPDATE, component, component.getUniqueId(), modifier, null, null, artifactDefinition
3363                             .getUniqueId(), e.getResponseFormat(), component.getComponentType(), null);
3364                     throw e;
3365                 }
3366             }
3367             try {
3368                 if (oldCheckSum != null && oldCheckSum.equals(newCheckSum)) {
3369
3370                     artifactDefinition.setPayloadUpdateDate(payloadUpdateDateGen.get());
3371                     updateArifactDefinitionStatus = artifactToscaOperation.updateArtifactOnResource(artifactDefinition, component
3372                             ,artifactDefinition.getUniqueId(), componentType.getNodeType(), instanceId, true);
3373                     log.trace("No real update done in payload for {} artifact, updating payloadUpdateDate {}", artifactDefinition
3374                             .getArtifactType(), artifactDefinition.getEsId());
3375                     if (updateArifactDefinitionStatus.isRight()) {
3376                         ResponseFormat responseFormat = componentsUtils.getResponseFormatByArtifactId(componentsUtils.convertFromStorageResponse(updateArifactDefinitionStatus
3377                                 .right()
3378                                 .value()), artifactDefinition.getArtifactDisplayName());
3379                         log.trace("Failed to update payloadUpdateDate {}", artifactDefinition.getEsId());
3380                         handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition, artifactDefinition
3381                                         .getUniqueId(), artifactDefinition.getUniqueId(), responseFormat,
3382                                 ComponentTypeEnum.RESOURCE_INSTANCE, resourceInstanceName);
3383
3384                         return Either.right(responseFormat);
3385                     }
3386                 }
3387                 else {
3388                     artifactDefinition.getArtifactChecksum();
3389                     artifactDefinition.setArtifactChecksum(newCheckSum);
3390                     artifactDefinition.setEsId(artifactDefinition.getUniqueId());
3391                     log.trace("No real update done in payload for {} artifact, updating payloadUpdateDate {}", artifactDefinition
3392                             .getArtifactType(), artifactDefinition.getEsId());
3393                     updateArifactDefinitionStatus = artifactToscaOperation.updateArtifactOnResource(artifactDefinition, component,
3394                             artifactDefinition.getUniqueId(), componentType.getNodeType(), instanceId, true);
3395
3396                     log.trace("Update Payload {}", artifactDefinition.getEsId());
3397                 }
3398                 if (updateArifactDefinitionStatus.isLeft()) {
3399
3400                     artifactDefinition = updateArifactDefinitionStatus.left().value();
3401                     artifactData.setId(artifactDefinition.getUniqueId());
3402                     CassandraOperationStatus saveArtifactStatus = artifactCassandraDao.saveArtifact(artifactData);
3403
3404                     if (saveArtifactStatus == CassandraOperationStatus.OK) {
3405                         if (!inTransaction) {
3406                             janusGraphDao.commit();
3407                         }
3408                         log.debug("Artifact Saved In cassandra {}", artifactData.getId());
3409                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
3410                         handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition, artifactDefinition
3411                                         .getUniqueId(), artifactDefinition.getUniqueId(), responseFormat,
3412                                 ComponentTypeEnum.RESOURCE_INSTANCE, resourceInstanceName);
3413
3414                     }
3415                     else {
3416                         if (!inTransaction) {
3417                             janusGraphDao.rollback();
3418                         }
3419                         log.info("Failed to save artifact {}.", artifactData.getId());
3420                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
3421                         handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition, artifactDefinition
3422                                         .getUniqueId(), artifactDefinition.getUniqueId(), responseFormat,
3423                                 ComponentTypeEnum.RESOURCE_INSTANCE, resourceInstanceName);
3424
3425                         return Either.right(responseFormat);
3426                     }
3427                 }
3428                 else {
3429                     ResponseFormat responseFormat = componentsUtils.getResponseFormatByArtifactId(componentsUtils.convertFromStorageResponse(updateArifactDefinitionStatus
3430                             .right()
3431                             .value()), artifactDefinition.getArtifactDisplayName());
3432                     log.debug("Failed To update artifact {}", artifactData.getId());
3433                     handleAuditing(AuditingActionEnum.ARTIFACT_PAYLOAD_UPDATE, component, component.getUniqueId(), modifier, artifactDefinition, artifactDefinition
3434                                     .getUniqueId(), artifactDefinition.getUniqueId(), responseFormat,
3435                             ComponentTypeEnum.RESOURCE_INSTANCE, resourceInstanceName);
3436
3437                     return Either.right(responseFormat);
3438
3439                 }
3440             }
3441             finally {
3442                 if (shouldLock) {
3443                     graphLockOperation.unlockComponent(component.getUniqueId(), component.getComponentType()
3444                             .getNodeType());
3445                 }
3446             }
3447         }
3448
3449         return Either.left(artifactDefinition);
3450     }
3451
3452
3453     public Map<String, Object> buildJsonForUpdateArtifact(ArtifactDefinition artifactDef, ArtifactGroupTypeEnum artifactGroupType, List<ArtifactTemplateInfo> updatedRequiredArtifacts) {
3454         return this.buildJsonForUpdateArtifact(artifactDef.getUniqueId(), artifactDef.getArtifactName(), artifactDef.getArtifactType(), artifactGroupType, artifactDef
3455                         .getArtifactLabel(), artifactDef.getArtifactDisplayName(),
3456                 artifactDef.getDescription(), artifactDef.getPayloadData(), updatedRequiredArtifacts, artifactDef.getListHeatParameters());
3457
3458     }
3459
3460     public Map<String, Object> buildJsonForUpdateArtifact(String artifactId, String artifactName, String artifactType, ArtifactGroupTypeEnum artifactGroupType, String label, String displayName, String description, byte[] artifactContent,
3461                                                           List<ArtifactTemplateInfo> updatedRequiredArtifacts, List<HeatParameterDefinition> heatParameters) {
3462
3463         Map<String, Object> json = new HashMap<>();
3464         if (artifactId != null && !artifactId.isEmpty()) {
3465             json.put(Constants.ARTIFACT_ID, artifactId);
3466         }
3467
3468         json.put(Constants.ARTIFACT_NAME, artifactName);
3469         json.put(Constants.ARTIFACT_TYPE, artifactType);
3470         json.put(Constants.ARTIFACT_DESCRIPTION, description);
3471
3472         if (artifactContent != null) {
3473             log.debug("payload is encoded. perform decode");
3474             String encodedPayload = Base64.encodeBase64String(artifactContent);
3475             json.put(Constants.ARTIFACT_PAYLOAD_DATA, encodedPayload);
3476         }
3477         json.put(Constants.ARTIFACT_DISPLAY_NAME, displayName);
3478         json.put(Constants.ARTIFACT_LABEL, label);
3479         json.put(Constants.ARTIFACT_GROUP_TYPE, artifactGroupType.getType());
3480         json.put(Constants.REQUIRED_ARTIFACTS, (updatedRequiredArtifacts == null || updatedRequiredArtifacts.isEmpty()) ? new ArrayList<>()
3481                 : updatedRequiredArtifacts.stream()
3482                 .filter(e -> e.getType().equals(ArtifactTypeEnum.HEAT_ARTIFACT.getType()) || e
3483                         .getType()
3484                         .equals(ArtifactTypeEnum.HEAT_NESTED.getType()))
3485                 .map(ArtifactTemplateInfo::getFileName)
3486                 .collect(Collectors.toList()));
3487         json.put(Constants.ARTIFACT_HEAT_PARAMS, (heatParameters == null || heatParameters.isEmpty()) ? new ArrayList<>()
3488                 : heatParameters);
3489         return json;
3490     }
3491
3492     public Either<ArtifactDefinition, Operation> updateResourceInstanceArtifactNoContent(String resourceId, Component containerComponent, User user, Map<String, Object> json, ArtifactOperationInfo operation, ArtifactDefinition artifactInfo) {
3493
3494         String jsonStr = gson.toJson(json);
3495         ArtifactDefinition artifactDefinitionFromJson = artifactInfo == null ? RepresentationUtils.convertJsonToArtifactDefinition(jsonStr, ArtifactDefinition.class, false) : artifactInfo;
3496         String artifactUniqueId = artifactDefinitionFromJson == null ? null : artifactDefinitionFromJson.getUniqueId();
3497         Either<ArtifactDefinition, Operation> uploadArtifactToService = validateAndHandleArtifact(resourceId, ComponentTypeEnum.RESOURCE_INSTANCE, operation, artifactUniqueId,
3498                 artifactDefinitionFromJson, null, jsonStr, null, null, user, containerComponent, false, false, true);
3499
3500         return Either.left(uploadArtifactToService.left().value());
3501     }
3502
3503     private Either<ArtifactDefinition, Operation> handleUpdateHeatEnvAndHeatMeta(String componentId, ArtifactDefinition artifactInfo, AuditingActionEnum auditingAction, String artifactId, User user, ComponentTypeEnum componentType,
3504                                                                                  Component parent, String originData, String origMd5, ArtifactOperationInfo operation) {
3505         if (origMd5 != null) {
3506             validateMd5(origMd5, originData, artifactInfo.getPayloadData(), operation);
3507             if (ArrayUtils.isNotEmpty(artifactInfo.getPayloadData())) {
3508                 validateDeploymentArtifact(artifactInfo, parent);
3509                 handlePayload(artifactInfo, isArtifactMetadataUpdate(auditingAction));
3510             } else { // duplicate
3511                 throw new ByActionStatusComponentException(ActionStatus.MISSING_DATA, ARTIFACT_PAYLOAD);
3512             }
3513         }
3514         return updateHeatEnvParamsAndMetadata(componentId, artifactId, artifactInfo, user, auditingAction, parent, componentType, origMd5);
3515     }
3516
3517     private Either<ArtifactDefinition, Operation> updateHeatEnvParamsAndMetadata(String componentId, String artifactId, ArtifactDefinition artifactInfo, User user, AuditingActionEnum auditingAction, Component parent,
3518                                                                                  ComponentTypeEnum componentType, String origMd5) {
3519         Either<ComponentInstance, ResponseFormat> getRI = getRIFromComponent(parent, componentId, artifactId, auditingAction, user);
3520         if (getRI.isRight()) {
3521             throw new ByResponseFormatComponentException(getRI.right().value());
3522         }
3523         ComponentInstance ri = getRI.left().value();
3524         Either<ArtifactDefinition, ResponseFormat> getArtifactRes = getArtifactFromRI(parent, ri, componentId, artifactId, auditingAction, user);
3525         if (getArtifactRes.isRight()) {
3526             throw new ByResponseFormatComponentException(getArtifactRes.right().value());
3527         }
3528         ArtifactDefinition currArtifact = getArtifactRes.left().value();
3529
3530         if (currArtifact.getArtifactType().equals(ArtifactTypeEnum.HEAT.getType()) ||
3531                 currArtifact.getArtifactType().equals(ArtifactTypeEnum.HEAT_VOL.getType()) ||
3532                 currArtifact.getArtifactType().equals(ArtifactTypeEnum.HEAT_NET.getType())) {
3533             throw new ByActionStatusComponentException(ActionStatus.RESTRICTED_OPERATION);
3534         }
3535         List<HeatParameterDefinition> currentHeatEnvParams = currArtifact.getListHeatParameters();
3536         List<HeatParameterDefinition> updatedHeatEnvParams = artifactInfo.getListHeatParameters();
3537
3538         // upload
3539         if (origMd5 != null) {
3540             Either<List<HeatParameterDefinition>, ResponseFormat> uploadParamsValidationResult = validateUploadParamsFromEnvFile(auditingAction, parent, user, artifactInfo,
3541                     artifactId, componentType, ri.getName(), currentHeatEnvParams, updatedHeatEnvParams, currArtifact.getArtifactName());
3542             if (uploadParamsValidationResult.isRight()) {
3543                 throw new ByResponseFormatComponentException(uploadParamsValidationResult.right().value());
3544             }
3545             artifactInfo.setListHeatParameters(updatedHeatEnvParams);
3546         }
3547
3548         Either<ArtifactDefinition, ResponseFormat> validateAndConvertHeatParamers = validateAndConvertHeatParameters(artifactInfo, ArtifactTypeEnum.HEAT_ENV.getType());
3549         if (validateAndConvertHeatParamers.isRight()) {
3550             throw new ByResponseFormatComponentException(validateAndConvertHeatParamers.right().value());
3551         }
3552
3553         if (updatedHeatEnvParams != null && !updatedHeatEnvParams.isEmpty()) {
3554             // fill reduced heat env parameters List for updating
3555             boolean updateRequired = replaceCurrHeatValueWithUpdatedValue(currentHeatEnvParams, updatedHeatEnvParams);
3556             if (updateRequired) {
3557                 currArtifact.setHeatParamsUpdateDate(System.currentTimeMillis());
3558                 currArtifact.setListHeatParameters(currentHeatEnvParams);
3559                 Either<ArtifactDefinition, StorageOperationStatus> updateArtifactRes = artifactToscaOperation.updateArtifactOnResource(
3560                         currArtifact, parent, currArtifact.getUniqueId(), componentType.getNodeType(), componentId, true);
3561                 if (updateArtifactRes.isRight()) {
3562                     log.debug("Failed to update artifact on graph  - {}", artifactId);
3563                     throw new StorageException(updateArtifactRes.right().value());
3564                 }
3565                 StorageOperationStatus error = generateCustomizationUUIDOnGroupInstance(ri, updateArtifactRes.left().value().getUniqueId(), parent.getUniqueId());
3566                 if (error != StorageOperationStatus.OK) {
3567                     throw new StorageException(error);
3568                 }
3569             }
3570         }
3571         updateHeatMetaDataIfNeeded(componentId,user,auditingAction,componentType, parent,ri,artifactInfo);
3572         StorageOperationStatus error = generateCustomizationUUIDOnInstance(parent.getUniqueId(), ri.getUniqueId(), componentType);
3573         if (error != StorageOperationStatus.OK) {
3574             throw new StorageException(error);
3575         }
3576
3577         return Either.left(currArtifact);
3578     }
3579
3580     private void
3581     updateHeatMetaDataIfNeeded(String componentId, User user, AuditingActionEnum auditingAction, ComponentTypeEnum componentType, Component parent, ComponentInstance resourceInstance, ArtifactDefinition updatedHeatEnvArtifact) {
3582         String heatArtifactId = updatedHeatEnvArtifact.getGeneratedFromId();
3583         Either<ArtifactDefinition, ResponseFormat> getArtifactRes = getArtifactFromRI(parent, resourceInstance, componentId, heatArtifactId, auditingAction, user);
3584         if (getArtifactRes.isRight()) {
3585             throw new ByResponseFormatComponentException(getArtifactRes.right().value());
3586         }
3587         ArtifactDefinition heatArtifactToUpdate = getArtifactRes.left().value();
3588         if (isUpdateHeatMetaDataNeeded(updatedHeatEnvArtifact, heatArtifactToUpdate)) {
3589             validateHeatMetaData(updatedHeatEnvArtifact);
3590             updateHeatMetadataFromHeatEnv(updatedHeatEnvArtifact, heatArtifactToUpdate);
3591             Either<ArtifactDefinition, StorageOperationStatus> updateArtifactRes = artifactToscaOperation.updateArtifactOnResource(heatArtifactToUpdate, parent,
3592                     heatArtifactToUpdate.getUniqueId(), componentType.getNodeType(), componentId, false);
3593
3594             if (updateArtifactRes.isRight()) {
3595                 log.debug("Failed to update artifact on graph  - {}", heatArtifactId);
3596                 throw new StorageException(updateArtifactRes.right().value());
3597             }
3598             ArtifactDefinition artifactDefinition = updateArtifactRes.left().value();
3599             updateGeneratedIdInHeatEnvOnInstance(resourceInstance, parent, heatArtifactId, heatArtifactToUpdate, artifactDefinition, componentType.getNodeType());
3600             StorageOperationStatus error = generateCustomizationUUIDOnGroupInstance(resourceInstance, artifactDefinition.getUniqueId(), parent.getUniqueId());
3601             if (error != StorageOperationStatus.OK) {
3602                 throw new StorageException(error);
3603             }
3604         }
3605     }
3606
3607     private void validateHeatMetaData(ArtifactDefinition updatedHeatEnv) {
3608         Integer maxMinutes = ConfigurationManager.getConfigurationManager().getConfiguration().getHeatArtifactDeploymentTimeout().getMaxMinutes();
3609         Integer minMinutes = ConfigurationManager.getConfigurationManager().getConfiguration().getHeatArtifactDeploymentTimeout().getMinMinutes();
3610         Integer updateTimeout = updatedHeatEnv.getTimeout();
3611         if (updateTimeout > maxMinutes || updateTimeout < minMinutes) {
3612             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_INVALID_TIMEOUT);
3613         }
3614     }
3615
3616     private boolean isUpdateHeatMetaDataNeeded(ArtifactDefinition updatedHeatEnv, ArtifactDefinition origHeat) {
3617         // currently only timeout metadata can be updated
3618         return !origHeat.getTimeout().equals(updatedHeatEnv.getTimeout());
3619     }
3620
3621     private void updateHeatMetadataFromHeatEnv(ArtifactDefinition updatedHeatEnv, ArtifactDefinition origHeat) {
3622         // currently only timeout metadata can be updated
3623         origHeat.setTimeout(updatedHeatEnv.getTimeout());
3624     }
3625
3626     private boolean replaceCurrHeatValueWithUpdatedValue(List<HeatParameterDefinition> currentHeatEnvParams, List<HeatParameterDefinition> updatedHeatEnvParams) {
3627         boolean isUpdate = false;
3628         List<String> currentParamsNames = currentHeatEnvParams.stream().map(x -> x.getName()).collect(Collectors.toList());
3629         for (HeatParameterDefinition heatEnvParam : updatedHeatEnvParams) {
3630             String paramName = heatEnvParam.getName();
3631             validateParamName(paramName, currentParamsNames);
3632             for (HeatParameterDefinition currHeatParam : currentHeatEnvParams) {
3633                 if (paramName.equalsIgnoreCase(currHeatParam.getName())) {
3634                     String updatedParamValue = heatEnvParam.getCurrentValue();
3635                     if (!Objects.equals(updatedParamValue, currHeatParam.getCurrentValue())) {
3636                         currHeatParam.setCurrentValue(updatedParamValue);
3637                         isUpdate = true;
3638                     }
3639                 }
3640             }
3641         }
3642         return isUpdate;
3643     }
3644
3645     private void validateParamName(String paramName, List<String> heatParamsNames) {
3646         if (!heatParamsNames.contains(paramName)) {
3647             throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, paramName);
3648         }
3649     }
3650
3651     private Either<ArtifactDefinition, Operation> updateHeatParams(String componentId, ArtifactDefinition artifactEnvInfo, AuditingActionEnum auditingAction, Component parent,
3652                                                                    ComponentTypeEnum componentType, ArtifactDefinition currHeatArtifact, boolean needToUpdateGroup) {
3653         Either<ArtifactDefinition, Operation> insideEither = null;
3654         String currentHeatId = currHeatArtifact.getUniqueId();
3655
3656         String esArtifactId = currHeatArtifact.getEsId();
3657         Either<DAOArtifactData, CassandraOperationStatus> artifactFromES = artifactCassandraDao.getArtifact(esArtifactId);
3658         if (artifactFromES.isRight()) {
3659             StorageOperationStatus storageResponse = DaoStatusConverter.convertCassandraStatusToStorageStatus(artifactFromES.right().value());
3660             throw new StorageException(storageResponse, currHeatArtifact.getArtifactDisplayName());
3661         }
3662
3663         DAOArtifactData DAOArtifactData = artifactFromES.left().value();
3664         ArtifactDefinition updatedHeatArt = currHeatArtifact;
3665         List<HeatParameterDefinition> updatedHeatEnvParams = artifactEnvInfo.getListHeatParameters();
3666         List<HeatParameterDefinition> currentHeatEnvParams = currHeatArtifact.getListHeatParameters();
3667         List<HeatParameterDefinition> newHeatEnvParams = new ArrayList<>();
3668
3669         if (CollectionUtils.isNotEmpty(updatedHeatEnvParams) && CollectionUtils.isNotEmpty(currentHeatEnvParams)) {
3670             //TODO: improve complexity - currently N^2
3671             String paramName;
3672             for (HeatParameterDefinition heatEnvParam : updatedHeatEnvParams) {
3673                 paramName = heatEnvParam.getName();
3674                 for (HeatParameterDefinition currHeatParam : currentHeatEnvParams) {
3675                     if (paramName.equalsIgnoreCase(currHeatParam.getName())) {
3676                         String updatedParamValue = heatEnvParam.getCurrentValue();
3677                         if (updatedParamValue == null) {
3678                             updatedParamValue = heatEnvParam.getDefaultValue();
3679                         }
3680                         HeatParameterType paramType = HeatParameterType.isValidType(currHeatParam.getType());
3681                         if (!paramType.getValidator().isValid(updatedParamValue, null)) {
3682                             throw new ByActionStatusComponentException(ActionStatus.INVALID_HEAT_PARAMETER_VALUE,
3683                                     ArtifactTypeEnum.HEAT_ENV.getType(), paramType.getType(), paramName);
3684                         }
3685                         currHeatParam.setCurrentValue(paramType.getConverter().convert(updatedParamValue, null, null));
3686                         newHeatEnvParams.add(currHeatParam);
3687                         break;
3688                     }
3689                 }
3690             }
3691             if (!newHeatEnvParams.isEmpty()) {
3692                 currHeatArtifact.setListHeatParameters(currentHeatEnvParams);
3693                 Either<ArtifactDefinition, StorageOperationStatus> operationStatus = artifactToscaOperation.updateArtifactOnResource(
3694                         currHeatArtifact, parent, currHeatArtifact.getUniqueId(), componentType.getNodeType(), componentId, true);
3695
3696                 if (operationStatus.isRight()) {
3697                     log.debug("Failed to update artifact on graph  - {}", currHeatArtifact.getUniqueId());
3698                     throw new StorageException(operationStatus.right().value());
3699                 }
3700                 updatedHeatArt = operationStatus.left().value();
3701                 if (!updatedHeatArt.getDuplicated() || DAOArtifactData.getId() == null) {
3702                     DAOArtifactData.setId(updatedHeatArt.getEsId());
3703                 }
3704                 saveArtifactInCassandra(DAOArtifactData, parent, artifactEnvInfo, currentHeatId, updatedHeatArt
3705                         .getUniqueId(), auditingAction, componentType);
3706                 insideEither = Either.left(updatedHeatArt);
3707             }
3708         }
3709         Either<ArtifactDefinition, StorageOperationStatus> updateHeatEnvArtifact;
3710         if (!currentHeatId.equals(updatedHeatArt.getUniqueId())) {
3711             artifactEnvInfo.setArtifactChecksum(null);
3712             updateHeatEnvArtifact = artifactToscaOperation.updateHeatEnvArtifact(parent, artifactEnvInfo, currentHeatId, updatedHeatArt
3713                     .getUniqueId(), componentType.getNodeType(), componentId);
3714         }
3715         else {
3716             //TODO Andrey check if componentId = parent.getUniqeId
3717             updateHeatEnvArtifact = artifactToscaOperation.updateHeatEnvPlaceholder(artifactEnvInfo, parent, componentType
3718                     .getNodeType());
3719
3720         }
3721         if (needToUpdateGroup && updateHeatEnvArtifact.isLeft()) {
3722             ActionStatus result = updateGroupForHeat(currHeatArtifact, updatedHeatArt, artifactEnvInfo,
3723                     updateHeatEnvArtifact.left().value(), parent);
3724             if (result != ActionStatus.OK) {
3725                 throw new ByActionStatusComponentException(result);
3726             }
3727         }
3728         if (updatedHeatEnvParams.isEmpty()) {
3729             throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML, currHeatArtifact.getArtifactName());
3730         }
3731         return insideEither;
3732     }
3733
3734
3735     private StorageOperationStatus generateCustomizationUUIDOnGroupInstance(ComponentInstance ri, String artifactId, String componentId) {
3736         StorageOperationStatus error = StorageOperationStatus.OK;
3737         log.debug("Need to re-generate  customization UUID for group instance on component instance  {}", ri.getUniqueId());
3738         List<GroupInstance> groupsInstances = ri.getGroupInstances();
3739         List<String> groupInstancesId = null;
3740         if (groupsInstances != null && !groupsInstances.isEmpty()) {
3741             groupInstancesId = groupsInstances.stream()
3742                     .filter(p -> p.getGroupInstanceArtifacts() != null && p.getGroupInstanceArtifacts()
3743                             .contains(artifactId))
3744                     .map(GroupInstanceDataDefinition::getUniqueId)
3745                     .collect(Collectors.toList());
3746         }
3747         if (groupInstancesId != null && !groupInstancesId.isEmpty()) {
3748             toscaOperationFacade.generateCustomizationUUIDOnInstanceGroup(componentId, ri.getUniqueId(), groupInstancesId);
3749         }
3750         return error;
3751
3752     }
3753
3754     public Either<List<HeatParameterDefinition>, ResponseFormat> validateUploadParamsFromEnvFile(AuditingActionEnum auditingAction, Component parent, User user, ArtifactDefinition artifactInfo, String artifactId, ComponentTypeEnum componentType,
3755                                                                                                  String riName, List<HeatParameterDefinition> currentHeatEnvParams, List<HeatParameterDefinition> updatedHeatEnvParams, String currArtifactName) {
3756
3757         if (updatedHeatEnvParams == null || updatedHeatEnvParams.isEmpty()) {
3758             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_DEPLOYMENT_ARTIFACT_HEAT, artifactInfo
3759                     .getArtifactName(), currArtifactName);
3760             handleAuditing(auditingAction, parent, parent.getUniqueId(), user, artifactInfo, null, artifactId, responseFormat, componentType, riName);
3761             return Either.right(responseFormat);
3762         }
3763
3764         for (HeatParameterDefinition uploadedHeatParam : updatedHeatEnvParams) {
3765             String paramName = uploadedHeatParam.getName();
3766             boolean isExistsInHeat = false;
3767             for (HeatParameterDefinition currHeatParam : currentHeatEnvParams) {
3768                 if (paramName.equalsIgnoreCase(currHeatParam.getName())) {
3769
3770                     isExistsInHeat = true;
3771                     uploadedHeatParam.setType(currHeatParam.getType());
3772                     uploadedHeatParam.setCurrentValue(uploadedHeatParam.getDefaultValue());
3773                     uploadedHeatParam.setDefaultValue(currHeatParam.getDefaultValue());
3774                     uploadedHeatParam.setUniqueId(currHeatParam.getUniqueId());
3775                     break;
3776                 }
3777             }
3778             if (!isExistsInHeat) {
3779                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISMATCH_HEAT_VS_HEAT_ENV, currArtifactName);
3780                 handleAuditing(auditingAction, parent, parent.getUniqueId(), user, artifactInfo, null, artifactId, responseFormat, componentType, riName);
3781                 return Either.right(responseFormat);
3782             }
3783         }
3784         return Either.left(updatedHeatEnvParams);
3785     }
3786
3787     private Either<ComponentInstance, ResponseFormat> getRIFromComponent(Component component, String riID, String artifactId, AuditingActionEnum auditingAction, User user) {
3788         ResponseFormat responseFormat = null;
3789         List<ComponentInstance> ris = component.getComponentInstances();
3790         for (ComponentInstance ri : ris) {
3791             if (riID.equals(ri.getUniqueId())) {
3792                 return Either.left(ri);
3793             }
3794         }
3795         responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE, riID);
3796         log.debug("Resource Instance not found, resourceInstanceId {}", riID);
3797         handleAuditing(auditingAction, null, riID, user, null, null, artifactId, responseFormat, ComponentTypeEnum.RESOURCE_INSTANCE, null);
3798         return Either.right(responseFormat);
3799     }
3800
3801     private Either<ArtifactDefinition, ResponseFormat> getArtifactFromRI(Component component, ComponentInstance ri, String riID, String artifactId, AuditingActionEnum auditingAction, User user) {
3802         ResponseFormat responseFormat = null;
3803         Map<String, ArtifactDefinition> rtifactsMap = ri.getDeploymentArtifacts();
3804         for (ArtifactDefinition artifact : rtifactsMap.values()) {
3805             if (artifactId.equals(artifact.getUniqueId())) {
3806                 return Either.left(artifact);
3807             }
3808         }
3809         responseFormat = componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND, riID, component.getUniqueId());
3810         handleAuditing(auditingAction, component, riID, user, null, null, artifactId, responseFormat, ComponentTypeEnum.RESOURCE_INSTANCE, ri
3811                 .getName());
3812         return Either.right(responseFormat);
3813     }
3814
3815     public ArtifactDefinition extractArtifactDefinition(Either<ArtifactDefinition, Operation> eitherArtifact) {
3816         ArtifactDefinition ret;
3817         if (eitherArtifact.isLeft()) {
3818             ret = eitherArtifact.left().value();
3819         }
3820         else {
3821             ret = eitherArtifact.right().value().getImplementationArtifact();
3822         }
3823         return ret;
3824     }
3825
3826     public byte[] downloadComponentArtifactByUUIDs(ComponentTypeEnum componentType, String componentUuid, String artifactUUID, ResourceCommonInfo resourceCommonInfo) {
3827         Component component = getComponentByUuid(componentType, componentUuid);
3828         resourceCommonInfo.setResourceName(component.getName());
3829         return downloadArtifact(component.getAllArtifacts(), artifactUUID, component.getName());
3830     }
3831
3832     /**
3833      * downloads an artifact of resource instance of component by UUIDs
3834      *
3835      * @param componentType
3836      * @param componentUuid
3837      * @param resourceInstanceName
3838      * @param artifactUUID
3839      * @return
3840      */
3841     public byte[] downloadResourceInstanceArtifactByUUIDs(ComponentTypeEnum componentType, String componentUuid,
3842                                                           String resourceInstanceName, String artifactUUID) {
3843         ComponentInstance resourceInstance = getRelatedComponentInstance(componentType, componentUuid, resourceInstanceName);
3844
3845         if (resourceInstance != null) {
3846             return downloadArtifact(resourceInstance.getDeploymentArtifacts(), artifactUUID, resourceInstance.getName());
3847         } else {
3848             return downloadArtifact(null, artifactUUID, null);
3849         }
3850     }
3851
3852     /**
3853      * uploads an artifact to a component by UUID
3854      *
3855      * @param data
3856      * @param request
3857      * @param componentType
3858      * @param componentUuid
3859      * @param resourceCommonInfo
3860      * @param operation
3861      * @return
3862      */
3863     public ArtifactDefinition uploadArtifactToComponentByUUID(String data, HttpServletRequest request, ComponentTypeEnum componentType,
3864                                                               String componentUuid, ResourceCommonInfo resourceCommonInfo,                                                                                      ArtifactOperationInfo operation) {
3865         Either<ArtifactDefinition, Operation> actionResult;
3866         Component component;
3867         String componentId;
3868         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinition(data, ArtifactDefinition.class, false);
3869         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3870         String userId = request.getHeader(Constants.USER_ID_HEADER);
3871
3872         Either<ComponentMetadataData, ActionStatus> getComponentRes =
3873             fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
3874
3875         ComponentMetadataDataDefinition componentMetadataDataDefinition = getComponentRes.left().value().getMetadataDataDefinition();
3876         componentId = componentMetadataDataDefinition.getUniqueId();
3877         String componentName = componentMetadataDataDefinition.getName();
3878
3879         if (!componentMetadataDataDefinition
3880                 .getState()
3881                 .equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3882             component = checkoutParentComponent(componentType, componentId, userId);
3883             if (component != null) {
3884                 componentId = component.getUniqueId();
3885                 componentName = component.getName();
3886             }
3887         }
3888         resourceCommonInfo.setResourceName(componentName);
3889
3890         actionResult = handleArtifactRequest(componentId, userId, componentType, operation, null, artifactInfo,
3891                 origMd5, data, null, null, null, null);
3892         return actionResult.left().value();
3893     }
3894
3895     /**
3896      * upload an artifact to a resource instance by UUID
3897      *
3898      * @param data
3899      * @param request
3900      * @param componentType
3901      * @param componentUuid
3902      * @param resourceInstanceName
3903      * @param operation
3904      * @return
3905      */
3906     public ArtifactDefinition uploadArtifactToRiByUUID(String data, HttpServletRequest request, ComponentTypeEnum componentType, String componentUuid, String resourceInstanceName,
3907                                                        ArtifactOperationInfo operation) {
3908         Either<ArtifactDefinition, Operation> actionResult;
3909         Component component = null;
3910         String componentInstanceId;
3911         String componentId;
3912         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3913         String userId = request.getHeader(Constants.USER_ID_HEADER);
3914
3915         ImmutablePair<Component, ComponentInstance> componentRiPair = null;
3916
3917         Either<ComponentMetadataData, ActionStatus> getComponentRes =
3918             fetchLatestComponentMetadataOrThrow(componentType, componentUuid, resourceInstanceName);
3919         if (!getComponentRes.left()
3920                 .value()
3921                 .getMetadataDataDefinition()
3922                 .getState()
3923                 .equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3924             component = checkoutParentComponent(componentType, getComponentRes.left()
3925                     .value()
3926                     .getMetadataDataDefinition()
3927                     .getUniqueId(), userId);
3928         }
3929         if (component == null) {
3930             componentRiPair = getRelatedComponentComponentInstance(componentType, componentUuid, resourceInstanceName);
3931         }
3932         else {
3933             componentRiPair = getRelatedComponentComponentInstance(component, resourceInstanceName);
3934         }
3935         componentInstanceId = componentRiPair.getRight().getUniqueId();
3936         componentId = componentRiPair.getLeft().getUniqueId();
3937         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinition(data, ArtifactDefinition.class, false);
3938
3939         actionResult = handleArtifactRequest(componentInstanceId, userId, ComponentTypeEnum.RESOURCE_INSTANCE,
3940                 operation, null, artifactInfo, origMd5, data, null, null,
3941                 componentId, ComponentTypeEnum.findParamByType(componentType));
3942
3943         return actionResult.left().value();
3944     }
3945
3946     /**
3947      * updates an artifact on a component by UUID
3948      *
3949      * @param data
3950      * @param request
3951      * @param componentType
3952      * @param componentUuid
3953      * @param artifactUUID
3954      * @param resourceCommonInfo
3955      * @param operation        TODO
3956      * @return
3957      */
3958     public ArtifactDefinition updateArtifactOnComponentByUUID(String data, HttpServletRequest request, ComponentTypeEnum componentType, String componentUuid, String artifactUUID,
3959                                                               ResourceCommonInfo resourceCommonInfo, ArtifactOperationInfo operation) {
3960         Either<ArtifactDefinition, Operation> actionResult;
3961         Component component;
3962         String componentId;
3963         String artifactId ;
3964         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinitionForUpdate(data, ArtifactDefinition.class);
3965         String origMd5 = request.getHeader(Constants.MD5_HEADER);
3966         String userId = request.getHeader(Constants.USER_ID_HEADER);
3967
3968         Either<ComponentMetadataData, ActionStatus> getComponentRes =
3969             fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
3970         componentId = getComponentRes.left().value().getMetadataDataDefinition().getUniqueId();
3971         String componentName = getComponentRes.left().value().getMetadataDataDefinition().getName();
3972
3973         if (!getComponentRes.left()
3974                 .value()
3975                 .getMetadataDataDefinition()
3976                 .getState()
3977                 .equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
3978             component = checkoutParentComponent(componentType, componentId, userId);
3979             if (component != null) {
3980                 componentId = component.getUniqueId();
3981                 componentName = component.getName();
3982             }
3983         }
3984         resourceCommonInfo.setResourceName(componentName);
3985         artifactId = getLatestParentArtifactDataIdByArtifactUUID(artifactUUID, componentId, componentType);
3986         actionResult = handleArtifactRequest(componentId, userId, componentType, operation, artifactId, artifactInfo,
3987                 origMd5, data, null, null, null, null);
3988         if (actionResult.isRight()) {
3989             log.debug(FAILED_UPLOAD_ARTIFACT_TO_COMPONENT, componentType, componentUuid, actionResult
3990                     .right()
3991                     .value());
3992         }
3993
3994         return actionResult.left().value();
3995     }
3996
3997     /**
3998      * updates an artifact on a resource instance by UUID
3999      *
4000      * @param data
4001      * @param request
4002      * @param componentType
4003      * @param componentUuid
4004      * @param resourceInstanceName
4005      * @param artifactUUID
4006      * @param operation            TODO
4007      * @return
4008      */
4009     public ArtifactDefinition updateArtifactOnRiByUUID(String data, HttpServletRequest request, ComponentTypeEnum componentType, String componentUuid, String resourceInstanceName, String artifactUUID,
4010                                                        ArtifactOperationInfo operation) {
4011
4012         Either<ArtifactDefinition, Operation> actionResult;
4013         Component component = null;
4014         String componentInstanceId;
4015         String componentId;
4016         String artifactId;
4017         String origMd5 = request.getHeader(Constants.MD5_HEADER);
4018         String userId = request.getHeader(Constants.USER_ID_HEADER);
4019
4020         ImmutablePair<Component, ComponentInstance> componentRiPair = null;
4021         Either<ComponentMetadataData, ActionStatus> getComponentRes =
4022             fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
4023         if (!getComponentRes.left()
4024                 .value()
4025                 .getMetadataDataDefinition()
4026                 .getState()
4027                 .equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
4028             component = checkoutParentComponent(componentType, getComponentRes.left()
4029                     .value()
4030                     .getMetadataDataDefinition()
4031                     .getUniqueId(), userId);
4032         }
4033         if (component == null) {
4034             componentRiPair = getRelatedComponentComponentInstance(componentType, componentUuid, resourceInstanceName);
4035         }
4036         else {
4037             componentRiPair = getRelatedComponentComponentInstance(component, resourceInstanceName);
4038         }
4039         componentInstanceId = componentRiPair.getRight().getUniqueId();
4040         componentId = componentRiPair.getLeft().getUniqueId();
4041         artifactId = findArtifactId(componentRiPair.getRight(), artifactUUID);
4042         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinition(data, ArtifactDefinition.class, false);
4043
4044         actionResult = handleArtifactRequest(componentInstanceId, userId, ComponentTypeEnum.RESOURCE_INSTANCE, operation, artifactId, artifactInfo, origMd5, data, null, null, componentId, ComponentTypeEnum
4045                 .findParamByType(componentType));
4046         return actionResult.left().value();
4047     }
4048
4049     private Either<ArtifactDefinition, ResponseFormat> updateOperationArtifact(String componentId, String interfaceType, String operationUuid, ArtifactDefinition artifactInfo){
4050         Either<Component, StorageOperationStatus> componentStorageOperationStatusEither = toscaOperationFacade.getToscaElement(componentId);
4051         if (componentStorageOperationStatusEither.isRight()) {
4052             StorageOperationStatus errorStatus = componentStorageOperationStatusEither.right().value();
4053             log.debug("Failed to fetch resource information by resource id, error {}", errorStatus);
4054             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
4055         }
4056         Component storedComponent = componentStorageOperationStatusEither.left().value();
4057
4058         Optional<InterfaceDefinition> optionalInterface = InterfaceOperationUtils.getInterfaceDefinitionFromComponentByInterfaceType(storedComponent, interfaceType);
4059         if(!optionalInterface.isPresent()) {
4060             log.debug("Failed to get resource interface for resource Id {}", componentId);
4061             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceType));
4062         }
4063
4064         //fetch the operation from storage
4065         InterfaceDefinition gotInterface = optionalInterface.get();
4066         Map<String, Operation> operationsMap = gotInterface.getOperationsMap();
4067         Optional<Operation> optionalOperation = operationsMap.values()
4068                 .stream()
4069                 .filter(o -> o.getUniqueId().equals(operationUuid))
4070                 .findFirst();
4071         if (!optionalOperation.isPresent()) {
4072             log.debug("Failed to get resource interface operation for resource Id {} and operationId {}", componentId, operationUuid);
4073             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, componentId);
4074             return Either.right(responseFormat);
4075         }
4076
4077         Operation operation = optionalOperation.get();
4078         ArtifactDefinition implementationArtifact =  operation.getImplementationArtifact();
4079         implementationArtifact.setArtifactUUID(artifactInfo.getArtifactUUID());
4080         implementationArtifact.setUniqueId(artifactInfo.getUniqueId());
4081         implementationArtifact.setArtifactName(artifactInfo.getArtifactName());
4082         implementationArtifact.setDescription(artifactInfo.getDescription());
4083         implementationArtifact.setArtifactType(artifactInfo.getArtifactType());
4084         implementationArtifact.setArtifactLabel(artifactInfo.getArtifactLabel());
4085         implementationArtifact.setArtifactDisplayName(artifactInfo.getArtifactDisplayName());
4086         implementationArtifact.setEsId(artifactInfo.getEsId());
4087         operation.setImplementation(implementationArtifact);
4088         gotInterface.setOperationsMap(operationsMap);
4089         Either<List<InterfaceDefinition>, StorageOperationStatus> interfaceDefinitionStorageOperationStatusEither =
4090                 interfaceOperation.updateInterfaces(storedComponent.getUniqueId(), Collections.singletonList(gotInterface));
4091         if (interfaceDefinitionStorageOperationStatusEither.isRight()){
4092             StorageOperationStatus storageOperationStatus = interfaceDefinitionStorageOperationStatusEither.right().value();
4093             ActionStatus actionStatus =
4094                     componentsUtils.convertFromStorageResponseForDataType(storageOperationStatus);
4095             return Either.right(componentsUtils.getResponseFormat(actionStatus));
4096         }
4097
4098         return Either.left(artifactInfo);
4099     }
4100
4101     /**
4102      * updates an artifact on a component by UUID
4103      *
4104      * @param data
4105      * @param request
4106      * @param componentType
4107      * @param componentUuid
4108      * @param artifactUUID
4109      * @param operation
4110      * @return
4111      */
4112     public Either<ArtifactDefinition, ResponseFormat> updateArtifactOnInterfaceOperationByResourceUUID(
4113             String data, HttpServletRequest request, ComponentTypeEnum componentType,
4114             String componentUuid, String interfaceUUID, String operationUUID, String artifactUUID,
4115         ResourceCommonInfo resourceCommonInfo,ArtifactOperationInfo operation) {
4116         Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
4117         Either<ArtifactDefinition, ResponseFormat> updateArtifactResult;
4118         Either<Either<ArtifactDefinition, Operation>, ResponseFormat> actionResult = null;
4119         ArtifactDefinition updateArtifact = null;
4120         String componentId = null;
4121         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinitionForUpdate(data, ArtifactDefinition.class);
4122         String origMd5 = request.getHeader(Constants.MD5_HEADER);
4123         String userId = request.getHeader(Constants.USER_ID_HEADER);
4124         ArtifactDefinition existingArtifactInfo = null;
4125         String interfaceName = null;
4126
4127         Either<ComponentMetadataData, ActionStatus> getComponentRes =
4128             fetchLatestComponentMetadata(componentType, componentUuid).right().map(as -> {
4129                 errorWrapper.setInnerElement(componentsUtils.getResponseFormat(as));
4130                 return as;
4131             });
4132
4133         if(getComponentRes.isRight()) {
4134             errorWrapper.setInnerElement(componentsUtils.getResponseFormat(getComponentRes.right().value()));
4135         }
4136
4137         if (errorWrapper.isEmpty()) {
4138             componentId = getComponentRes.left().value().getMetadataDataDefinition().getUniqueId();
4139             String componentName = getComponentRes.left().value().getMetadataDataDefinition().getName();
4140             if (!getComponentRes.left()
4141                     .value()
4142                     .getMetadataDataDefinition()
4143                     .getState()
4144                     .equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
4145                 Component component = checkoutParentComponent(componentType, componentId, userId);
4146                 if (component != null) {
4147                     componentId = component.getUniqueId();
4148                     componentName = component.getName();
4149                 }
4150
4151             }
4152             resourceCommonInfo.setResourceName(componentName);
4153         }
4154
4155         if(errorWrapper.isEmpty()){
4156             Either<String, ResponseFormat> interfaceNameEither = fetchInterfaceName(componentId, interfaceUUID);
4157             if (interfaceNameEither.isRight()) {
4158                 errorWrapper.setInnerElement(interfaceNameEither.right().value());
4159             }
4160             else {
4161                 interfaceName = interfaceNameEither.left().value();
4162             }
4163
4164             if(errorWrapper.isEmpty()){
4165                 Either<Component, StorageOperationStatus> toscaComponentEither = toscaOperationFacade.getToscaElement(componentId);
4166                 if (toscaComponentEither.isRight()) {
4167                     StorageOperationStatus status = toscaComponentEither.right().value();
4168                     log.debug("Could not fetch component with type {} and id {}. Status is {}. ", componentType, componentId, status);
4169                     errorWrapper.setInnerElement(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status)));
4170                 }
4171
4172                 if (errorWrapper.isEmpty()) {
4173                     NodeTypeEnum parentType = convertParentType(componentType);
4174                     final List<ArtifactDefinition> existingDeploymentArtifacts =
4175                         getDeploymentArtifacts(toscaComponentEither.left().value(),null);
4176                     for (ArtifactDefinition artifactDefinition: existingDeploymentArtifacts){
4177                         if(artifactInfo.getArtifactName().equalsIgnoreCase(artifactDefinition.getArtifactName())){
4178                             existingArtifactInfo = artifactDefinition;
4179                             break;
4180                         }
4181                     }
4182                     if(existingArtifactInfo != null){
4183                         return updateOperationArtifact(componentId, interfaceName, operationUUID, existingArtifactInfo);
4184                     }
4185                 }
4186             }
4187         }
4188
4189         if (errorWrapper.isEmpty()) {
4190                 try {
4191                     actionResult = Either.left(handleArtifactRequest(componentId, userId, componentType, operation,
4192                             artifactUUID, artifactInfo, origMd5, data, interfaceName,
4193                             operationUUID, null, null));
4194                 }catch (ComponentException e){
4195                     errorWrapper.setInnerElement(e.getResponseFormat());
4196             }
4197         }
4198
4199         if (errorWrapper.isEmpty()) {
4200             updateArtifact = actionResult.left().value().left().value();
4201             updateArtifactResult = Either.left(updateArtifact);
4202
4203         }
4204         else {
4205             updateArtifactResult = Either.right(errorWrapper.getInnerElement());
4206         }
4207         return updateArtifactResult;
4208     }
4209
4210
4211     private Either<ComponentMetadataData, ActionStatus> fetchLatestComponentMetadataOrThrow(
4212         ComponentTypeEnum componentType, String componentUuid
4213     ) {
4214         return fetchLatestComponentMetadataOrThrow(componentType, componentUuid, componentUuid);
4215     }
4216
4217     private Either<ComponentMetadataData, ActionStatus> fetchLatestComponentMetadataOrThrow(
4218         ComponentTypeEnum componentType, String componentUuid, String resourceInstanceName
4219     ) {
4220         return fetchLatestComponentMetadata(componentType, componentUuid).right().map(as -> {
4221             throw new ByActionStatusComponentException(as, resourceInstanceName);
4222         });
4223     }
4224
4225     private Either<ComponentMetadataData, ActionStatus> fetchLatestComponentMetadata(
4226         ComponentTypeEnum componentType, String componentUuid
4227     ) {
4228         return toscaOperationFacade
4229             .getLatestComponentMetadataByUuid(componentUuid, JsonParseFlagEnum.ParseMetadata, true)
4230             .right().map(sos -> {
4231                 log.debug(FAILED_FETCH_COMPONENT, componentType, componentUuid, sos);
4232                 return componentsUtils.convertFromStorageResponse(sos, componentType);
4233             });
4234     }
4235
4236     private Either<String, ResponseFormat> fetchInterfaceName(String componentId, String interfaceUUID) {
4237         Either<Component, StorageOperationStatus> componentStorageOperationStatusEither = toscaOperationFacade.getToscaElement(componentId);
4238         if (componentStorageOperationStatusEither.isRight()) {
4239             StorageOperationStatus errorStatus = componentStorageOperationStatusEither.right().value();
4240             log.debug("Failed to fetch component information by component id, error {}", errorStatus);
4241             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
4242         }
4243         Component storedComponent = componentStorageOperationStatusEither.left().value();
4244
4245         Optional<InterfaceDefinition> optionalInterface = InterfaceOperationUtils
4246             .getInterfaceDefinitionFromComponentByInterfaceId(storedComponent, interfaceUUID);
4247         if(!optionalInterface.isPresent()) {
4248             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceUUID));
4249         }
4250         return Either.left(optionalInterface.get().getType());
4251     }
4252
4253     /**
4254      * deletes an artifact on a component by UUID
4255      *
4256      * @param request
4257      * @param componentType
4258      * @param componentUuid
4259      * @param artifactUUID
4260      * @param resourceCommonInfo
4261      * @param operation        TODO
4262      * @return
4263      */
4264     public ArtifactDefinition deleteArtifactOnComponentByUUID(HttpServletRequest request, ComponentTypeEnum componentType, String componentUuid, String artifactUUID, ResourceCommonInfo resourceCommonInfo,
4265                                                               ArtifactOperationInfo operation) {
4266
4267         Either<ArtifactDefinition, Operation> actionResult;
4268         Component component;
4269         String componentId ;
4270         String artifactId;
4271         String origMd5 = request.getHeader(Constants.MD5_HEADER);
4272         String userId = request.getHeader(Constants.USER_ID_HEADER);
4273
4274         Either<ComponentMetadataData, ActionStatus> getComponentRes =
4275             fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
4276         componentId = getComponentRes.left().value().getMetadataDataDefinition().getUniqueId();
4277         String componentName = getComponentRes.left().value().getMetadataDataDefinition().getName();
4278         if (!getComponentRes.left()
4279                 .value()
4280                 .getMetadataDataDefinition()
4281                 .getState()
4282                 .equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
4283             component = checkoutParentComponent(componentType, componentId, userId);
4284             if (component != null) {
4285                 componentId = component.getUniqueId();
4286                 componentName = component.getName();
4287             }
4288         }
4289         resourceCommonInfo.setResourceName(componentName);
4290         artifactId = getLatestParentArtifactDataIdByArtifactUUID(artifactUUID, componentId, componentType);
4291         actionResult = handleArtifactRequest(componentId, userId, componentType, operation, artifactId, null, origMd5, null, null, null, null, null);
4292         return actionResult.left().value();
4293     }
4294
4295     /**
4296      * deletes an artifact from a resource instance by UUID
4297      *
4298      * @param request
4299      * @param componentType
4300      * @param componentUuid
4301      * @param resourceInstanceName
4302      * @param artifactUUID
4303      * @param operation            TODO
4304      * @return
4305      */
4306     public ArtifactDefinition deleteArtifactOnRiByUUID(HttpServletRequest request, ComponentTypeEnum componentType,
4307                                                        String componentUuid, String resourceInstanceName,
4308                                                        String artifactUUID, ArtifactOperationInfo operation) {
4309
4310         Either<ArtifactDefinition, Operation> actionResult;
4311         Component component = null;
4312         String componentInstanceId;
4313         String componentId;
4314         String artifactId;
4315         String origMd5 = request.getHeader(Constants.MD5_HEADER);
4316         String userId = request.getHeader(Constants.USER_ID_HEADER);
4317         ImmutablePair<Component, ComponentInstance> componentRiPair = null;
4318         Either<ComponentMetadataData, ActionStatus> getComponentRes =
4319             fetchLatestComponentMetadataOrThrow(componentType, componentUuid);
4320         if (!getComponentRes.left()
4321                 .value()
4322                 .getMetadataDataDefinition()
4323                 .getState()
4324                 .equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
4325             component = checkoutParentComponent(componentType, getComponentRes.left()
4326                     .value()
4327                     .getMetadataDataDefinition()
4328                     .getUniqueId(), userId);
4329         }
4330         if (component == null) {
4331             componentRiPair = getRelatedComponentComponentInstance(componentType, componentUuid, resourceInstanceName);
4332         }
4333         else {
4334             componentRiPair = getRelatedComponentComponentInstance(component, resourceInstanceName);
4335         }
4336         componentInstanceId = componentRiPair.getRight().getUniqueId();
4337         componentId = componentRiPair.getLeft().getUniqueId();
4338         artifactId = findArtifactId(componentRiPair.getRight(), artifactUUID);
4339
4340         actionResult = handleArtifactRequest(componentInstanceId, userId, ComponentTypeEnum.RESOURCE_INSTANCE, operation, artifactId, null, origMd5, null, null, null, componentId, ComponentTypeEnum
4341                 .findParamByType(componentType));
4342         return actionResult.left().value();
4343     }
4344
4345     private String findArtifactId(ComponentInstance instance, String artifactUUID) {
4346         String artifactId = null;
4347         ArtifactDefinition foundArtifact = null;
4348         if (instance.getDeploymentArtifacts() != null) {
4349             foundArtifact = instance.getDeploymentArtifacts()
4350                     .values()
4351                     .stream()
4352                     .filter(e -> e.getArtifactUUID() != null && e.getArtifactUUID()
4353                             .equals(artifactUUID))
4354                     .findFirst()
4355                     .orElse(null);
4356         }
4357         if (foundArtifact == null && instance.getArtifacts() != null) {
4358             foundArtifact = instance.getArtifacts()
4359                     .values()
4360                     .stream()
4361                     .filter(e -> e.getArtifactUUID() != null && e.getArtifactUUID()
4362                             .equals(artifactUUID))
4363                     .findFirst()
4364                     .orElse(null);
4365         }
4366         if (foundArtifact == null) {
4367             log.debug("The artifact {} was not found on instance {}. ", artifactUUID, instance.getUniqueId());
4368             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactUUID);
4369         }
4370         else {
4371             artifactId = foundArtifact.getUniqueId();
4372         }
4373         return artifactId;
4374     }
4375
4376     @SuppressWarnings("unchecked")
4377     public ArtifactDefinition createHeatEnvPlaceHolder(List<ArtifactDefinition> createdArtifacts, ArtifactDefinition heatArtifact,
4378                                                        String envType, String parentId, NodeTypeEnum parentType,
4379                                                        String parentName, User user, Component component,
4380                                                        Map<String, String> existingEnvVersions) {
4381         Map<String, Object> deploymentResourceArtifacts = ConfigurationManager.getConfigurationManager()
4382                 .getConfiguration()
4383                 .getDeploymentResourceInstanceArtifacts();
4384         if (deploymentResourceArtifacts == null) {
4385             log.debug("no deployment artifacts are configured for generated artifacts");
4386             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
4387         }
4388         Map<String, Object> placeHolderData = (Map<String, Object>) deploymentResourceArtifacts.get(envType);
4389         if (placeHolderData == null) {
4390             log.debug("no env type {} are configured for generated artifacts", envType);
4391             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
4392         }
4393
4394         String envLabel = (heatArtifact.getArtifactLabel() + HEAT_ENV_SUFFIX).toLowerCase();
4395         ArtifactDefinition createArtifactPlaceHolder = createArtifactPlaceHolderInfo(parentId, envLabel, placeHolderData, user
4396                 .getUserId(), ArtifactGroupTypeEnum.DEPLOYMENT, true);
4397         ArtifactDefinition artifactHeatEnv = createArtifactPlaceHolder;
4398         artifactHeatEnv.setGeneratedFromId(heatArtifact.getUniqueId());
4399         artifactHeatEnv.setHeatParamsUpdateDate(System.currentTimeMillis());
4400         artifactHeatEnv.setTimeout(0);
4401         artifactHeatEnv.setIsFromCsar(heatArtifact.getIsFromCsar());
4402         buildHeatEnvFileName(heatArtifact, artifactHeatEnv, placeHolderData);
4403         // rbetzer - keep env artifactVersion - changeComponentInstanceVersion flow
4404         handleEnvArtifactVersion(artifactHeatEnv, existingEnvVersions);
4405         ArtifactDefinition heatEnvPlaceholder;
4406         // Evg : for resource instance artifact will be added later as block with other env artifacts from BL
4407         if (parentType != NodeTypeEnum.ResourceInstance) {
4408             String checkSum = artifactToscaOperation.sortAndCalculateChecksumForHeatParameters(heatArtifact.getHeatParameters());
4409             artifactHeatEnv.setArtifactChecksum(checkSum);
4410             Either<ArtifactDefinition, StorageOperationStatus> addHeatEnvArtifact = addHeatEnvArtifact(artifactHeatEnv, heatArtifact, component, parentType, parentId);
4411             if (addHeatEnvArtifact.isRight()) {
4412                 log.debug("failed to create heat env artifact on resource instance");
4413                 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormatForResourceInstance(componentsUtils.convertFromStorageResponseForResourceInstance(addHeatEnvArtifact
4414                         .right()
4415                         .value(), false), "", null));
4416             }
4417             heatEnvPlaceholder = createArtifactPlaceHolder;
4418         }
4419         else {
4420             heatEnvPlaceholder = artifactHeatEnv;
4421             artifactToscaOperation.generateUUID(heatEnvPlaceholder, heatEnvPlaceholder.getArtifactVersion());
4422             setHeatCurrentValuesOnHeatEnvDefaultValues(heatArtifact, heatEnvPlaceholder);
4423         }
4424         ComponentTypeEnum componentType = component.getComponentType();
4425         if (parentType == NodeTypeEnum.ResourceInstance) {
4426             componentType = ComponentTypeEnum.RESOURCE_INSTANCE;
4427         }
4428         createdArtifacts.add(heatEnvPlaceholder);
4429         componentsUtils.auditComponent(componentsUtils.getResponseFormat(ActionStatus.OK), user, component, AuditingActionEnum.ARTIFACT_UPLOAD,
4430                 new ResourceCommonInfo(parentName, componentType.getValue()),
4431                 ResourceVersionInfo.newBuilder().build(),
4432                 ResourceVersionInfo.newBuilder().artifactUuid(heatEnvPlaceholder.getUniqueId()).build(),
4433                 null, heatEnvPlaceholder, null);
4434         return heatEnvPlaceholder;
4435     }
4436
4437     private void setHeatCurrentValuesOnHeatEnvDefaultValues(ArtifactDefinition artifact, ArtifactDefinition artifactDefinition) {
4438         if (artifact.getListHeatParameters() == null) {
4439             return;
4440         }
4441         List<HeatParameterDefinition> heatEnvParameters = new ArrayList<>();
4442         for (HeatParameterDefinition parameter : artifact.getListHeatParameters()) {
4443             HeatParameterDefinition heatEnvParameter = new HeatParameterDefinition(parameter);
4444             heatEnvParameter.setDefaultValue(parameter.getCurrentValue());
4445             heatEnvParameter.setCurrentValue(null);
4446             heatEnvParameters.add(heatEnvParameter);
4447         }
4448         artifactDefinition.setListHeatParameters(heatEnvParameters);
4449     }
4450
4451     private void buildHeatEnvFileName(ArtifactDefinition heatArtifact, ArtifactDefinition heatEnvArtifact, Map<String, Object> placeHolderData) {
4452         String heatExtension = GeneralUtility.getFilenameExtension(heatArtifact.getArtifactName());
4453         String envExtension = (String) placeHolderData.get(ARTIFACT_PLACEHOLDER_FILE_EXTENSION);
4454         String name = heatArtifact.getArtifactName();
4455         String fileName;
4456         if (name == null) {
4457             name = heatArtifact.getArtifactLabel();
4458             fileName = name + "." + envExtension;
4459         }
4460         else {
4461             fileName = name.replaceAll("." + heatExtension, "." + envExtension);
4462         }
4463         heatEnvArtifact.setArtifactName(fileName);
4464     }
4465
4466     private void handleEnvArtifactVersion(ArtifactDefinition heatEnvArtifact, Map<String, String> existingEnvVersions) {
4467         if (null != existingEnvVersions) {
4468             String prevVersion = existingEnvVersions.get(heatEnvArtifact.getArtifactName());
4469             if (null != prevVersion) {
4470                 heatEnvArtifact.setArtifactVersion(prevVersion);
4471             }
4472         }
4473     }
4474
4475     public List<ArtifactDefinition> handleArtifactsForInnerVfcComponent(List<ArtifactDefinition> artifactsToHandle, Resource component, User user, List<ArtifactDefinition> vfcsNewCreatedArtifacts,
4476                                                                         ArtifactOperationInfo operation, boolean shouldLock, boolean inTransaction) {
4477         ComponentTypeEnum componentType = component.getComponentType();
4478         List<ArtifactDefinition> uploadedArtifacts = new ArrayList<>();
4479         Either<ArtifactDefinition, Operation> result;
4480         try {
4481             for (ArtifactDefinition artifactDefinition : artifactsToHandle) {
4482                 result = handleLoadedArtifact(component, user, operation, shouldLock, inTransaction, componentType, artifactDefinition);
4483                 uploadedArtifacts.add(result.left().value());
4484             }
4485         } catch (ComponentException e) {
4486             log.debug(FAILED_UPLOAD_ARTIFACT_TO_COMPONENT, componentType, component
4487                     .getName(), e.getResponseFormat());
4488             if (operation.isCreateOrLink()) {
4489                 vfcsNewCreatedArtifacts.addAll(uploadedArtifacts);
4490             }
4491             throw e;
4492         }
4493         return uploadedArtifacts;
4494     }
4495
4496     public Either<ArtifactDefinition, Operation> handleLoadedArtifact(Resource component, User user, ArtifactOperationInfo operation, boolean shouldLock, boolean inTransaction,
4497                                                                       ComponentTypeEnum componentType, ArtifactDefinition artifactDefinition) {
4498         AuditingActionEnum auditingAction = detectAuditingType(operation, "");
4499         String componentId = component.getUniqueId();
4500         String artifactId = artifactDefinition.getUniqueId();
4501         Either<ArtifactDefinition, Operation> result;
4502         Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
4503         //artifact validation
4504         artifactDefinition = validateArtifact(componentId, componentType, operation,
4505                 artifactId, artifactDefinition, auditingAction, user,
4506                 component, shouldLock, inTransaction);
4507         switch (operation.getArtifactOperationEnum()) {
4508             case CREATE:
4509                 byte[] validPayload = getValidPayload(componentId, artifactDefinition, operation, auditingAction, artifactId, user, componentType, component, null, null);
4510                 result = createArtifact(component, componentId, artifactDefinition, validPayload,
4511                         componentType, auditingAction, null, null);
4512                 break;
4513             case UPDATE:
4514                 validPayload = getValidPayload(componentId, artifactDefinition, operation, auditingAction, artifactId, user, componentType, component, null, null);
4515                 result = handleUpdate(componentId, componentType, operation, artifactId, artifactDefinition, validPayload, null, null, null, null,
4516                         auditingAction, user, component, true);
4517                 break;
4518             case DELETE:
4519                 result = Either.left(handleDeleteInternal(componentId, artifactId, componentType, component));
4520                 break;
4521             case DOWNLOAD:
4522                 if (artifactGenerationRequired(component, artifactDefinition)) {
4523                     result = Either.left(generateNotSavedArtifact(component, artifactDefinition));
4524                 } else {
4525                     result = Either.left(handleDownload(componentId, artifactId, componentType, component));
4526                 }
4527                 break;
4528             case LINK:
4529                 result = Either.left(handleLink(componentId, artifactDefinition, componentType, component));
4530                 break;
4531             default:
4532                 throw new UnsupportedOperationException("In ArtifactsBusinessLogic received illegal operation: " + operation.getArtifactOperationEnum());
4533         }
4534         return result;
4535     }
4536
4537     public List<ArtifactDefinition> handleArtifactsRequestForInnerVfcComponent(List<ArtifactDefinition> artifactsToHandle, Resource component, User user, List<ArtifactDefinition> vfcsNewCreatedArtifacts,
4538                                                                                ArtifactOperationInfo operation, boolean shouldLock, boolean inTransaction) {
4539
4540         List<ArtifactDefinition> handleArtifactsResult;
4541         ComponentTypeEnum componentType = component.getComponentType();
4542         List<ArtifactDefinition> uploadedArtifacts = new ArrayList<>();
4543         Either<ArtifactDefinition, Operation> actionResult;
4544         String originData;
4545         String origMd5;
4546         try {
4547             for (ArtifactDefinition artifact : artifactsToHandle) {
4548                 originData = ArtifactUtils.buildJsonStringForCsarVfcArtifact(artifact);
4549                 origMd5 = GeneralUtility.calculateMD5Base64EncodedByString(originData);
4550                 actionResult = handleArtifactRequest(component.getUniqueId(), user.getUserId(), componentType, operation, artifact
4551                         .getUniqueId(), artifact, origMd5, originData, null, null, null, null, shouldLock, inTransaction);
4552                 uploadedArtifacts.add(actionResult.left().value());
4553             }
4554             handleArtifactsResult = uploadedArtifacts;
4555         }catch (ComponentException e){
4556             if (operation.isCreateOrLink()) {
4557                 vfcsNewCreatedArtifacts.addAll(uploadedArtifacts);
4558             }
4559             throw e;
4560         }
4561         return handleArtifactsResult;
4562     }
4563
4564     private ComponentInstance getRelatedComponentInstance(
4565         ComponentTypeEnum componentType, String componentUuid, String resourceInstanceName
4566     ) {
4567         String normalizedName = ValidationUtils.normalizeComponentInstanceName(resourceInstanceName);
4568         Option<Component> oComponent = Option.of(getComponentByUuid(componentType, componentUuid));
4569         return oComponent
4570             .toTry(componentNotFound(componentType, componentUuid))
4571             .flatMap(component -> findFirstMatching(component,
4572                 ci -> ValidationUtils.normalizeComponentInstanceName(ci.getName()).equals(normalizedName)
4573             ).toTry(componentInstanceNotFound(componentType, resourceInstanceName, component))
4574         ).get();
4575     }
4576
4577     private ImmutablePair<Component, ComponentInstance> getRelatedComponentComponentInstance(
4578         Component component, String resourceInstanceName
4579     ) {
4580         String normalizedName = ValidationUtils.normalizeComponentInstanceName(resourceInstanceName);
4581         ComponentInstance componentInstance = findFirstMatching(component,
4582             ci -> ValidationUtils.normalizeComponentInstanceName(ci.getName()).equals(normalizedName)
4583         ).toTry(componentInstanceNotFound(component.getComponentType(), resourceInstanceName, component)).get();
4584         return new ImmutablePair<>(component, componentInstance);
4585     }
4586
4587     private ImmutablePair<Component, ComponentInstance> getRelatedComponentComponentInstance(
4588         ComponentTypeEnum componentType, String componentUuid, String resourceInstanceName
4589     ) {
4590         Component component = getLatestComponentByUuid(componentType, componentUuid);
4591         ComponentInstance componentInstance = findFirstMatching(component,
4592             ci -> ci.getNormalizedName().equals(resourceInstanceName)
4593         ).toTry(componentInstanceNotFound(component.getComponentType(), resourceInstanceName, component)).get();
4594         return new ImmutablePair<>(component, componentInstance);
4595     }
4596
4597     private Supplier<Throwable> componentNotFound(ComponentTypeEnum componentType, String componentUuid) {
4598         return () -> {
4599             log.debug(FAILED_FETCH_COMPONENT, componentType.getValue(), componentUuid);
4600             return new ByActionStatusComponentException(ActionStatus.COMPONENT_NOT_FOUND, componentUuid);
4601         };
4602     }
4603
4604     private Supplier<Throwable> componentInstanceNotFound(
4605         ComponentTypeEnum componentType, String resourceInstanceName, Component component
4606     ) {
4607         return () -> {
4608             log.debug(COMPONENT_INSTANCE_NOT_FOUND, resourceInstanceName, component.getName());
4609             return new ByActionStatusComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER,
4610                 resourceInstanceName,
4611                 RESOURCE_INSTANCE, componentType.getValue(), component.getName());
4612         };
4613     }
4614
4615     private static Option<ComponentInstance> findFirstMatching(Component component, Predicate<ComponentInstance> filter) {
4616         return Option.ofOptional(component.getComponentInstances()
4617             .stream()
4618             .filter(filter)
4619             .findFirst());
4620     }
4621
4622     private byte[] downloadArtifact(Map<String, ArtifactDefinition> artifacts, String artifactUUID, String componentName) {
4623
4624         ImmutablePair<String, byte[]> downloadArtifact;
4625         List<ArtifactDefinition> artifactsList = null;
4626         ArtifactDefinition deploymentArtifact;
4627         if (artifacts != null && !artifacts.isEmpty()) {
4628             artifactsList = artifacts.values()
4629                     .stream()
4630                     .filter(art -> art.getArtifactUUID() != null && art.getArtifactUUID()
4631                             .equals(artifactUUID))
4632                     .collect(Collectors.toList());
4633         }
4634         if (artifactsList == null || artifactsList.isEmpty()) {
4635             log.debug("Deployment artifact with uuid {} was not found for component {}", artifactUUID, componentName);
4636             throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND, artifactUUID);
4637         }
4638         deploymentArtifact = artifactsList.get(0);
4639         downloadArtifact = downloadArtifact(deploymentArtifact);
4640         log.trace("Succeeded to download artifact with uniqueId {}", deploymentArtifact.getUniqueId());
4641         return downloadArtifact.getRight();
4642     }
4643
4644     private Component getLatestComponentByUuid(ComponentTypeEnum componentType, String componentUuid) {
4645         Component component;
4646         Either<Component, StorageOperationStatus> getComponentRes = toscaOperationFacade.getLatestComponentByUuid(componentUuid);
4647         if (getComponentRes.isRight()) {
4648             StorageOperationStatus status = getComponentRes.right().value();
4649             log.debug(FAILED_FETCH_COMPONENT, componentType, componentUuid, status);
4650             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status));
4651         }
4652         else {
4653             component = getComponentRes.left().value();
4654         }
4655         return component;
4656     }
4657
4658     private Component getComponentByUuid(ComponentTypeEnum componentType, String componentUuid) {
4659         Component component;
4660         Either<List<Component>, StorageOperationStatus> getComponentRes = toscaOperationFacade.getComponentListByUuid(componentUuid, null);
4661         if (getComponentRes.isRight()) {
4662             StorageOperationStatus status = getComponentRes.right().value();
4663             log.debug(FAILED_FETCH_COMPONENT, componentType, componentUuid, status);
4664             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status));
4665         }
4666         else {
4667             List<Component> value = getComponentRes.left().value();
4668             if (value.isEmpty()) {
4669                 log.debug("Could not fetch component with type {} and uuid {}.", componentType, componentUuid);
4670                 ActionStatus status = componentType == ComponentTypeEnum.RESOURCE ? ActionStatus.RESOURCE_NOT_FOUND : ActionStatus.SERVICE_NOT_FOUND;
4671                 throw new ByActionStatusComponentException(status);
4672             }
4673             else {
4674                 component = value.get(0);
4675             }
4676         }
4677         return component;
4678     }
4679
4680     private String getLatestParentArtifactDataIdByArtifactUUID(String artifactUUID, String parentId, ComponentTypeEnum componentType) {
4681         ActionStatus actionStatus = ActionStatus.ARTIFACT_NOT_FOUND;
4682         StorageOperationStatus storageStatus;
4683         ArtifactDefinition latestArtifact;
4684         List<ArtifactDefinition> artifacts;
4685         Either<Map<String, ArtifactDefinition>, StorageOperationStatus> getArtifactsRes = artifactToscaOperation.getArtifacts(parentId);
4686         if (getArtifactsRes.isRight()) {
4687             storageStatus = getArtifactsRes.right().value();
4688             log.debug("Couldn't fetch artifacts data for parent component {} with uid {}, error: {}", componentType, parentId, storageStatus);
4689             if (storageStatus != StorageOperationStatus.NOT_FOUND) {
4690                 actionStatus = componentsUtils.convertFromStorageResponse(storageStatus);
4691             }
4692             throw new ByActionStatusComponentException(actionStatus, artifactUUID);
4693         }
4694         artifacts = getArtifactsRes.left()
4695                 .value()
4696                 .values()
4697                 .stream()
4698                 .filter(a -> a.getArtifactUUID() != null && a.getArtifactUUID()
4699                         .equals(artifactUUID))
4700                 .collect(Collectors.toList());
4701         if (artifacts == null || artifacts.isEmpty()) {
4702             log.debug("Couldn't fetch artifact with UUID {} data for parent component {} with uid {}, error: {}", artifactUUID, componentType, parentId, actionStatus);
4703             throw new ByActionStatusComponentException(actionStatus, artifactUUID);
4704         }
4705         latestArtifact = artifacts.stream().max((a1, a2) -> {
4706             int compareRes = Double.compare(Double.parseDouble(a1.getArtifactVersion()), Double.parseDouble(a2.getArtifactVersion()));
4707             if (compareRes == 0) {
4708                 compareRes = Long.compare(a1.getLastUpdateDate() == null ? 0 : a1.getLastUpdateDate(), a2.getLastUpdateDate() == null ? 0 : a2
4709                         .getLastUpdateDate());
4710             }
4711             return compareRes;
4712         }).get();
4713         if (latestArtifact == null) {
4714             log.debug("Couldn't fetch latest artifact with UUID {} data for parent component {} with uid {}, error: {}", artifactUUID, componentType, parentId, actionStatus);
4715             throw new ByActionStatusComponentException(actionStatus, artifactUUID);
4716         }
4717         return latestArtifact.getUniqueId();
4718     }
4719
4720     private Component checkoutParentComponent(ComponentTypeEnum componentType, String parentId, String userId) {
4721
4722         Component component = null;
4723         User modifier = userBusinessLogic.getUser(userId, false);
4724         LifecycleChangeInfoWithAction changeInfo = new LifecycleChangeInfoWithAction("External API checkout", LifecycleChanceActionEnum.UPDATE_FROM_EXTERNAL_API);
4725         Either<? extends Component, ResponseFormat> checkoutRes = lifecycleBusinessLogic.changeComponentState(componentType, parentId, modifier, LifeCycleTransitionEnum.CHECKOUT, changeInfo, false, true);
4726         if (checkoutRes.isRight()) {
4727             log.debug("Could not change state of component {} with uid {} to checked out. Status is {}. ", componentType
4728                     .getNodeType(), parentId, checkoutRes.right().value().getStatus());
4729             throw new ByResponseFormatComponentException(checkoutRes.right().value());
4730         }
4731         return checkoutRes.left().value();
4732     }
4733
4734     @Autowired
4735     void setNodeTemplateOperation(NodeTemplateOperation nodeTemplateOperation) {
4736         this.nodeTemplateOperation = nodeTemplateOperation;
4737     }
4738
4739     public List<ArtifactConfiguration> getConfiguration() {
4740         return ConfigurationManager.getConfigurationManager().getConfiguration().getArtifacts();
4741     }
4742 }