Revert "Interface operation feature enhancements"
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ServiceBusinessLogic.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  */
20
21 package org.openecomp.sdc.be.components.impl;
22
23 import com.google.common.annotations.VisibleForTesting;
24 import com.google.common.base.Strings;
25 import com.google.gson.Gson;
26 import com.google.gson.GsonBuilder;
27 import fj.data.Either;
28 import org.apache.commons.collections.MapUtils;
29 import org.apache.commons.lang3.StringUtils;
30 import org.apache.commons.lang3.tuple.ImmutablePair;
31 import org.openecomp.sdc.be.components.distribution.engine.IDistributionEngine;
32 import org.openecomp.sdc.be.components.distribution.engine.INotificationData;
33 import org.openecomp.sdc.be.components.distribution.engine.VfModuleArtifactPayload;
34 import org.openecomp.sdc.be.components.health.HealthCheckBusinessLogic;
35 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
36 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
37 import org.openecomp.sdc.be.components.path.ForwardingPathValidator;
38 import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation;
39 import org.openecomp.sdc.be.config.BeEcompErrorManager;
40 import org.openecomp.sdc.be.config.ConfigurationManager;
41 import org.openecomp.sdc.be.dao.api.ActionStatus;
42 import org.openecomp.sdc.be.dao.cassandra.AuditCassandraDao;
43 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
44 import org.openecomp.sdc.be.datamodel.ServiceRelations;
45 import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter;
46 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
47 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
48 import org.openecomp.sdc.be.datatypes.enums.InstantiationTypes;
49 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
50 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
51 import org.openecomp.sdc.be.externalapi.servlet.representation.ServiceDistributionReqInfo;
52 import org.openecomp.sdc.be.impl.ForwardingPathUtils;
53 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
54 import org.openecomp.sdc.be.model.*;
55 import org.openecomp.sdc.be.model.category.CategoryDefinition;
56 import org.openecomp.sdc.be.model.jsontitan.operations.ForwardingPathOperation;
57 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
58 import org.openecomp.sdc.be.model.operations.api.ICacheMangerOperation;
59 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
60 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
61 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
62 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
63 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
64 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
65 import org.openecomp.sdc.be.resources.data.auditing.*;
66 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo;
67 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo;
68 import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
69 import org.openecomp.sdc.be.user.Role;
70 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
71 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
72 import org.openecomp.sdc.common.api.Constants;
73 import org.openecomp.sdc.common.datastructure.Wrapper;
74 import org.openecomp.sdc.common.kpi.api.ASDCKpiApi;
75 import org.openecomp.sdc.common.log.wrappers.Logger;
76 import org.openecomp.sdc.common.util.GeneralUtility;
77 import org.openecomp.sdc.common.util.ThreadLocalsHolder;
78 import org.openecomp.sdc.common.util.ValidationUtils;
79 import org.openecomp.sdc.exception.ResponseFormat;
80 import org.springframework.beans.factory.annotation.Autowired;
81 import org.springframework.web.context.WebApplicationContext;
82
83 import javax.servlet.ServletContext;
84 import javax.servlet.http.HttpServletRequest;
85 import java.nio.charset.StandardCharsets;
86 import java.util.*;
87 import java.util.concurrent.Callable;
88 import java.util.function.Function;
89 import java.util.stream.Collectors;
90
91 import static org.apache.commons.collections.CollectionUtils.isEmpty;
92 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
93 import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.UPDATE_SERVICE_METADATA;
94
95 @org.springframework.stereotype.Component("serviceBusinessLogic")
96 public class ServiceBusinessLogic extends ComponentBusinessLogic {
97
98     private static final String CHANGE_SERVICE_DISTRIBUTION = "Change Service Distribution";
99         private static final String THE_SERVICE_WITH_SYSTEM_NAME_LOCKED = "The service with system name {} locked. ";
100         private static final String FAILED_TO_LOCK_SERVICE_RESPONSE_IS = "Failed to lock service {}. Response is {}. ";
101         private static final String AUDIT_BEFORE_SENDING_RESPONSE = "audit before sending response";
102         private static final Logger log = Logger.getLogger(ServiceBusinessLogic.class);
103     private static final String INITIAL_VERSION = "0.1";
104     private static final String STATUS_SUCCESS_200 = "200";
105         private static final String STATUS_DEPLOYED = "DEPLOYED";
106     @Autowired
107     private IDistributionEngine distributionEngine;
108     @Autowired
109     private AuditCassandraDao auditCassandraDao;
110     @Autowired
111     private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
112     @Autowired
113     private ICacheMangerOperation cacheManagerOperation;
114     @Autowired
115     private ServiceDistributionValidation serviceDistributionValidation;
116
117     @Autowired
118     private ForwardingPathOperation forwardingPathOperation;
119     @Autowired
120     private ForwardingPathValidator forwardingPathValidator;
121     @Autowired
122     private UiComponentDataConverter uiComponentDataConverter;
123
124     public Either<Service, ResponseFormat> changeServiceDistributionState(String serviceId, String state, LifecycleChangeInfoWithAction commentObj, User user) {
125
126         validateUserExists(user.getUserId(), "change Service Distribution State", false);
127
128         log.debug("check request state");
129         Either<DistributionTransitionEnum, ResponseFormat> validateEnum = validateTransitionEnum(state);
130         if (validateEnum.isRight()) {
131             return Either.right(validateEnum.right().value());
132         }
133         DistributionTransitionEnum distributionTransition = validateEnum.left().value();
134         AuditingActionEnum auditAction = distributionTransition == DistributionTransitionEnum.APPROVE ? AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_APPROV : AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_REJECT;
135         Either<String, ResponseFormat> commentResponse = validateComment(commentObj);
136         if (commentResponse.isRight()) {
137             return Either.right(commentResponse.right().value());
138         }
139         String comment = commentResponse.left().value();
140
141         Either<Service, ResponseFormat> validateService = validateServiceDistributionChange(user, serviceId, auditAction, comment);
142         if (validateService.isRight()) {
143             return Either.right(validateService.right().value());
144         }
145         Service service = validateService.left().value();
146         Either<User, ResponseFormat> validateUser = validateUserDistributionChange(user, service, auditAction, comment);
147         if (validateUser.isRight()) {
148             return Either.right(validateUser.right().value());
149         }
150         user = validateUser.left().value();
151
152         // lock resource
153
154         Either<Boolean, ResponseFormat> lockResult = lockComponent(serviceId, service, "ChangeServiceDistributionState");
155         if (lockResult.isRight()) {
156             ResponseFormat responseFormat = lockResult.right().value();
157             createAudit(user, auditAction, comment, service, responseFormat);
158             return Either.right(responseFormat);
159         }
160
161         try {
162
163             DistributionStatusEnum newState;
164             if (distributionTransition == DistributionTransitionEnum.APPROVE) {
165                 newState = DistributionStatusEnum.DISTRIBUTION_APPROVED;
166             } else {
167                 newState = DistributionStatusEnum.DISTRIBUTION_REJECTED;
168             }
169             Either<Service, StorageOperationStatus> result = toscaOperationFacade.updateDistributionStatus(service, user, newState);
170             if (result.isRight()) {
171                 titanDao.rollback();
172                 BeEcompErrorManager.getInstance().logBeSystemError("ChangeServiceDistributionState");
173                 log.debug("service {} is  change destribuation status failed", service.getUniqueId());
174                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR, service.getVersion(), service.getName());
175                 createAudit(user, auditAction, comment, service, responseFormat);
176                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
177             }
178             titanDao.commit();
179             Service updatedService = result.left().value();
180             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
181             log.debug(AUDIT_BEFORE_SENDING_RESPONSE);
182             componentsUtils.auditComponent(responseFormat, user, updatedService, auditAction, new ResourceCommonInfo(ComponentTypeEnum.SERVICE.getValue()), ResourceVersionInfo.newBuilder().build(), comment);
183             return Either.left(result.left().value());
184         } finally {
185             graphLockOperation.unlockComponent(serviceId, NodeTypeEnum.Service);
186         }
187
188     }
189
190     public Either<List<Map<String, Object>>, ResponseFormat> getComponentAuditRecords(String componentVersion, String componentUUID, String userId) {
191         validateUserExists(userId, "get Component Audit Records", false);
192         Either<List<Map<String, Object>>, ActionStatus> result;
193         try {
194
195             // Certified Version
196             if (componentVersion.endsWith(".0")) {
197                 Either<List<ResourceAdminEvent>, ActionStatus> eitherAuditingForCertified = auditCassandraDao.getByServiceInstanceId(componentUUID);
198                 if (eitherAuditingForCertified.isLeft()) {
199                     result = Either.left(getAuditingFieldsList(eitherAuditingForCertified.left().value()));
200                 } else {
201                     result = Either.right(eitherAuditingForCertified.right().value());
202                 }
203             }
204             // Uncertified Version
205             else {
206                 result = getAuditRecordsForUncertifiedComponent(componentUUID, componentVersion);
207             }
208         } catch (Exception e) {
209             log.debug("get Audit Records failed with exception {}", e);
210             result = Either.right(ActionStatus.GENERAL_ERROR);
211         }
212
213         if (result.isRight()) {
214             return Either.right(componentsUtils.getResponseFormat(result.right().value()));
215         } else {
216             return Either.left(result.left().value());
217         }
218
219     }
220
221     private Either<List<Map<String, Object>>, ActionStatus> getAuditRecordsForUncertifiedComponent(String componentUUID, String componentVersion) {
222         // First Query
223         Either<List<ResourceAdminEvent>, ActionStatus> eitherprevVerAudit = auditCassandraDao.getAuditByServiceIdAndPrevVersion(componentUUID, componentVersion);
224
225         if (eitherprevVerAudit.isRight()) {
226             return Either.right(eitherprevVerAudit.right().value());
227         }
228
229         // Second Query
230         Either<List<ResourceAdminEvent>, ActionStatus> eitherCurrVerAudit = auditCassandraDao.getAuditByServiceIdAndCurrVersion(componentUUID, componentVersion);
231         if (eitherCurrVerAudit.isRight()) {
232             return Either.right(eitherCurrVerAudit.right().value());
233         }
234
235
236         Either<List<ResourceAdminEvent>, ActionStatus> eitherArchiveRestoreList = getArchiveRestoreEventList(componentUUID);
237         if (eitherArchiveRestoreList.isRight()) {
238             return Either.right(eitherArchiveRestoreList.right().value());
239         }
240
241         List<Map<String, Object>> prevVerAuditList = getAuditingFieldsList(eitherprevVerAudit.left().value());
242         List<Map<String, Object>> currVerAuditList = getAuditingFieldsList(eitherCurrVerAudit.left().value());
243
244         List<Map<String, Object>> duplicateElements = new ArrayList<>();
245         duplicateElements.addAll(prevVerAuditList);
246         duplicateElements.retainAll(currVerAuditList);
247
248         List<Map<String, Object>> joinedNonDuplicatedList = new ArrayList<>();
249         joinedNonDuplicatedList.addAll(prevVerAuditList);
250         joinedNonDuplicatedList.removeAll(duplicateElements);
251         joinedNonDuplicatedList.addAll(currVerAuditList);
252         joinedNonDuplicatedList.addAll(getAuditingFieldsList(eitherArchiveRestoreList.left().value()));
253
254
255         return Either.left(joinedNonDuplicatedList);
256     }
257
258     private Either<List<ResourceAdminEvent>, ActionStatus> getArchiveRestoreEventList(String componentUUID) {
259         // Archive Query
260         Either<List<ResourceAdminEvent>, ActionStatus> eitherArchiveAudit = auditCassandraDao.getArchiveAuditByServiceInstanceId(componentUUID);
261         if (eitherArchiveAudit.isRight()) {
262             return Either.right(eitherArchiveAudit.right().value());
263         }
264
265         // Restore Query
266         Either<List<ResourceAdminEvent>, ActionStatus> eitherRestoreAudit = auditCassandraDao.getRestoreAuditByServiceInstanceId(componentUUID);
267         if (eitherRestoreAudit.isRight()) {
268             return Either.right(eitherRestoreAudit.right().value());
269         }
270
271         List<ResourceAdminEvent> archiveAudit = new ArrayList<>();
272         archiveAudit.addAll(eitherArchiveAudit.left().value());
273         archiveAudit.addAll(eitherRestoreAudit.left().value());
274
275         return Either.left(archiveAudit);
276     }
277
278     private List<Map<String, Object>> getAuditingFieldsList(List<? extends AuditingGenericEvent> prevVerAuditList) {
279
280         List<Map<String, Object>> prevVerAudit = new ArrayList<>();
281         for (AuditingGenericEvent auditEvent : prevVerAuditList) {
282             auditEvent.fillFields();
283             prevVerAudit.add(auditEvent.getFields());
284         }
285         return prevVerAudit;
286     }
287
288     /**
289      * createService
290      *
291      * @param service
292      *            - Service
293      * @param user
294      *            - modifier data (userId)
295      * @return Either<Service, responseFormat>
296      */
297     public Either<Service, ResponseFormat> createService(Service service, User user) {
298
299         // get user details
300         user = validateUser(user, "Create Service", service, AuditingActionEnum.CREATE_RESOURCE, false);
301         // validate user role
302         validateUserRole(user, service, new ArrayList<>(), AuditingActionEnum.CREATE_RESOURCE, null);
303         service.setCreatorUserId(user.getUserId());
304         // warn on overridden fields
305         checkFieldsForOverideAttampt(service);
306         // enrich object
307         log.debug("enrich service with version and state");
308         service.setState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
309         service.setVersion(INITIAL_VERSION);
310         service.setConformanceLevel(ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel());
311         service.setDistributionStatus(DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED);
312
313         Either<Service, ResponseFormat> createServiceResponse = validateServiceBeforeCreate(service, user, AuditingActionEnum.CREATE_RESOURCE);
314         if (createServiceResponse.isRight()) {
315             return createServiceResponse;
316         }
317         return createServiceByDao(service, AuditingActionEnum.CREATE_RESOURCE, user);
318     }
319
320     private void checkFieldsForOverideAttampt(Service service) {
321         checkComponentFieldsForOverrideAttempt(service);
322         if (service.getDistributionStatus() != null) {
323             log.info("Distribution Status cannot be defined by user. This field will be overridden by the application");
324         }
325     }
326
327     private Either<Service, ResponseFormat> createServiceByDao(Service service, AuditingActionEnum actionEnum, User user) {
328         log.debug("send service {} to dao for create", service.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
329
330         Either<Boolean, ResponseFormat> lockResult = lockComponentByName(service.getSystemName(), service, "Create Service");
331         if (lockResult.isRight()) {
332             ResponseFormat responseFormat = lockResult.right().value();
333             componentsUtils.auditComponentAdmin(responseFormat, user, service, actionEnum, ComponentTypeEnum.SERVICE);
334             return Either.right(responseFormat);
335         }
336
337         log.debug("System name locked is {}, status = {}", service.getSystemName(), lockResult);
338
339         try {
340
341             createMandatoryArtifactsData(service, user);
342             createServiceApiArtifactsData(service, user);
343             setToscaArtifactsPlaceHolders(service, user);
344             generateAndAddInputsFromGenericTypeProperties(service, fetchAndSetDerivedFromGenericType(service));
345
346             Either<Service, StorageOperationStatus> dataModelResponse = toscaOperationFacade.createToscaComponent(service);
347
348             // service created successfully!!!
349             if (dataModelResponse.isLeft()) {
350                 log.debug("Service created successfully!!!");
351                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
352                 componentsUtils.auditComponentAdmin(responseFormat, user, service, actionEnum, ComponentTypeEnum.SERVICE);
353                 ASDCKpiApi.countCreatedServicesKPI();
354                 return Either.left(dataModelResponse.left().value());
355             }
356
357             ResponseFormat responseFormat = componentsUtils.getResponseFormatByComponent(componentsUtils.convertFromStorageResponse(dataModelResponse.right().value()), service, ComponentTypeEnum.SERVICE);
358             log.debug(AUDIT_BEFORE_SENDING_RESPONSE);
359             componentsUtils.auditComponentAdmin(responseFormat, user, service, actionEnum, ComponentTypeEnum.SERVICE);
360             return Either.right(responseFormat);
361
362         } finally {
363             graphLockOperation.unlockComponentByName(service.getSystemName(), service.getUniqueId(), NodeTypeEnum.Service);
364         }
365     }
366
367     @SuppressWarnings("unchecked")
368     private void createServiceApiArtifactsData(Service service, User user) {
369         // create mandatory artifacts
370
371         // TODO it must be removed after that artifact uniqueId creation will be
372         // moved to ArtifactOperation
373         String serviceUniqueId = service.getUniqueId();
374         Map<String, ArtifactDefinition> artifactMap = service.getServiceApiArtifacts();
375         if (artifactMap == null)
376             artifactMap = new HashMap<>();
377
378         Map<String, Object> serviceApiArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration().getServiceApiArtifacts();
379         List<String> exludeServiceCategory = ConfigurationManager.getConfigurationManager().getConfiguration().getExcludeServiceCategory();
380
381         List<CategoryDefinition> categories = service.getCategories();
382         boolean isCreateArtifact = true;
383         if (categories != null && exludeServiceCategory != null && !exludeServiceCategory.isEmpty()) {
384             for (String exlude : exludeServiceCategory) {
385                 if (exlude.equalsIgnoreCase(categories.get(0).getName())) {
386                     isCreateArtifact = false;
387                     break;
388                 }
389             }
390
391         }
392
393         if (serviceApiArtifacts != null && isCreateArtifact) {
394             Set<String> keys = serviceApiArtifacts.keySet();
395             for (String serviceApiArtifactName : keys) {
396                 Map<String, Object> artifactInfoMap = (Map<String, Object>) serviceApiArtifacts.get(serviceApiArtifactName);
397                 ArtifactDefinition artifactDefinition = createArtifactDefinition(serviceUniqueId, serviceApiArtifactName, artifactInfoMap, user, true);
398                 artifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.SERVICE_API);
399                 artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition);
400             }
401
402             service.setServiceApiArtifacts(artifactMap);
403         }
404     }
405
406     private Either<Service, ResponseFormat> validateServiceBeforeCreate(Service service, User user, AuditingActionEnum actionEnum) {
407
408         Either<Boolean, ResponseFormat> validationResponse = validateServiceFieldsBeforeCreate(user, service, actionEnum);
409         if (validationResponse.isRight()) {
410             return Either.right(validationResponse.right().value());
411         }
412         service.setCreatorFullName(user.getFirstName() + " " + user.getLastName());
413         service.setContactId(service.getContactId().toLowerCase());
414
415         // Generate invariant UUID - must be here and not in operation since it
416         // should stay constant during clone
417         String invariantUUID = UniqueIdBuilder.buildInvariantUUID();
418         service.setInvariantUUID(invariantUUID);
419
420         return Either.left(service);
421     }    
422     
423     
424    
425     private Either<Boolean, ResponseFormat> validateServiceFieldsBeforeCreate(User user, Service service, AuditingActionEnum actionEnum) {
426         try {
427             validateComponentFieldsBeforeCreate(user, service, actionEnum);
428
429             Either<Boolean, ResponseFormat> serviceNameUniquenessValidation = validateComponentNameUnique(user, service, actionEnum);
430             if (serviceNameUniquenessValidation.isRight()) {
431                 throw new ComponentException(serviceNameUniquenessValidation.right().value());
432             }
433             Either<Boolean, ResponseFormat> categoryValidation = validateServiceCategory(user, service, actionEnum);
434             if (categoryValidation.isRight()) {
435                 return categoryValidation;
436             }
437             Either<Boolean, ResponseFormat> projectCodeValidation = validateProjectCode(user, service, actionEnum);
438             if (projectCodeValidation.isRight()) {
439                 return projectCodeValidation;
440             }
441             validateServiceTypeAndCleanup(service);
442
443             Either<Boolean, ResponseFormat> serviceRoleValidation = validateServiceRoleAndCleanup(user, service, actionEnum);
444             if (serviceRoleValidation.isRight()) {
445                 return serviceRoleValidation;
446             }
447             return validateInstantiationTypeValue(user, service, actionEnum);
448         } catch (ComponentException exception) {
449             ResponseFormat responseFormat = componentsUtils.getResponseFormat(exception);
450             componentsUtils.auditComponentAdmin(responseFormat, user, service,
451                     AuditingActionEnum.CREATE_SERVICE, ComponentTypeEnum.SERVICE);
452             return Either.right(responseFormat);
453         }
454     }
455
456     private Either<Boolean, ResponseFormat> validateServiceCategory(User user, Service service, AuditingActionEnum actionEnum) {
457         log.debug("validate Service category");
458         if (isEmpty(service.getCategories())) {
459             ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_CATEGORY, ComponentTypeEnum.SERVICE.getValue());
460             componentsUtils.auditComponentAdmin(errorResponse, user, service, actionEnum, ComponentTypeEnum.SERVICE);
461             return Either.right(errorResponse);
462         }
463         Either<Boolean, ResponseFormat> validatCategory = validateServiceCategory(service.getCategories());
464         if (validatCategory.isRight()) {
465             ResponseFormat responseFormat = validatCategory.right().value();
466             componentsUtils.auditComponentAdmin(responseFormat, user, service, actionEnum, ComponentTypeEnum.SERVICE);
467             return Either.right(responseFormat);
468         }
469         return Either.left(true);
470     }
471
472     public Either<Map<String, Boolean>, ResponseFormat> validateServiceNameExists(String serviceName, String userId) {
473         validateUserExists(userId, "validate Service Name Exists", false);
474
475         Either<Boolean, StorageOperationStatus> dataModelResponse = toscaOperationFacade.validateComponentNameUniqueness(serviceName, null, ComponentTypeEnum.SERVICE);
476         // DE242223
477         titanDao.commit();
478
479         if (dataModelResponse.isLeft()) {
480             Map<String, Boolean> result = new HashMap<>();
481             result.put("isValid", dataModelResponse.left().value());
482             log.debug("validation was successfully performed.");
483             return Either.left(result);
484         }
485         ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(dataModelResponse.right().value()));
486         return Either.right(responseFormat);
487     }
488
489     public void setElementDao(IElementOperation elementDao) {
490         this.elementDao = elementDao;
491     }
492
493     public void setCassandraAuditingDao(AuditCassandraDao auditingDao) {
494         this.auditCassandraDao = auditingDao;
495     }
496
497     public ArtifactsBusinessLogic getArtifactBl() {
498         return artifactsBusinessLogic;
499     }
500
501     public void setArtifactBl(ArtifactsBusinessLogic artifactBl) {
502         this.artifactsBusinessLogic = artifactBl;
503     }
504
505     public Either<Service, ResponseFormat> updateServiceMetadata(String serviceId, Service serviceUpdate, User user) {
506         user = validateUser(user, "updateServiceMetadata", serviceUpdate, null, false);
507         // validate user role
508         validateUserRole(user, serviceUpdate, new ArrayList<>(), null, null);
509
510         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaElement(serviceId);
511         if (storageStatus.isRight()) {
512             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), ""));
513         }
514
515         Service currentService = storageStatus.left().value();
516
517         if (!ComponentValidationUtils.canWorkOnComponent(currentService, user.getUserId())) {
518             log.info("Restricted operation for user: {}, on service: {}", user.getUserId(), currentService.getCreatorUserId());
519             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
520         }
521         Either<Boolean, ResponseFormat> validateAndUpdateInterfacesEither = interfaceOperationBusinessLogic.validateComponentNameAndUpdateInterfaces(currentService, serviceUpdate);
522         if (validateAndUpdateInterfacesEither.isRight()) {
523             log.info("failed to validate and update Interfaces on service {}", currentService.getCreatorUserId());
524             return Either.right(validateAndUpdateInterfacesEither.right().value());
525         }
526         Either<Service, ResponseFormat> validationRsponse = validateAndUpdateServiceMetadata(user, currentService, serviceUpdate);
527         if (validationRsponse.isRight()) {
528             log.info("service update metadata: validations field.");
529             return validationRsponse;
530         }
531         Service serviceToUpdate = validationRsponse.left().value();
532         // lock resource
533
534         Either<Boolean, ResponseFormat> lockResult = lockComponent(serviceId, currentService, "Update Service Metadata");
535         if (lockResult.isRight()) {
536             return Either.right(lockResult.right().value());
537         }
538         try {
539             Either<Service, StorageOperationStatus> updateResponse = toscaOperationFacade.updateToscaElement(serviceToUpdate);
540             if (updateResponse.isRight()) {
541                 titanDao.rollback();
542                 BeEcompErrorManager.getInstance().logBeSystemError("Update Service Metadata");
543                 log.debug("failed to update sevice {}", serviceToUpdate.getUniqueId());
544                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
545             }
546             titanDao.commit();
547             return Either.left(updateResponse.left().value());
548         } finally {
549             graphLockOperation.unlockComponent(serviceId, NodeTypeEnum.Service);
550         }
551     }
552
553     public Either<Set<String>, ResponseFormat> deleteForwardingPaths(String serviceId, Set<String> pathIdsToDelete, User user, boolean lock) {
554         Service serviceToDelete = initServiceToDeletePaths(serviceId, pathIdsToDelete);
555         user = validateUser(user, "deleteForwardingPaths", serviceToDelete, null, false);
556         // validate user role
557         validateUserRole(user, serviceToDelete, new ArrayList<>(), null, null);
558         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaElement(serviceId);
559         if (storageStatus.isRight()) {
560             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), ""));
561         }
562         Service service = storageStatus.left().value();
563         Either<Set<String>, StorageOperationStatus> result = null;
564         if (lock) {
565             Either<Boolean, ResponseFormat> lockResult = lockComponent(service.getUniqueId(), service, "Delete Forwarding Path on Service");
566             if (lockResult.isRight()) {
567                 titanDao.rollback();
568                 return Either.right(componentsUtils.getResponseFormat(componentsUtils
569                     .convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), ""));
570             }
571         }
572         try{
573             result = forwardingPathOperation.deleteForwardingPath(service ,pathIdsToDelete);
574             if (result.isRight()) {
575                 log.debug(FAILED_TO_LOCK_SERVICE_RESPONSE_IS, service.getName(), result.right().value());
576                 titanDao.rollback();
577                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE)));
578             }
579             titanDao.commit();
580             log.debug(THE_SERVICE_WITH_SYSTEM_NAME_LOCKED, service.getSystemName());
581
582         } catch (Exception e){
583             log.error("Exception occurred during delete forwarding path : {}", e.getMessage(), e);
584             titanDao.rollback();
585             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
586         } finally {
587               graphLockOperation.unlockComponent(service.getUniqueId(), NodeTypeEnum.Service);
588         }
589         return Either.left(result.left().value());
590     }
591
592     private Service initServiceToDeletePaths(String serviceId, Collection<String> pathIdsToDelete) {
593         Service serviceToDelete = new Service();
594         serviceToDelete.setUniqueId(serviceId);
595         serviceToDelete.setForwardingPaths(new HashMap<>());
596         pathIdsToDelete.forEach(pathIdToDelete ->  serviceToDelete.getForwardingPaths().put(pathIdToDelete, new ForwardingPathDataDefinition()));
597         return serviceToDelete;
598     }
599
600     public Either<Service, ResponseFormat> updateForwardingPath(String serviceId, Service serviceUpdate, User user, boolean lock) {
601         return createOrUpdateForwardingPath(serviceId, serviceUpdate, user, true,"updateForwardingPath", lock);
602     }
603
604     public Either<Service, ResponseFormat> createForwardingPath(String serviceId, Service serviceUpdate, User user, boolean lock) {
605         return createOrUpdateForwardingPath(serviceId, serviceUpdate, user, false, "createForwardingPath", lock);
606     }
607
608     private ForwardingPathDataDefinition  getTrimmedValues(ForwardingPathDataDefinition path){
609         ForwardingPathDataDefinition dataDefinition = new ForwardingPathDataDefinition(path.getName());
610         dataDefinition.setName(Strings.nullToEmpty(path.getName()).trim());
611         dataDefinition.setProtocol(Strings.nullToEmpty(path.getProtocol()).trim());
612         dataDefinition.setDestinationPortNumber(Strings.nullToEmpty(path.getDestinationPortNumber()).trim());
613         dataDefinition.setUniqueId(path.getUniqueId());
614         dataDefinition.setPathElements(path.getPathElements());
615         dataDefinition.setDescription(path.getDescription());
616         dataDefinition.setToscaResourceName(path.getToscaResourceName());
617         return  dataDefinition;
618     }
619
620     private Either<Service, ResponseFormat> createOrUpdateForwardingPath(String serviceId, Service serviceUpdate, User user, boolean isUpdate, String errorContext, boolean lock) {
621         validateUserAndRole(serviceUpdate, user, errorContext);
622
623         Map<String, ForwardingPathDataDefinition> forwardingPaths = serviceUpdate.getForwardingPaths();
624
625         Map<String, ForwardingPathDataDefinition> trimmedForwardingPaths =
626                 forwardingPaths.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
627                         entry -> new ForwardingPathDataDefinition(getTrimmedValues(entry.getValue()))));
628
629         Either<Boolean, ResponseFormat> booleanResponseFormatEither = forwardingPathValidator.validateForwardingPaths(trimmedForwardingPaths.values(),
630                 serviceId, isUpdate);
631         if(booleanResponseFormatEither.isRight()){
632             return Either.right(booleanResponseFormatEither.right().value());
633         }
634
635         Either<Service, StorageOperationStatus> serviceStorageOperationStatusEither = toscaOperationFacade.getToscaElement(serviceId);
636
637         if(serviceStorageOperationStatusEither.isRight()){
638             StorageOperationStatus errorStatus = serviceStorageOperationStatusEither.right().value();
639             log.debug("Failed to fetch service information by service id, error {}", errorStatus);
640             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
641         }
642         Service storedService = serviceStorageOperationStatusEither.left().value();
643
644         Either<ForwardingPathDataDefinition, StorageOperationStatus> result;
645         Either<Component, StorageOperationStatus> forwardingPathOrigin = toscaOperationFacade.getLatestByName(ForwardingPathUtils.FORWARDING_PATH_NODE_NAME);
646         if (forwardingPathOrigin.isRight()) {
647             StorageOperationStatus errorStatus = forwardingPathOrigin.right().value();
648             log.debug("Failed to fetch normative forwarding path resource by tosca name, error {}", errorStatus);
649             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
650         }
651         Component component = forwardingPathOrigin.left().value();
652         final String toscaResourceName;
653         if (  component.getComponentType() == ComponentTypeEnum.RESOURCE) {
654             toscaResourceName = ((Resource) component).getToscaResourceName();
655         } else {
656             toscaResourceName = "";
657         }
658         Either<Boolean, ResponseFormat> lockResult = null;
659         if (lock) {
660             lockResult =
661                 lockComponent(storedService.getUniqueId(), storedService, "Add or Update Forwarding Path on Service");
662             if (lockResult.isRight()) {
663                 log.debug(FAILED_TO_LOCK_SERVICE_RESPONSE_IS, storedService.getName(),
664                     lockResult.right().value().getFormattedMessage());
665                 return Either.right(lockResult.right().value());
666             } else {
667                 log.debug(THE_SERVICE_WITH_SYSTEM_NAME_LOCKED, storedService.getSystemName());
668             }
669         }
670         Map<String, ForwardingPathDataDefinition> resultMap = new HashMap<>();
671         try {
672             trimmedForwardingPaths.values().forEach(fp -> fp.setToscaResourceName(toscaResourceName));
673
674             try {
675                 for (ForwardingPathDataDefinition forwardingPathDataDefinition : trimmedForwardingPaths.values()) {
676                     if (isUpdate) {
677                         result = forwardingPathOperation.updateForwardingPath(serviceId, forwardingPathDataDefinition);
678                     } else {
679                         result = forwardingPathOperation.addForwardingPath(serviceId, forwardingPathDataDefinition);
680                     }
681                     if (result.isRight()) {
682                         titanDao.rollback();
683                         return Either.right(componentsUtils.getResponseFormat(
684                             componentsUtils.convertFromStorageResponse(result.right().value(), ComponentTypeEnum.SERVICE),
685                             ""));
686                     } else {
687                         ForwardingPathDataDefinition fpDataDefinition = result.left().value();
688                         resultMap.put(fpDataDefinition.getUniqueId(), forwardingPathDataDefinition);
689                     }
690                 }
691
692             } catch (Exception e) {
693                 titanDao.rollback();
694                 log.error("Exception occurred during add or update forwarding path property values: {}", e.getMessage(),
695                     e);
696                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
697             }
698             titanDao.commit();
699         } finally {
700             if (lockResult != null && lockResult.isLeft() && lockResult.left().value()) {
701                 graphLockOperation.unlockComponent(storedService.getUniqueId(), NodeTypeEnum.Service);
702             }
703         }
704         Service service = createServiceWithForwardingPathForResponse(serviceId, resultMap);
705         return Either.left(service);
706     }
707
708     private Service createServiceWithForwardingPathForResponse(String serviceId, Map<String,ForwardingPathDataDefinition> forwardingPathDataDefinitionMap) {
709         Service service = new Service();
710         service.setUniqueId(serviceId);
711         service.setForwardingPaths(forwardingPathDataDefinitionMap);
712         return service;
713     }
714
715     private void validateUserAndRole(Service serviceUpdate, User user, String errorContext) {
716         user = validateUser(user, errorContext, serviceUpdate, null, false);
717         validateUserRole(user, serviceUpdate, new ArrayList<>(), null, null);
718
719     }
720
721     @VisibleForTesting
722     Either<Service, ResponseFormat> validateAndUpdateServiceMetadata(User user, Service currentService, Service serviceUpdate) {
723
724         try {
725             boolean hasBeenCertified = ValidationUtils.hasBeenCertified(currentService.getVersion());
726             Either<Boolean, ResponseFormat> response = validateAndUpdateCategory(user, currentService, serviceUpdate, hasBeenCertified, UPDATE_SERVICE_METADATA);
727             if (response.isRight()) {
728                 ResponseFormat errorResponse = response.right().value();
729                 return Either.right(errorResponse);
730             }
731
732             verifyValuesAreIdentical(serviceUpdate.getCreatorUserId(), currentService.getCreatorUserId(), "creatorUserId");
733             verifyValuesAreIdentical(serviceUpdate.getCreatorFullName(), currentService.getCreatorFullName(), "creatorFullName");
734             verifyValuesAreIdentical(serviceUpdate.getLastUpdaterUserId(), currentService.getLastUpdaterUserId(), "lastUpdaterUserId");
735             verifyValuesAreIdentical(serviceUpdate.getLastUpdaterFullName(), currentService.getLastUpdaterFullName(), "lastUpdaterFullName");
736
737             response = validateAndUpdateServiceName(user, currentService, serviceUpdate, hasBeenCertified, null);
738             if (response.isRight()) {
739                 return Either.right(response.right().value());
740             }
741
742             verifyValuesAreIdentical(serviceUpdate.getDistributionStatus(), currentService.getDistributionStatus(), "distributionStatus");
743
744             if (serviceUpdate.getProjectCode() != null) {
745                 response = validateAndUpdateProjectCode(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
746                 if (response.isRight()) {
747                     return Either.right(response.right().value());
748                 }
749             }
750
751             response = validateAndUpdateIcon(user, currentService, serviceUpdate, hasBeenCertified, UPDATE_SERVICE_METADATA);
752             if (response.isRight()) {
753                 return Either.right(response.right().value());
754             }
755
756             verifyValuesAreIdentical(serviceUpdate.getCreationDate(), currentService.getCreationDate(), "creationDate");
757             verifyValuesAreIdentical(serviceUpdate.getVersion(), currentService.getVersion(), "version");
758
759             response = validateAndUpdateDescription(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
760             if (response.isRight()) {
761                 return Either.right(response.right().value());
762             }
763
764             response = validateAndUpdateTags(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
765             if (response.isRight()) {
766                 return Either.right(response.right().value());
767             }
768
769             response = validateAndUpdateContactId(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
770             if (response.isRight()) {
771                 return Either.right(response.right().value());
772             }
773
774             verifyValuesAreIdentical(serviceUpdate.getLastUpdateDate(), currentService.getLastUpdateDate(), "lastUpdateDate");
775             verifyValuesAreIdentical(serviceUpdate.getLifecycleState(), currentService.getLifecycleState(), "lifecycleState");
776             verifyValuesAreIdentical(serviceUpdate.isHighestVersion(), currentService.isHighestVersion(), "isHighestVersion");
777             verifyValuesAreIdentical(serviceUpdate.getUUID(), currentService.getUUID(), "uuid");
778
779             validateAndUpdateServiceType(currentService, serviceUpdate);
780
781             response = validateAndUpdateServiceRole(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
782             if (response.isRight()) {
783                 return Either.right(response.right().value());
784             }
785
786             response = validateAndUpdateInstantiationTypeValue(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
787             if (response.isRight()) {
788                 return Either.right(response.right().value());
789             }
790
791             verifyValuesAreIdentical(serviceUpdate.getInvariantUUID(), currentService.getInvariantUUID(), "invariantUUID");
792
793             validateAndUpdateEcompNaming(currentService, serviceUpdate);
794
795             currentService.setEnvironmentContext(serviceUpdate.getEnvironmentContext());
796             return Either.left(currentService);
797
798         } catch (ComponentException exception) {
799             ResponseFormat responseFormat = componentsUtils.getResponseFormat(exception);
800             componentsUtils.auditComponentAdmin(responseFormat, user, serviceUpdate,
801                     AuditingActionEnum.UPDATE_SERVICE_METADATA, ComponentTypeEnum.SERVICE);
802             return Either.right(responseFormat);
803         }
804     }
805
806     private void verifyValuesAreIdentical(Object updatedValue, Object originalValue, String fieldName) {
807         if (updatedValue != null && !updatedValue.equals(originalValue)) {
808             log.info("update service: received request to update {} to {} the field is not updatable ignoring.", fieldName, updatedValue);
809         }
810     }
811
812     private void validateAndUpdateEcompNaming(Service currentService, Service serviceUpdate) {
813         Boolean isEcompGeneratedCurr = currentService.isEcompGeneratedNaming();
814         Boolean isEcompGeneratedUpdate = serviceUpdate.isEcompGeneratedNaming();
815         if (isEcompGeneratedUpdate != null && !isEcompGeneratedUpdate.equals(isEcompGeneratedCurr)) {
816             currentService.setEcompGeneratedNaming(isEcompGeneratedUpdate);
817         }
818         String namingPolicyUpdate = serviceUpdate.getNamingPolicy();
819         if (currentService.isEcompGeneratedNaming()) {
820             currentService.setNamingPolicy(namingPolicyUpdate);
821         } else {
822             if (!StringUtils.isEmpty(namingPolicyUpdate)) {
823                 log.warn("NamingPolicy must be empty for EcompGeneratedNaming=false");
824             }
825             currentService.setNamingPolicy("");
826         }
827     }
828
829     private Either<Boolean, ResponseFormat> validateAndUpdateContactId(User user, Service currentService, Service serviceUpdate, AuditingActionEnum audatingAction) {
830         String contactIdUpdated = serviceUpdate.getContactId();
831         String contactIdCurrent = currentService.getContactId();
832         if (!contactIdCurrent.equals(contactIdUpdated)) {
833            validateContactId(user, serviceUpdate, audatingAction);
834             currentService.setContactId(contactIdUpdated.toLowerCase());
835         }
836         return Either.left(true);
837     }
838
839     private Either<Boolean, ResponseFormat> validateAndUpdateTags(User user, Service currentService, Service serviceUpdate, AuditingActionEnum audatingAction) {
840         List<String> tagsUpdated = serviceUpdate.getTags();
841         List<String> tagsCurrent = currentService.getTags();
842         if (tagsUpdated == null || tagsUpdated.isEmpty()) {
843             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_TAGS);
844             componentsUtils.auditComponentAdmin(responseFormat, user, serviceUpdate, audatingAction, ComponentTypeEnum.SERVICE);
845             return Either.right(responseFormat);
846         }
847
848         if (!(tagsCurrent.containsAll(tagsUpdated) && tagsUpdated.containsAll(tagsCurrent))) {
849             validateTagsListAndRemoveDuplicates(user, serviceUpdate, audatingAction);
850             currentService.setTags(tagsUpdated);
851         }
852         return Either.left(true);
853     }
854
855     private Either<Boolean, ResponseFormat> validateAndUpdateDescription(User user, Service currentService, Service serviceUpdate, AuditingActionEnum audatingAction) {
856         String descriptionUpdated = serviceUpdate.getDescription();
857         String descriptionCurrent = currentService.getDescription();
858         if (!descriptionCurrent.equals(descriptionUpdated)) {
859             validateDescriptionAndCleanup(user, serviceUpdate, audatingAction);
860             currentService.setDescription(serviceUpdate.getDescription());
861         }
862         return Either.left(true);
863     }
864
865     private Either<Boolean, ResponseFormat> validateAndUpdateProjectCode(User user, Service currentService, Service serviceUpdate, AuditingActionEnum audatingAction) {
866         String projectCodeUpdated = serviceUpdate.getProjectCode();
867         String projectCodeCurrent = currentService.getProjectCode();
868         if (!projectCodeCurrent.equals(projectCodeUpdated)) {
869
870             Either<Boolean, ResponseFormat> validatProjectCodeResponse = validateProjectCode(user, serviceUpdate, audatingAction);
871             if (validatProjectCodeResponse.isRight()) {
872                 ResponseFormat errorRespons = validatProjectCodeResponse.right().value();
873                 return Either.right(errorRespons);
874             }
875             currentService.setProjectCode(projectCodeUpdated);
876
877         }
878         return Either.left(true);
879     }
880
881     private Either<Boolean, ResponseFormat> validateAndUpdateIcon(User user, Service currentService, Service serviceUpdate, boolean hasBeenCertified, AuditingActionEnum audatingAction) {
882         String iconUpdated = serviceUpdate.getIcon();
883         String iconCurrent = currentService.getIcon();
884         if (!iconCurrent.equals(iconUpdated)) {
885             if (!hasBeenCertified) {
886                 validateIcon(user, serviceUpdate, audatingAction);
887                 currentService.setIcon(iconUpdated);
888             } else {
889                 log.info("icon {} cannot be updated once the service has been certified once.", iconUpdated);
890                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.SERVICE_ICON_CANNOT_BE_CHANGED);
891                 return Either.right(errorResponse);
892             }
893         }
894         return Either.left(true);
895     }
896
897     private Either<Boolean, ResponseFormat> validateAndUpdateServiceName(User user, Service currentService, Service serviceUpdate, boolean hasBeenCertified, AuditingActionEnum auditingAction) {
898         String serviceNameUpdated = serviceUpdate.getName();
899         String serviceNameCurrent = currentService.getName();
900         if (!serviceNameCurrent.equals(serviceNameUpdated)) {
901             if (!hasBeenCertified) {
902                 validateComponentName(user, serviceUpdate, auditingAction);
903                 Either<Boolean, ResponseFormat> serviceNameUniquenessValidation = validateComponentNameUnique(user, serviceUpdate, auditingAction);
904                 if (serviceNameUniquenessValidation.isRight()) {
905                     return serviceNameUniquenessValidation;
906                 }
907                 currentService.setName(serviceNameUpdated);
908                 currentService.getComponentMetadataDefinition().getMetadataDataDefinition().setNormalizedName(ValidationUtils.normaliseComponentName(serviceNameUpdated));
909                 currentService.getComponentMetadataDefinition().getMetadataDataDefinition().setSystemName(ValidationUtils.convertToSystemName(serviceNameUpdated));
910
911             } else {
912                 log.info("service name {} cannot be updated once the service has been certified once.", serviceNameUpdated);
913                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.SERVICE_NAME_CANNOT_BE_CHANGED);
914                 return Either.right(errorResponse);
915             }
916         }
917         return Either.left(true);
918     }
919
920     private void validateAndUpdateServiceType(Service currentService, Service updatedService) {
921         String updatedServiceType = updatedService.getServiceType();
922         String currentServiceType = currentService.getServiceType();
923         if (!currentServiceType.equals(updatedServiceType)) {
924             validateServiceTypeAndCleanup(updatedService);
925             currentService.setServiceType(updatedServiceType);
926         }
927     }
928
929     private void validateServiceTypeAndCleanup(Component component) {
930         log.debug("validate service type");
931         String serviceType = ((Service)component).getServiceType();
932         if (serviceType == null) {
933             log.info("service type is not valid.");
934             throw new ComponentException(ActionStatus.INVALID_SERVICE_TYPE);
935         }
936         serviceType = cleanUpText(serviceType);
937         validateServiceType(serviceType);
938     }
939
940
941     private void validateServiceType(String serviceType) {
942         if (serviceType.isEmpty()) {
943             return;
944         }
945         if (!ValidationUtils.validateServiceTypeLength(serviceType)) {
946             log.info("service type exceeds limit.");
947             throw new ComponentException(ActionStatus.SERVICE_TYPE_EXCEEDS_LIMIT, "" + ValidationUtils.SERVICE_TYPE_MAX_LENGTH);
948         }
949         if (!ValidationUtils.validateIsEnglish(serviceType)) {
950             log.info("service type is not valid.");
951             throw new ComponentException(ActionStatus.INVALID_SERVICE_TYPE);
952         }
953     }
954
955     private Either<Boolean, ResponseFormat> validateAndUpdateServiceRole(User user, Service currentService, Service updatedService, AuditingActionEnum auditingAction) {
956         String updatedServiceRole = updatedService.getServiceRole();
957         String currentServiceRole = currentService.getServiceRole();
958         if (!currentServiceRole.equals(updatedServiceRole)) {
959             Either<Boolean, ResponseFormat> validateServiceRole = validateServiceRoleAndCleanup(user, updatedService , auditingAction);
960             if (validateServiceRole.isRight()) {
961                 ResponseFormat errorResponse = validateServiceRole.right().value();
962                 componentsUtils.auditComponentAdmin(errorResponse, user, updatedService, auditingAction, ComponentTypeEnum.SERVICE);
963                 return Either.right(errorResponse);
964             }
965             currentService.setServiceRole(updatedServiceRole);
966         }
967         return Either.left(true);
968     }
969
970     protected Either<Boolean, ResponseFormat> validateServiceRoleAndCleanup(User user, Component component, AuditingActionEnum actionEnum) {
971         log.debug("validate service role");
972         String serviceRole = ((Service)component).getServiceRole();
973         if (serviceRole != null){
974             serviceRole = cleanUpText(serviceRole);
975
976             Either<Boolean, ResponseFormat> validateServiceRole = validateServiceRole(serviceRole);
977             if (validateServiceRole.isRight()) {
978                 ResponseFormat responseFormat = validateServiceRole.right().value();
979                 componentsUtils.auditComponentAdmin(responseFormat, user, component, actionEnum, ComponentTypeEnum.SERVICE);
980                 return Either.right(responseFormat);
981             }
982             return Either.left(true);
983         } else {
984             return Either.left(false);
985         }
986     }
987
988     private Either<Boolean, ResponseFormat> validateAndUpdateInstantiationTypeValue(User user, Service currentService, Service updatedService, AuditingActionEnum auditingAction) {
989         String updatedInstaType= updatedService.getInstantiationType();
990         String currentInstaType = currentService.getInstantiationType();
991         if (!currentInstaType.equals(updatedInstaType)) {
992             Either<Boolean, ResponseFormat> validateInstantiationType = validateInstantiationTypeValue(user, updatedService , auditingAction);
993             if (validateInstantiationType.isRight()) {
994                 ResponseFormat errorResponse = validateInstantiationType.right().value();
995                 componentsUtils.auditComponentAdmin(errorResponse, user, updatedService, auditingAction, ComponentTypeEnum.SERVICE);
996                 return Either.right(errorResponse);
997             }
998             currentService.setInstantiationType(updatedInstaType);
999         }
1000         return Either.left(true);
1001     }
1002
1003     private Either<Boolean, ResponseFormat> validateInstantiationTypeValue(User user, Service service, AuditingActionEnum actionEnum) {
1004         log.debug("validate instantiation type");
1005         String instantiationType = service.getInstantiationType();
1006         if (!InstantiationTypes.containsName(instantiationType) || instantiationType == null){
1007                         log.error("Recieved Instantiation type {} is not valid.", instantiationType);
1008                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_INSTANTIATION_TYPE);
1009                         componentsUtils.auditComponentAdmin(errorResponse, user, service, actionEnum, ComponentTypeEnum.SERVICE);
1010                         return Either.right(errorResponse);
1011                 }
1012                 return Either.left(true);
1013     }
1014     
1015     private Either<Boolean, ResponseFormat> validateServiceRole(String serviceRole) {
1016         if (serviceRole.equals("")){
1017             return Either.left(true);
1018         } else {
1019             if (!ValidationUtils.validateServiceRoleLength(serviceRole)) {
1020                 log.info("service role exceeds limit.");
1021                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.SERVICE_ROLE_EXCEEDS_LIMIT, "" + ValidationUtils.SERVICE_ROLE_MAX_LENGTH);
1022                 return Either.right(errorResponse);
1023             }
1024
1025             if (!ValidationUtils.validateIsEnglish(serviceRole)) {
1026                 log.info("service role is not valid.");
1027                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_SERVICE_ROLE);
1028                 return Either.right(errorResponse);
1029             }
1030             return Either.left(true);
1031         }
1032     }
1033
1034     private Either<Boolean, ResponseFormat> validateAndUpdateCategory(User user, Service currentService, Service serviceUpdate, boolean hasBeenCertified, AuditingActionEnum audatingAction) {
1035         List<CategoryDefinition> categoryUpdated = serviceUpdate.getCategories();
1036         List<CategoryDefinition> categoryCurrent = currentService.getCategories();
1037         Either<Boolean, ResponseFormat> validateCategoryResponse = validateServiceCategory(user, serviceUpdate, audatingAction);
1038         if (validateCategoryResponse.isRight()) {
1039             return Either.right(validateCategoryResponse.right().value());
1040         }
1041         if (!categoryCurrent.get(0).getName().equals(categoryUpdated.get(0).getName())) {
1042             if (!hasBeenCertified) {
1043                 currentService.setCategories(categoryUpdated);
1044             } else {
1045                 log.info("category {} cannot be updated once the service has been certified once.", categoryUpdated);
1046                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.SERVICE_CATEGORY_CANNOT_BE_CHANGED);
1047                 return Either.right(errorResponse);
1048             }
1049         }
1050         return Either.left(true);
1051
1052     }
1053
1054     private Either<Boolean, ResponseFormat> validateServiceCategory(List<CategoryDefinition> list) {
1055         if (list != null) {
1056             if (list.size() > 1) {
1057                 log.debug("Must be only one category for service");
1058                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_TOO_MUCH_CATEGORIES, ComponentTypeEnum.SERVICE.getValue());
1059                 return Either.right(responseFormat);
1060             }
1061             CategoryDefinition category = list.get(0);
1062             if (category.getSubcategories() != null) {
1063                 log.debug("Subcategories cannot be defined for service");
1064                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.SERVICE_CANNOT_CONTAIN_SUBCATEGORY);
1065                 return Either.right(responseFormat);
1066             }
1067             if (!ValidationUtils.validateStringNotEmpty(category.getName())) {
1068                 log.debug("Resource category is empty");
1069                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_CATEGORY, ComponentTypeEnum.SERVICE.getValue());
1070                 return Either.right(responseFormat);
1071             }
1072
1073             log.debug("validating service category {} against valid categories list", list);
1074             Either<List<CategoryDefinition>, ActionStatus> categorys = elementDao.getAllServiceCategories();
1075             if (categorys.isRight()) {
1076                 log.debug("failed to retrive service categories from Titan");
1077                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(categorys.right().value());
1078                 return Either.right(responseFormat);
1079             }
1080             List<CategoryDefinition> categoryList = categorys.left().value();
1081             for (CategoryDefinition value : categoryList) {
1082                 if (value.getName().equals(category.getName())) {
1083                     return Either.left(true);
1084                 }
1085             }
1086             log.debug("Category {} is not part of service category group. Service category valid values are {}", list, categoryList);
1087             return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INVALID_CATEGORY, ComponentTypeEnum.SERVICE.getValue()));
1088         }
1089         return Either.left(false);
1090     }
1091
1092     public Either<ServiceRelations, ResponseFormat> getServiceComponentsRelations(String serviceId, User user) {
1093         Either<Service, ResponseFormat> serviceResponseFormatEither = getService(serviceId, user);
1094         if (serviceResponseFormatEither.isRight()){
1095             return Either.right(serviceResponseFormatEither.right().value());
1096         }
1097         final ServiceRelations serviceRelations = new ForwardingPathUtils().convertServiceToServiceRelations(serviceResponseFormatEither.left().value());
1098         return Either.left(serviceRelations);
1099
1100
1101     }
1102
1103     public ResponseFormat deleteService(String serviceId, User user) {
1104         ResponseFormat responseFormat;
1105         String ecompErrorContext = "delete service";
1106
1107         validateUserExists(user, ecompErrorContext, false);
1108         Either<Service, StorageOperationStatus> serviceStatus = toscaOperationFacade.getToscaElement(serviceId);
1109         if (serviceStatus.isRight()) {
1110             log.debug("failed to get service {}", serviceId);
1111             return componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(serviceStatus.right().value()), "");
1112         }
1113
1114         Service service = serviceStatus.left().value();
1115
1116         StorageOperationStatus result = StorageOperationStatus.OK;
1117         Either<Boolean, ResponseFormat> lockResult = lockComponent(service, "Mark service to delete");
1118         if (lockResult.isRight()) {
1119             return lockResult.right().value();
1120         }
1121         try {
1122             result = markComponentToDelete(service);
1123             if (result.equals(StorageOperationStatus.OK)) {
1124                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.NO_CONTENT);
1125             } else {
1126                 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(result);
1127                 responseFormat = componentsUtils.getResponseFormatByResource(actionStatus, service.getName());
1128             }
1129             return responseFormat;
1130         } finally {
1131             if (result == null || !result.equals(StorageOperationStatus.OK)) {
1132                 log.warn("operation failed. do rollback");
1133                 BeEcompErrorManager.getInstance().logBeSystemError("Delete Service");
1134                 titanDao.rollback();
1135             } else {
1136                 log.debug("operation success. do commit");
1137                 titanDao.commit();
1138             }
1139             graphLockOperation.unlockComponent(serviceId, NodeTypeEnum.Service);
1140         }
1141     }
1142
1143     public ResponseFormat deleteServiceByNameAndVersion(String serviceName, String version, User user) {
1144         ResponseFormat responseFormat;
1145         String ecompErrorContext = "delete service";
1146         validateUserNotEmpty(user, ecompErrorContext);
1147         user = validateUserExists(user, ecompErrorContext, false);
1148
1149         Either<Service, ResponseFormat> getResult = getServiceByNameAndVersion(serviceName, version, user.getUserId());
1150         if (getResult.isRight()) {
1151             return getResult.right().value();
1152         }
1153         Service service = getResult.left().value();
1154
1155         StorageOperationStatus result = StorageOperationStatus.OK;
1156         Either<Boolean, ResponseFormat> lockResult = lockComponent(service, "Mark service to delete");
1157         if (lockResult.isRight()) {
1158             result = StorageOperationStatus.GENERAL_ERROR;
1159             return componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
1160         }
1161
1162         try {
1163             result = markComponentToDelete(service);
1164             if (result.equals(StorageOperationStatus.OK)) {
1165                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.NO_CONTENT);
1166             } else {
1167                 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(result);
1168                 responseFormat = componentsUtils.getResponseFormatByResource(actionStatus, service.getName());
1169             }
1170             return responseFormat;
1171
1172         } finally {
1173             if (result == null || !result.equals(StorageOperationStatus.OK)) {
1174                 log.warn("operation failed. do rollback");
1175                 BeEcompErrorManager.getInstance().logBeSystemError("Delete Service");
1176                 titanDao.rollback();
1177             } else {
1178                 log.debug("operation success. do commit");
1179                 titanDao.commit();
1180             }
1181             graphLockOperation.unlockComponent(service.getUniqueId(), NodeTypeEnum.Service);
1182         }
1183     }
1184
1185     public Either<Service, ResponseFormat> getService(String serviceId, User user) {
1186         String ecompErrorContext = "Get service";
1187         validateUserNotEmpty(user, ecompErrorContext);
1188         validateUserExists(user, ecompErrorContext, false);
1189
1190         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaElement(serviceId);
1191         if (storageStatus.isRight()) {
1192             log.debug("failed to get service by id {}", serviceId);
1193             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), serviceId));
1194         }
1195
1196         if(!(storageStatus.left().value() instanceof Service)){
1197             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND), serviceId));
1198         }
1199         Service service = storageStatus.left().value();
1200         return Either.left(service);
1201
1202
1203
1204
1205     }
1206
1207     public Either<Service, ResponseFormat> getServiceByNameAndVersion(String serviceName, String serviceVersion, String userId) {
1208         validateUserExists(userId, "get Service By Name And Version", false);
1209         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getComponentByNameAndVersion(ComponentTypeEnum.SERVICE, serviceName, serviceVersion);
1210         if (storageStatus.isRight()) {
1211             log.debug("failed to get service by name {} and version {}", serviceName, serviceVersion);
1212             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), serviceName));
1213         }
1214         Service service = storageStatus.left().value();
1215         return Either.left(service);
1216     }
1217
1218     @SuppressWarnings("unchecked")
1219     private void createMandatoryArtifactsData(Service service, User user) {
1220         // create mandatory artifacts
1221
1222         // TODO it must be removed after that artifact uniqueId creation will be
1223         // moved to ArtifactOperation
1224         String serviceUniqueId = service.getUniqueId();
1225         Map<String, ArtifactDefinition> artifactMap = service.getArtifacts();
1226         if (artifactMap == null)
1227             artifactMap = new HashMap<>();
1228
1229         Map<String, Object> informationalServiceArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration().getInformationalServiceArtifacts();
1230         List<String> exludeServiceCategory = ConfigurationManager.getConfigurationManager().getConfiguration().getExcludeServiceCategory();
1231
1232         String category = service.getCategories().get(0).getName();
1233         boolean isCreateArtifact = true;
1234         if (category != null && exludeServiceCategory != null && !exludeServiceCategory.isEmpty()) {
1235             for (String exlude : exludeServiceCategory) {
1236                 if (exlude.equalsIgnoreCase(category)) {
1237                     isCreateArtifact = false;
1238                     break;
1239                 }
1240             }
1241
1242         }
1243
1244         if (informationalServiceArtifacts != null && isCreateArtifact) {
1245             Set<String> keys = informationalServiceArtifacts.keySet();
1246             for (String informationalServiceArtifactName : keys) {
1247                 Map<String, Object> artifactInfoMap = (Map<String, Object>) informationalServiceArtifacts.get(informationalServiceArtifactName);
1248                 ArtifactDefinition artifactDefinition = createArtifactDefinition(serviceUniqueId, informationalServiceArtifactName, artifactInfoMap, user, false);
1249                 artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition);
1250
1251             }
1252
1253             service.setArtifacts(artifactMap);
1254         }
1255     }
1256
1257     private ArtifactDefinition createArtifactDefinition(String serviceId, String logicalName, Map<String, Object> artifactInfoMap, User user, Boolean isServiceApi) {
1258
1259         ArtifactDefinition artifactInfo = artifactsBusinessLogic.createArtifactPlaceHolderInfo(serviceId, logicalName, artifactInfoMap, user, ArtifactGroupTypeEnum.INFORMATIONAL);
1260
1261         if (isServiceApi) {
1262             artifactInfo.setMandatory(false);
1263             artifactInfo.setServiceApi(true);
1264         }
1265         return artifactInfo;
1266     }
1267
1268     private Either<DistributionTransitionEnum, ResponseFormat> validateTransitionEnum(String distributionTransition) {
1269         DistributionTransitionEnum transitionEnum = null;
1270
1271         transitionEnum = DistributionTransitionEnum.getFromDisplayName(distributionTransition);
1272         if (transitionEnum == null) {
1273             BeEcompErrorManager.getInstance().logBeSystemError(CHANGE_SERVICE_DISTRIBUTION);
1274             log.info("state operation is not valid. operations allowed are: {}", DistributionTransitionEnum.valuesAsString());
1275             ResponseFormat error = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
1276             return Either.right(error);
1277         }
1278
1279         return Either.left(transitionEnum);
1280     }
1281
1282     private Either<String, ResponseFormat> validateComment(LifecycleChangeInfoWithAction comment) {
1283         String data = comment.getUserRemarks();
1284
1285         if (data == null || data.trim().isEmpty()) {
1286             BeEcompErrorManager.getInstance().logBeInvalidJsonInput(CHANGE_SERVICE_DISTRIBUTION);
1287             log.debug("user comment cannot be empty or null.");
1288             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1289         }
1290         data = ValidationUtils.removeNoneUtf8Chars(data);
1291         data = ValidationUtils.removeHtmlTags(data);
1292         data = ValidationUtils.normaliseWhitespace(data);
1293         data = ValidationUtils.stripOctets(data);
1294
1295         if (!ValidationUtils.validateLength(data, ValidationUtils.COMMENT_MAX_LENGTH)) {
1296             BeEcompErrorManager.getInstance().logBeInvalidJsonInput(CHANGE_SERVICE_DISTRIBUTION);
1297             log.debug("user comment exceeds limit.");
1298             return Either.right(componentsUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, "comment", String.valueOf(ValidationUtils.COMMENT_MAX_LENGTH)));
1299         }
1300         if (!ValidationUtils.validateIsEnglish(data)) {
1301             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1302         }
1303         return Either.left(data);
1304     }
1305
1306     private Either<Service, ResponseFormat> validateServiceDistributionChange(User user, String serviceId, AuditingActionEnum auditAction, String comment) {
1307         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaElement(serviceId);
1308         if (storageStatus.isRight()) {
1309             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.SERVICE_NOT_FOUND, serviceId);
1310             log.debug(AUDIT_BEFORE_SENDING_RESPONSE);
1311             componentsUtils.auditComponent(responseFormat, user, auditAction, new ResourceCommonInfo(serviceId, ComponentTypeEnum.SERVICE.getValue()), comment);
1312             return Either.right(responseFormat);
1313         }
1314         Service service = storageStatus.left().value();
1315
1316         if (service.getLifecycleState() != LifecycleStateEnum.CERTIFIED) {
1317             log.info("service {} is  not available for distribution. Should be in certified state", service.getUniqueId());
1318             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.SERVICE_NOT_AVAILABLE_FOR_DISTRIBUTION, service.getVersion(), service.getName());
1319             createAudit(user, auditAction, comment, service, responseFormat);
1320             return Either.right(responseFormat);
1321         }
1322         return Either.left(service);
1323     }
1324
1325     private Either<User, ResponseFormat> validateUserDistributionChange(User user, Service service, AuditingActionEnum auditAction, String comment) {
1326         log.debug("get user from DB");
1327
1328         // get user details
1329         user = validateUser(user, "Activate Distribution", service, auditAction, false);
1330         // validate user role
1331         List<Role> roles = new ArrayList<>();
1332         roles.add(Role.ADMIN);
1333         roles.add(Role.GOVERNOR);
1334         roles.add(Role.OPS);
1335         validateUserRole(user, service, roles, auditAction, comment);
1336         return Either.left(user);
1337     }
1338
1339     private void createAudit(User user, AuditingActionEnum auditAction, String comment, Service component, ResponseFormat responseFormat) {
1340         log.debug(AUDIT_BEFORE_SENDING_RESPONSE);
1341         componentsUtils.auditComponent(responseFormat, user, component, auditAction, new ResourceCommonInfo(ComponentTypeEnum.SERVICE.getValue()),
1342                 ResourceVersionInfo.newBuilder()
1343                         .state(component.getLifecycleState().name())
1344                         .version(component.getVersion())
1345                         .build(),
1346                 comment);
1347     }
1348
1349     private String getEnvNameFromConfiguration() {
1350         String configuredEnvName = ConfigurationManager.getConfigurationManager().getDistributionEngineConfiguration().getEnvironments().get(0);
1351         log.trace("Update environment name to be {}", configuredEnvName);
1352         return configuredEnvName;
1353     }
1354
1355     public Either<String, ResponseFormat> activateServiceOnTenantEnvironment(String serviceId, String envId, User modifier, ServiceDistributionReqInfo data) {
1356
1357         Either<ActivationRequestInformation, ResponseFormat> activationRequestInformationEither = serviceDistributionValidation.validateActivateServiceRequest(serviceId, envId, modifier, data);
1358         if (activationRequestInformationEither.isRight()) {
1359             return Either.right(activationRequestInformationEither.right().value());
1360         }
1361
1362         ActivationRequestInformation activationRequestInformation = activationRequestInformationEither.left().value();
1363
1364         Either<String, ResponseFormat> result = null;
1365         String did = ThreadLocalsHolder.getUuid();
1366         Service service = activationRequestInformation.getServiceToActivate();
1367         result = buildAndSendServiceNotification(service, envId, did, activationRequestInformation.getWorkloadContext(), modifier);
1368         return result;
1369     }
1370
1371     public Either<String, ResponseFormat> buildAndSendServiceNotification(Service service, String envId, String did, String workloadContext, User modifier) {
1372         String envName = getEnvNameFromConfiguration();
1373         INotificationData notificationData = distributionEngine.buildServiceForDistribution(service, did, workloadContext);
1374         ActionStatus notifyServiceResponse = distributionEngine.notifyService(did, service, notificationData, envId, envName, modifier);
1375         if (notifyServiceResponse == ActionStatus.OK) {
1376             return Either.left(did);
1377         } else {
1378             BeEcompErrorManager.getInstance().logBeSystemError("Activate Distribution - send notification");
1379             log.debug("distributionEngine.notifyService response is: {}", notifyServiceResponse);
1380             ResponseFormat error = componentsUtils.getResponseFormat(ActionStatus.INVALID_RESPONSE_FROM_PROXY);
1381             return Either.right(error);
1382         }
1383     }
1384
1385     public Either<Service, ResponseFormat> activateDistribution(String serviceId, String envName, User modifier, HttpServletRequest request) {
1386
1387         User user = validateUserExists(modifier.getUserId(), "activate Distribution", false);
1388         Either<Service, ResponseFormat> result = null;
1389         ResponseFormat response = null;
1390         Service updatedService = null;
1391         String did = ThreadLocalsHolder.getUuid();
1392          // DE194021
1393         String configuredEnvName = ConfigurationManager.getConfigurationManager().getDistributionEngineConfiguration().getEnvironments().get(0);
1394         if (configuredEnvName != null && !configuredEnvName.equals(envName)) {
1395             log.trace("Update environment name to be {} instead of {}", configuredEnvName, envName);
1396             envName = configuredEnvName;
1397         }
1398         // DE194021
1399
1400         ServletContext servletContext = request.getSession().getServletContext();
1401         boolean isDistributionEngineUp = getHealthCheckBL(servletContext).isDistributionEngineUp(); // DE
1402         if (!isDistributionEngineUp) {
1403             BeEcompErrorManager.getInstance().logBeSystemError("Distribution Engine is DOWN");
1404             log.debug("Distribution Engine is DOWN");
1405             response = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
1406             return Either.right(response);
1407         }
1408
1409         Either<Service, StorageOperationStatus> serviceRes = toscaOperationFacade.getToscaElement(serviceId);
1410         if (serviceRes.isRight()) {
1411             log.debug("failed retrieving service");
1412             response = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(serviceRes.right().value(), ComponentTypeEnum.SERVICE), serviceId);
1413             componentsUtils.auditComponent(response, user, null, AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_REQUEST,
1414                     new ResourceCommonInfo(ComponentTypeEnum.SERVICE.getValue()),
1415                     ResourceVersionInfo.newBuilder()
1416                             .build(),
1417                     did);
1418             return Either.right(response);
1419         }
1420         Service service = serviceRes.left().value();
1421         String dcurrStatus = service.getDistributionStatus().name();
1422         String updatedStatus = dcurrStatus;
1423         StorageOperationStatus readyForDistribution = distributionEngine.isReadyForDistribution(envName);
1424         if (readyForDistribution.equals(StorageOperationStatus.OK)) {
1425             INotificationData notificationData = distributionEngine.buildServiceForDistribution(service, did, null);
1426             ActionStatus notifyServiceResponse = distributionEngine.notifyService(did, service, notificationData, envName, user);
1427             if (notifyServiceResponse == ActionStatus.OK) {
1428                 Either<Service, ResponseFormat> updateStateRes = updateDistributionStatusForActivation(service, user, DistributionStatusEnum.DISTRIBUTED);
1429                 if (updateStateRes.isLeft() && updateStateRes.left().value() != null) {
1430                     updatedService = updateStateRes.left().value();
1431                     updatedStatus = updatedService.getDistributionStatus().name();
1432                 } else {
1433                     // The response is not relevant
1434                     updatedService = service;
1435                 }
1436                 ASDCKpiApi.countActivatedDistribution();
1437                 response = componentsUtils.getResponseFormat(ActionStatus.OK);
1438                 result = Either.left(updatedService);
1439             } else {
1440                 BeEcompErrorManager.getInstance().logBeSystemError("Activate Distribution - send notification");
1441                 log.debug("distributionEngine.notifyService response is: {}", notifyServiceResponse);
1442                 response = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
1443                 result = Either.right(response);
1444             }
1445         } else {
1446             response = componentsUtils.getResponseFormatByDE(componentsUtils.convertFromStorageResponse(readyForDistribution), envName);
1447             result = Either.right(response);
1448         }
1449         componentsUtils.auditComponent(response, user, service, AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_REQUEST,
1450                 new ResourceCommonInfo(service.getName(),ComponentTypeEnum.SERVICE.getValue()),
1451                 ResourceVersionInfo.newBuilder()
1452                         .distributionStatus(dcurrStatus)
1453                         .build(),
1454                 ResourceVersionInfo.newBuilder()
1455                         .distributionStatus(updatedStatus)
1456                         .build(),
1457                 null, null, did);
1458         return result;
1459     }
1460
1461     // convert to private after deletion of temp url
1462     public Either<Service, ResponseFormat> updateDistributionStatusForActivation(Service service, User user, DistributionStatusEnum state) {
1463
1464         validateUserExists(user.getUserId(), "update Distribution Status For Activation", false);
1465
1466         String serviceId = service.getUniqueId();
1467         Either<Boolean, ResponseFormat> lockResult = lockComponent(serviceId, service, "updateDistributionStatusForActivation");
1468         if (lockResult.isRight()) {
1469             return Either.right(lockResult.right().value());
1470         }
1471         try {
1472             Either<Service, StorageOperationStatus> result = toscaOperationFacade.updateDistributionStatus(service, user, state);
1473             if (result.isRight()) {
1474                 titanDao.rollback();
1475                 BeEcompErrorManager.getInstance().logBeSystemError("updateDistributionStatusForActivation");
1476                 log.debug("service {}  change distribution status failed", serviceId);
1477                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1478             }
1479             titanDao.commit();
1480             return Either.left(result.left().value());
1481         } finally {
1482             graphLockOperation.unlockComponent(serviceId, NodeTypeEnum.Service);
1483         }
1484     }
1485
1486     public Either<Service, ResponseFormat> markDistributionAsDeployed(String serviceId, String did, User user) {
1487
1488         validateUserExists(user.getUserId(), "mark Distribution As Deployed", false);
1489         log.debug("mark distribution deployed");
1490
1491         AuditingActionEnum auditAction = AuditingActionEnum.DISTRIBUTION_DEPLOY;
1492         Either<Service, StorageOperationStatus> getServiceResponse = toscaOperationFacade.getToscaElement(serviceId);
1493         if (getServiceResponse.isRight()) {
1494             BeEcompErrorManager.getInstance().logBeComponentMissingError("markDistributionAsDeployed", ComponentTypeEnum.SERVICE.getValue(), serviceId);
1495             log.debug("service {} not found", serviceId);
1496             ResponseFormat responseFormat = auditDeployError(did, user, auditAction, null, componentsUtils.convertFromStorageResponse(getServiceResponse.right().value(), ComponentTypeEnum.SERVICE), "");
1497
1498             return Either.right(responseFormat);
1499         }
1500
1501         Service service = getServiceResponse.left().value();
1502         user = validateRoleForDeploy(did, user, auditAction, service);
1503         return checkDistributionAndDeploy(did, user, auditAction, service);
1504
1505     }
1506
1507     public Either<Service, ResponseFormat> generateVfModuleArtifacts(Service service, User modifier, boolean shouldLock, boolean inTransaction) {
1508         Function<ComponentInstance, List<ArtifactGenerator<ArtifactDefinition>>> artifactTaskGeneratorCreator = ri ->
1509                 // Only one VF Module Artifact per instance - add it to a list of one
1510                 buildArtifactGenList(service, modifier, shouldLock, inTransaction, ri);
1511
1512         return generateDeploymentArtifacts(service, artifactTaskGeneratorCreator);
1513
1514     }
1515
1516     private List<ArtifactGenerator<ArtifactDefinition>> buildArtifactGenList(Service service, User modifier, boolean shouldLock, boolean inTransaction, ComponentInstance ri) {
1517         List<ArtifactGenerator<ArtifactDefinition>> asList = new ArrayList<>();
1518
1519         if (ri.getOriginType() == OriginTypeEnum.VF) {
1520             asList = Arrays.asList(new VfModuleArtifacGenerator(modifier, ri, service, shouldLock, inTransaction));
1521         }
1522         return asList;
1523     }
1524
1525     private List<GroupInstance> collectGroupsInstanceForCompInstance(ComponentInstance currVF) {
1526         Map<String, ArtifactDefinition> deploymentArtifacts = currVF.getDeploymentArtifacts();
1527         if(currVF.getGroupInstances() != null){
1528             currVF.getGroupInstances().forEach(gi -> gi.alignArtifactsUuid(deploymentArtifacts));
1529         }
1530         return currVF.getGroupInstances();
1531     }
1532
1533     private ArtifactDefinition getVfModuleInstArtifactForCompInstance(ComponentInstance currVF, Service service, Wrapper<String> payloadWrapper, Wrapper<ResponseFormat> responseWrapper) {
1534         ArtifactDefinition vfModuleAertifact = null;
1535         if (MapUtils.isNotEmpty(currVF.getDeploymentArtifacts())) {
1536             Optional<ArtifactDefinition> optionalVfModuleArtifact = currVF.getDeploymentArtifacts().values().stream().filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.VF_MODULES_METADATA.name())).findAny();
1537             if (optionalVfModuleArtifact.isPresent()) {
1538                 vfModuleAertifact = optionalVfModuleArtifact.get();
1539             }
1540         }
1541         if (vfModuleAertifact == null) {
1542             Either<ArtifactDefinition, ResponseFormat> createVfModuleArtifact = createVfModuleArtifact(currVF, service, payloadWrapper.getInnerElement());
1543             if (createVfModuleArtifact.isLeft()) {
1544                 vfModuleAertifact = createVfModuleArtifact.left().value();
1545             } else {
1546                 responseWrapper.setInnerElement(createVfModuleArtifact.right().value());
1547             }
1548         }
1549         return vfModuleAertifact;
1550     }
1551
1552     private void fillVfModuleInstHeatEnvPayload(List<GroupInstance> groupsForCurrVF, Wrapper<String> payloadWrapper) {
1553         List<VfModuleArtifactPayload> vfModulePayloads = new ArrayList<>();
1554         if (groupsForCurrVF != null) {
1555             for (GroupInstance groupInstance : groupsForCurrVF) {
1556                 VfModuleArtifactPayload modulePayload = new VfModuleArtifactPayload(groupInstance);
1557                 vfModulePayloads.add(modulePayload);
1558             }
1559             vfModulePayloads.sort(VfModuleArtifactPayload::compareByGroupName);
1560
1561             final Gson gson = new GsonBuilder().setPrettyPrinting().create();
1562
1563             String vfModulePayloadString = gson.toJson(vfModulePayloads);
1564             payloadWrapper.setInnerElement(vfModulePayloadString);
1565         }
1566
1567     }
1568
1569     private Either<ArtifactDefinition, ResponseFormat> generateVfModuleInstanceArtifact(User modifier, ComponentInstance currVFInstance, Service service, boolean shouldLock, boolean inTransaction) {
1570         ArtifactDefinition vfModuleArtifact = null;
1571         Wrapper<ResponseFormat> responseWrapper = new Wrapper<>();
1572         Wrapper<String> payloadWrapper = new Wrapper<>();
1573         List<GroupInstance> groupsForCurrVF = collectGroupsInstanceForCompInstance(currVFInstance);
1574         if (responseWrapper.isEmpty()) {
1575             fillVfModuleInstHeatEnvPayload(groupsForCurrVF, payloadWrapper);
1576         }
1577         if (responseWrapper.isEmpty() && payloadWrapper.getInnerElement() != null) {
1578             vfModuleArtifact = getVfModuleInstArtifactForCompInstance(currVFInstance, service, payloadWrapper, responseWrapper);
1579         }
1580         if (responseWrapper.isEmpty() && vfModuleArtifact != null) {
1581             vfModuleArtifact = fillVfModulePayload(modifier, currVFInstance, vfModuleArtifact, shouldLock, inTransaction, payloadWrapper, responseWrapper, service);
1582         }
1583
1584         Either<ArtifactDefinition, ResponseFormat> result;
1585         if (responseWrapper.isEmpty()) {
1586             result = Either.left(vfModuleArtifact);
1587         } else {
1588             result = Either.right(responseWrapper.getInnerElement());
1589         }
1590
1591         return result;
1592     }
1593
1594     private ArtifactDefinition fillVfModulePayload(User modifier, ComponentInstance currVF, ArtifactDefinition vfModuleArtifact, boolean shouldLock, boolean inTransaction, Wrapper<String> payloadWrapper, Wrapper<ResponseFormat> responseWrapper, Service service) {
1595         ArtifactDefinition result = null;
1596         Either<ArtifactDefinition, ResponseFormat> eitherPayload = artifactsBusinessLogic.generateArtifactPayload(vfModuleArtifact, ComponentTypeEnum.RESOURCE_INSTANCE, service, currVF.getName(), modifier, shouldLock, inTransaction, System::currentTimeMillis,
1597                 () -> Either.left(artifactsBusinessLogic.createEsArtifactData(vfModuleArtifact, payloadWrapper.getInnerElement().getBytes(StandardCharsets.UTF_8))), currVF.getUniqueId());
1598         if (eitherPayload.isLeft()) {
1599             result = eitherPayload.left().value();
1600         } else {
1601             responseWrapper.setInnerElement(eitherPayload.right().value());
1602         }
1603         if (result == null) {
1604             result = vfModuleArtifact;
1605         }
1606
1607         return result;
1608     }
1609
1610     private Either<ArtifactDefinition, ResponseFormat> createVfModuleArtifact(ComponentInstance currVF, Service service, String vfModulePayloadString) {
1611
1612         ArtifactDefinition vfModuleArtifactDefinition = new ArtifactDefinition();
1613         String newCheckSum = null;
1614
1615         vfModuleArtifactDefinition.setDescription("Auto-generated VF Modules information artifact");
1616         vfModuleArtifactDefinition.setArtifactDisplayName("Vf Modules Metadata");
1617         vfModuleArtifactDefinition.setArtifactType(ArtifactTypeEnum.VF_MODULES_METADATA.getType());
1618         vfModuleArtifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.DEPLOYMENT);
1619         vfModuleArtifactDefinition.setArtifactLabel("vfModulesMetadata");
1620         vfModuleArtifactDefinition.setTimeout(0);
1621         vfModuleArtifactDefinition.setArtifactName(currVF.getNormalizedName() + "_modules.json");
1622         vfModuleArtifactDefinition.setPayloadData(vfModulePayloadString);
1623         if (vfModulePayloadString != null) {
1624             newCheckSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(vfModulePayloadString.getBytes());
1625         }
1626         vfModuleArtifactDefinition.setArtifactChecksum(newCheckSum);
1627
1628         Either<ArtifactDefinition, StorageOperationStatus> addArifactToComponent = artifactToscaOperation.addArifactToComponent(vfModuleArtifactDefinition, service.getUniqueId(), NodeTypeEnum.ResourceInstance, true, currVF.getUniqueId());
1629
1630         Either<ArtifactDefinition, ResponseFormat> result;
1631         if (addArifactToComponent.isLeft()) {
1632             result = Either.left(addArifactToComponent.left().value());
1633         } else {
1634             result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(addArifactToComponent.right().value())));
1635         }
1636
1637         return result;
1638     }
1639
1640     public Either<Service, ResponseFormat> generateHeatEnvArtifacts(Service service, User modifier, boolean shouldLock, boolean inTransaction) {
1641
1642         Function<ComponentInstance, List<ArtifactGenerator<ArtifactDefinition>>> artifactTaskGeneratorCreator = resourceInstance ->
1643                 // Get All Deployment Artifacts
1644                 service.getComponentInstances().stream().filter(ri -> ri != null && ri == resourceInstance).filter(ri -> ri.getDeploymentArtifacts() != null).flatMap(ri -> ri.getDeploymentArtifacts().values().stream()).
1645                         // Filter in Only Heat Env
1646                                 filter(depArtifact -> ArtifactTypeEnum.HEAT_ENV.getType().equals(depArtifact.getArtifactType())).
1647                         // Create ArtifactGenerator from those Artifacts
1648                                 map(depArtifact -> new HeatEnvArtifactGenerator(depArtifact, service, resourceInstance.getName(), modifier, shouldLock, inTransaction, resourceInstance.getUniqueId())).collect(Collectors.toList());
1649
1650         return generateDeploymentArtifacts(service, artifactTaskGeneratorCreator);
1651
1652     }
1653
1654     private <CallVal> Either<Service, ResponseFormat> generateDeploymentArtifacts(Service service, Function<ComponentInstance, List<ArtifactGenerator<CallVal>>> artifactTaskGeneratorCreator) {
1655
1656         // Get Flat List of (Callable) ArtifactGenerator for all the RI in the
1657         // service
1658         if (service.getComponentInstances() != null) {
1659             List<ArtifactGenerator<CallVal>> artifactGenList = service.getComponentInstances().stream().flatMap(ri -> artifactTaskGeneratorCreator.apply(ri).stream()).collect(Collectors.toList());
1660             if (artifactGenList != null && !artifactGenList.isEmpty()) {
1661                 for (ArtifactGenerator<CallVal> entry : artifactGenList) {
1662                     Either<CallVal, ResponseFormat> callRes;
1663                     try {
1664                         callRes = entry.call();
1665                         if (callRes.isRight()) {
1666                             log.debug("Failed to generate artifact error : {}", callRes.right().value());
1667                             return Either.right(callRes.right().value());
1668                         }
1669                     } catch (Exception e) {
1670                         log.debug("Failed to generate artifact exception : {}", e);
1671                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1672                     }
1673                 }
1674             }
1675         }
1676         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaFullElement(service.getUniqueId());
1677         if (storageStatus.isRight()) {
1678             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), ""));
1679         }
1680
1681         Service currentService = storageStatus.left().value();
1682
1683         return Either.left(currentService);
1684
1685     }
1686
1687     abstract class ArtifactGenerator<CallVal> implements Callable<Either<CallVal, ResponseFormat>> {
1688
1689     }
1690
1691     class HeatEnvArtifactGenerator extends ArtifactGenerator<ArtifactDefinition> {
1692         ArtifactDefinition artifactDefinition;
1693         Service service;
1694         String resourceInstanceName;
1695         User modifier;
1696         String instanceId;
1697         boolean shouldLock;
1698         boolean inTransaction;
1699
1700         HeatEnvArtifactGenerator(ArtifactDefinition artifactDefinition, Service service, String resourceInstanceName, User modifier, boolean shouldLock, boolean inTransaction, String instanceId) {
1701             this.artifactDefinition = artifactDefinition;
1702             this.service = service;
1703             this.resourceInstanceName = resourceInstanceName;
1704             this.modifier = modifier;
1705             this.shouldLock = shouldLock;
1706             this.instanceId = instanceId;
1707             this.inTransaction = inTransaction;
1708         }
1709
1710         @Override
1711         public Either<ArtifactDefinition, ResponseFormat> call() throws Exception {
1712             return artifactsBusinessLogic.forceGenerateHeatEnvArtifact(artifactDefinition, ComponentTypeEnum.RESOURCE_INSTANCE, service, resourceInstanceName, modifier, shouldLock, inTransaction, instanceId);
1713         }
1714
1715         public ArtifactDefinition getArtifactDefinition() {
1716             return artifactDefinition;
1717         }
1718
1719     }
1720
1721     class VfModuleArtifacGenerator extends ArtifactGenerator<ArtifactDefinition> {
1722         private User user;
1723         private ComponentInstance componentInstance;
1724         private Service service;
1725         boolean shouldLock;
1726         boolean inTransaction;
1727
1728         @Override
1729         public Either<ArtifactDefinition, ResponseFormat> call() throws Exception {
1730             return generateVfModuleInstanceArtifact(user, componentInstance, service, shouldLock, inTransaction);
1731         }
1732
1733         private VfModuleArtifacGenerator(User user, ComponentInstance componentInstance, Service service, boolean shouldLock, boolean inTransaction) {
1734             super();
1735             this.user = user;
1736             this.componentInstance = componentInstance;
1737             this.service = service;
1738             this.shouldLock = shouldLock;
1739             this.inTransaction = inTransaction;
1740         }
1741
1742     }
1743
1744     private synchronized Either<Service, ResponseFormat> checkDistributionAndDeploy(String distributionId, User user, AuditingActionEnum auditAction, Service service) {
1745         boolean isDeployed = isDistributionDeployed(distributionId);
1746         if (isDeployed) {
1747             return Either.left(service);
1748         }
1749         Either<Boolean, ResponseFormat> distributionSuccess = checkDistributionSuccess(distributionId, user, auditAction, service);
1750         if (distributionSuccess.isRight()) {
1751             return Either.right(distributionSuccess.right().value());
1752         }
1753
1754         log.debug("mark distribution {} as deployed - success", distributionId);
1755         componentsUtils.auditServiceDistributionDeployed(service.getName(), service.getVersion(), service.getUUID(), distributionId, STATUS_DEPLOYED, "OK", user);
1756         return Either.left(service);
1757     }
1758
1759     private boolean isDistributionDeployed(String distributionId) {
1760         Either<List<DistributionDeployEvent>, ActionStatus> alreadyDeployed = auditCassandraDao.getDistributionDeployByStatus(distributionId, AuditingActionEnum.DISTRIBUTION_DEPLOY.getName(), STATUS_DEPLOYED);
1761
1762         boolean isDeployed = false;
1763         if (alreadyDeployed.isLeft() && !alreadyDeployed.left().value().isEmpty()) {
1764             // already deployed
1765             log.debug("distribution {} is already deployed", distributionId);
1766             isDeployed = true;
1767         }
1768         return isDeployed;
1769     }
1770
1771     protected Either<Boolean, ResponseFormat> checkDistributionSuccess(String did, User user, AuditingActionEnum auditAction, Service service) {
1772
1773         log.trace("checkDistributionSuccess");
1774         // get all "DRequest" records for this distribution
1775
1776         Either<List<ResourceAdminEvent>, ActionStatus> distRequestsResponse = auditCassandraDao.getDistributionRequest(did, AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_REQUEST.getName());
1777         if (distRequestsResponse.isRight()) {
1778             ResponseFormat error = auditDeployError(did, user, auditAction, service, distRequestsResponse.right().value());
1779             return Either.right(error);
1780         }
1781
1782         List<ResourceAdminEvent> distributionRequests = distRequestsResponse.left().value();
1783         if (distributionRequests.isEmpty()) {
1784             BeEcompErrorManager.getInstance().logBeDistributionMissingError("markDistributionAsDeployed", did);
1785             log.info("distribution {} is not found", did);
1786             ResponseFormat error = auditDeployError(did, user, auditAction, service, ActionStatus.DISTRIBUTION_REQUESTED_NOT_FOUND);
1787             return Either.right(error);
1788         }
1789         boolean isRequestSucceeded = false;
1790         for (ResourceAdminEvent event : distributionRequests) {
1791             String eventStatus = event.getStatus();
1792             if (eventStatus != null && eventStatus.equals(STATUS_SUCCESS_200)) {
1793                 isRequestSucceeded = true;
1794                 break;
1795             }
1796         }
1797
1798         // get all "DNotify" records for this distribution
1799         Either<List<DistributionNotificationEvent>, ActionStatus> distNotificationsResponse = auditCassandraDao.getDistributionNotify(did, AuditingActionEnum.DISTRIBUTION_NOTIFY.getName());
1800         if (distNotificationsResponse.isRight()) {
1801             ResponseFormat error = auditDeployError(did, user, auditAction, service, distNotificationsResponse.right().value());
1802             return Either.right(error);
1803         }
1804
1805         List<DistributionNotificationEvent> distributionNotifications = distNotificationsResponse.left().value();
1806         boolean isNotificationsSucceeded = false;
1807         for (DistributionNotificationEvent event : distributionNotifications) {
1808             String eventStatus = event.getStatus();
1809             if (eventStatus != null && eventStatus.equals(STATUS_SUCCESS_200)) {
1810                 isNotificationsSucceeded = true;
1811                 break;
1812             }
1813         }
1814
1815         // if request failed OR there are notifications that failed
1816         if (!(isRequestSucceeded && isNotificationsSucceeded)) {
1817
1818             log.info("distribution {} has failed", did);
1819             ResponseFormat error = componentsUtils.getResponseFormat(ActionStatus.DISTRIBUTION_REQUESTED_FAILED, did);
1820             auditDeployError(did, user, auditAction, service, ActionStatus.DISTRIBUTION_REQUESTED_FAILED, did);
1821             return Either.right(error);
1822         }
1823         return Either.left(true);
1824     }
1825
1826     private ResponseFormat auditDeployError(String did, User user, AuditingActionEnum auditAction, Service service, ActionStatus status, String... params) {
1827
1828         ResponseFormat error = componentsUtils.getResponseFormat(status, params);
1829         String message = "";
1830         if (error.getMessageId() != null) {
1831             message = error.getMessageId() + ": ";
1832         }
1833         message += error.getFormattedMessage();
1834
1835         if (service != null) {
1836             componentsUtils.auditServiceDistributionDeployed(service.getName(), service.getVersion(), service.getUUID(), did, error.getStatus().toString(), message, user);
1837         } else {
1838             componentsUtils.auditServiceDistributionDeployed("", "", "", did, error.getStatus().toString(), message, user);
1839         }
1840         return error;
1841     }
1842
1843     private User validateRoleForDeploy(String did, User user, AuditingActionEnum auditAction, Service service) {
1844         Either<User, ActionStatus> eitherCreator = userAdmin.getUser(user.getUserId(), false);
1845         if (eitherCreator.isRight() || eitherCreator.left().value() == null) {
1846             BeEcompErrorManager.getInstance().logBeUserMissingError("Deploy Service", user.getUserId());
1847             log.debug("validateRoleForDeploy method - user is not listed. userId= {}", user.getUserId());
1848             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.USER_NOT_FOUND, user.getUserId());
1849             auditDeployError(did, user, auditAction, service, ActionStatus.USER_NOT_FOUND);
1850             throw new ComponentException(ActionStatus.USER_NOT_FOUND, user.getUserId());
1851         }
1852         user = eitherCreator.left().value();
1853         log.debug("validate user role");
1854         List<Role> roles = new ArrayList<>();
1855         roles.add(Role.ADMIN);
1856         roles.add(Role.OPS);
1857         try{
1858             validateUserRole(user, service, roles, auditAction, null);
1859         } catch (ComponentException e){
1860             log.info("role {} is not allowed to perform this action", user.getRole());
1861             auditDeployError(did, user, auditAction, service, e.getActionStatus());
1862             throw e;
1863         }
1864         return user;
1865     }
1866
1867     @Override
1868     public void setDeploymentArtifactsPlaceHolder(Component component, User user) {
1869
1870     }
1871
1872     @Override
1873     public Either<List<String>, ResponseFormat> deleteMarkedComponents() {
1874         return deleteMarkedComponents(ComponentTypeEnum.SERVICE);
1875     }
1876
1877     private HealthCheckBusinessLogic getHealthCheckBL(ServletContext context) {
1878         WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
1879         WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
1880         return webApplicationContext.getBean(HealthCheckBusinessLogic.class);
1881     }
1882
1883     @Override
1884     public ComponentInstanceBusinessLogic getComponentInstanceBL() {
1885         return componentInstanceBusinessLogic;
1886     }
1887
1888     @Override
1889     public Either<List<ComponentInstance>, ResponseFormat> getComponentInstancesFilteredByPropertiesAndInputs(String componentId, String userId) {
1890
1891         validateUserExists(userId, "Get Component Instances", false);
1892         Either<Component, StorageOperationStatus> getComponentRes = toscaOperationFacade.getToscaElement(componentId, JsonParseFlagEnum.ParseAll);
1893         if (getComponentRes.isRight()) {
1894             ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(getComponentRes.right().value()));
1895             return Either.right(responseFormat);
1896         }
1897
1898         List<ComponentInstance> componentInstances = getComponentRes.left().value().getComponentInstances();
1899
1900         return Either.left(componentInstances);
1901     }
1902
1903     public ICacheMangerOperation getCacheManagerOperation() {
1904         return cacheManagerOperation;
1905     }
1906
1907     public void setCacheManagerOperation(ICacheMangerOperation cacheManagerOperation) {
1908         this.cacheManagerOperation = cacheManagerOperation;
1909     }
1910
1911     public void setForwardingPathOperation(ForwardingPathOperation forwardingPathOperation) {
1912         this.forwardingPathOperation = forwardingPathOperation;
1913     }
1914
1915     @Override
1916     public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) {
1917         this.toscaOperationFacade = toscaOperationFacade;
1918     }/**
1919      * updates group instance with new property values in case of successful update of group instance related component instance will be updated with new modification time and related service will be updated with new last update date
1920      *
1921      */
1922     public Either<List<GroupInstanceProperty>, ResponseFormat> updateGroupInstancePropertyValues(User modifier, String serviceId, String componentInstanceId, String groupInstanceId, List<GroupInstanceProperty> newProperties) {
1923
1924         Either<List<GroupInstanceProperty>, ResponseFormat> actionResult = null;
1925         Either<ImmutablePair<Component, User>, ResponseFormat> validateUserAndComponentRes;
1926         Component component = null;
1927         Either<Boolean, ResponseFormat> lockResult = null;
1928         log.debug("Going to update group instance {} of service {} with new property values. ", groupInstanceId, serviceId);
1929         try {
1930             validateUserAndComponentRes = validateUserAndComponent(serviceId, modifier);
1931             if (validateUserAndComponentRes.isRight()) {
1932                 log.debug("Cannot update group instance {} of service {} with new property values. Validation failed.  ", groupInstanceId, serviceId);
1933                 actionResult = Either.right(validateUserAndComponentRes.right().value());
1934             }
1935             if (actionResult == null) {
1936                 component = validateUserAndComponentRes.left().value().getKey();
1937                 lockResult = lockComponentByName(component.getSystemName(), component, "Update Group Instance on Service");
1938                 if (lockResult.isRight()) {
1939                     log.debug(FAILED_TO_LOCK_SERVICE_RESPONSE_IS, component.getName(), lockResult.right().value().getFormattedMessage());
1940                     actionResult = Either.right(lockResult.right().value());
1941                 } else {
1942                     log.debug(THE_SERVICE_WITH_SYSTEM_NAME_LOCKED, component.getSystemName());
1943                 }
1944             }
1945             if (actionResult == null) {
1946                 actionResult = validateAndUpdateGroupInstancePropertyValuesAndContainingParents(component, componentInstanceId, groupInstanceId, newProperties);
1947                 if (actionResult.isRight()) {
1948                     log.debug("Failed to validate and update group instance {} property values and containing parents. The message is {}. ", groupInstanceId, actionResult.right().value().getFormattedMessage());
1949                 }
1950             }
1951         } catch (Exception e) {
1952             log.error("Exception occured during update Group Instance property values: {}", e.getMessage(), e);
1953             actionResult = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1954         } finally {
1955             if (lockResult != null && lockResult.isLeft() && lockResult.left().value()) {
1956                 graphLockOperation.unlockComponentByName(component.getSystemName(), component.getUniqueId(), NodeTypeEnum.Service);
1957             }
1958         }
1959         return actionResult;
1960     }
1961
1962     private Either<List<GroupInstanceProperty>, ResponseFormat> validateAndUpdateGroupInstancePropertyValuesAndContainingParents(Component component, String componentInstanceId, String groupInstanceId, List<GroupInstanceProperty> newProperties) {
1963
1964         Either<List<GroupInstanceProperty>, ResponseFormat> actionResult = null;
1965         Either<ImmutablePair<ComponentInstance, GroupInstance>, ResponseFormat> findGroupInstanceRes;
1966         Either<ImmutablePair<ComponentMetadataData, ComponentInstanceData>, ResponseFormat> updateParentsModificationTimeRes;
1967         ComponentInstance relatedComponentInstance = null;
1968         GroupInstance oldGroupInstance = null;
1969         Either<GroupInstance, ResponseFormat> updateGroupInstanceResult = null;
1970         GroupInstance updatedGroupInstance = null;
1971         boolean inTransaction = true;
1972         findGroupInstanceRes = findGroupInstanceOnRelatedComponentInstance(component, componentInstanceId, groupInstanceId);
1973         if (findGroupInstanceRes.isRight()) {
1974             log.debug("#validateAndUpdateGroupInstancePropertyValuesAndContainingParents - Group instance {} not found. ", groupInstanceId);
1975             actionResult = Either.right(findGroupInstanceRes.right().value());
1976         }
1977         if (actionResult == null) {
1978             oldGroupInstance = findGroupInstanceRes.left().value().getValue();
1979             relatedComponentInstance = findGroupInstanceRes.left().value().getKey();
1980             updateGroupInstanceResult = groupBusinessLogic.validateAndUpdateGroupInstancePropertyValues(component.getUniqueId(), componentInstanceId, oldGroupInstance, newProperties);
1981             if (updateGroupInstanceResult.isRight()) {
1982                 log.debug("#validateAndUpdateGroupInstancePropertyValuesAndContainingParents - Failed to update group instance {} property values. ", oldGroupInstance.getName());
1983                 actionResult = Either.right(updateGroupInstanceResult.right().value());
1984             }
1985         }
1986         if (actionResult == null) {
1987             updatedGroupInstance = updateGroupInstanceResult.left().value();
1988             if (!oldGroupInstance.getModificationTime().equals(updatedGroupInstance.getModificationTime())) {
1989                 updateParentsModificationTimeRes = updateParentsModificationTimeAndCustomizationUuid(component, relatedComponentInstance, updatedGroupInstance, inTransaction);
1990                 if (updateParentsModificationTimeRes.isRight()) {
1991                     log.debug("#validateAndUpdateGroupInstancePropertyValuesAndContainingParents - Failed to update modification time for group instance {}. ", oldGroupInstance.getName());
1992                     actionResult = Either.right(updateParentsModificationTimeRes.right().value());
1993                 }
1994             }
1995         }
1996         if (actionResult == null) {
1997             actionResult = Either.left(updatedGroupInstance.convertToGroupInstancesProperties());
1998         }
1999         return actionResult;
2000     }
2001
2002     private Either<ImmutablePair<ComponentMetadataData, ComponentInstanceData>, ResponseFormat> updateParentsModificationTimeAndCustomizationUuid(Component component, ComponentInstance relatedComponentInstance, GroupInstance updatedGroupInstance,
2003                                                                                                                                                   boolean inTranscation) {
2004
2005         Either<ImmutablePair<ComponentMetadataData, ComponentInstanceData>, ResponseFormat> actionResult;
2006         Either<ComponentMetadataData, StorageOperationStatus> serviceMetadataUpdateResult;
2007         Either<ComponentInstanceData, ResponseFormat> updateComponentInstanceRes = componentInstanceBusinessLogic.updateComponentInstanceModificationTimeAndCustomizationUuid(relatedComponentInstance, NodeTypeEnum.ResourceInstance,
2008                 updatedGroupInstance.getModificationTime(), inTranscation);
2009         if (updateComponentInstanceRes.isRight()) {
2010             log.debug("Failed to update component instance {} after update of group instance {}. ", relatedComponentInstance.getName(), updatedGroupInstance.getName());
2011             actionResult = Either.right(updateComponentInstanceRes.right().value());
2012         } else {
2013             serviceMetadataUpdateResult = toscaOperationFacade.updateComponentLastUpdateDateOnGraph(component);
2014             if (serviceMetadataUpdateResult.isRight()) {
2015                 log.debug("Failed to update service {} after update of component instance {} with new property values of group instance {}. ", component.getName(), relatedComponentInstance.getName(), updatedGroupInstance.getName());
2016                 actionResult = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(serviceMetadataUpdateResult.right().value())));
2017             } else {
2018                 actionResult = Either.left(new ImmutablePair<>(serviceMetadataUpdateResult.left().value(), updateComponentInstanceRes.left().value()));
2019             }
2020         }
2021         return actionResult;
2022     }
2023
2024     private Either<ImmutablePair<Component, User>, ResponseFormat> validateUserAndComponent(String serviceId, User modifier) {
2025
2026         Either<ImmutablePair<Component, User>, ResponseFormat> result = null;
2027         Either<Component, ResponseFormat> validateComponentExistsRes = null;
2028         User currUser = null;
2029         Component component = null;
2030         Either<User, ResponseFormat> validationUserResult = validateUserIgnoreAudit(modifier, "updateGroupInstancePropertyValues");
2031         if (validationUserResult.isRight()) {
2032             log.debug("#validateUserAndComponent - Failed to validate user with userId {}, for update service {}. ", modifier.getUserId(), serviceId);
2033             result = Either.right(validationUserResult.right().value());
2034         }
2035         if (result == null) {
2036             currUser = validationUserResult.left().value();
2037             validateComponentExistsRes = validateComponentExists(serviceId, ComponentTypeEnum.SERVICE, null);
2038             if (validateComponentExistsRes.isRight()) {
2039                 log.debug("#validateUserAndComponent - Failed to validate service existing {}. ", serviceId);
2040                 result = Either.right(validateComponentExistsRes.right().value());
2041             }
2042         }
2043         if (result == null) {
2044             component = validateComponentExistsRes.left().value();
2045             if (!ComponentValidationUtils.canWorkOnComponent(component, currUser.getUserId())) {
2046                 log.info("#validateUserAndComponent - Restricted operation for user: {}, on service: {}", currUser.getUserId(), component.getCreatorUserId());
2047                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
2048             }
2049         }
2050         if (result == null) {
2051             result = Either.left(new ImmutablePair<>(component, currUser));
2052         }
2053         return result;
2054     }
2055
2056     private Either<ImmutablePair<ComponentInstance, GroupInstance>, ResponseFormat> findGroupInstanceOnRelatedComponentInstance(Component component, String componentInstanceId, String groupInstanceId) {
2057
2058         Either<ImmutablePair<ComponentInstance, GroupInstance>, ResponseFormat> actionResult = null;
2059         GroupInstance groupInstance = null;
2060         ComponentInstance foundComponentInstance = findRelatedComponentInstance(component, componentInstanceId);
2061         if (foundComponentInstance == null) {
2062             log.debug("Component instance {} not found on service {}. ", componentInstanceId, component.getName());
2063             actionResult = Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, componentInstanceId, "resource instance", "service", component.getName()));
2064         }
2065         else if (isNotEmpty(foundComponentInstance.getGroupInstances())) {
2066             groupInstance = foundComponentInstance.getGroupInstances().stream().filter(gi -> gi.getUniqueId().equals(groupInstanceId)).findFirst().orElse(null);
2067             if (groupInstance == null) {
2068                 log.debug("Group instance {} not found on component instance {}. ", groupInstanceId, foundComponentInstance.getName());
2069                 actionResult = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_INSTANCE_NOT_FOUND_ON_COMPONENT_INSTANCE, groupInstanceId, foundComponentInstance.getName()));
2070             }
2071         }
2072         if (actionResult == null) {
2073             actionResult = Either.left(new ImmutablePair<>(foundComponentInstance, groupInstance));
2074         }
2075         return actionResult;
2076     }
2077
2078     private ComponentInstance findRelatedComponentInstance(Component component, String componentInstanceId) {
2079         ComponentInstance componentInstance = null;
2080         if (isNotEmpty(component.getComponentInstances())) {
2081             componentInstance = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(componentInstanceId)).findFirst().orElse(null);
2082         }
2083         return componentInstance;
2084     }
2085
2086     private Either<User, ResponseFormat> validateUserIgnoreAudit(User modifier, String ecompErrorContext) {
2087         User user = validateUser(modifier, ecompErrorContext, null, null, false);
2088         List<Role> roles = new ArrayList<>();
2089         roles.add(Role.ADMIN);
2090         roles.add(Role.DESIGNER);
2091         validateUserRole(user, roles);
2092         return Either.left(user);
2093     }
2094
2095     public Either<UiComponentDataTransfer, ResponseFormat> getUiComponentDataTransferByComponentId(String serviceId, List<String> dataParamsToReturn) {
2096
2097         ComponentParametersView paramsToReturn = new ComponentParametersView(dataParamsToReturn);
2098         Either<Service, StorageOperationStatus> serviceResultEither = toscaOperationFacade.getToscaElement(serviceId, paramsToReturn);
2099
2100         if (serviceResultEither.isRight()) {
2101             if(serviceResultEither.right().value().equals(StorageOperationStatus.NOT_FOUND)) {
2102                 log.debug("#getUiComponentDataTransferByComponentId - Failed to find service with id {} ", serviceId);
2103                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SERVICE_NOT_FOUND, serviceId));
2104             }
2105
2106             log.debug("#getUiComponentDataTransferByComponentId - failed to get service by id {} with filters {}", serviceId, dataParamsToReturn);
2107             return Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(serviceResultEither.right().value()), ""));
2108         }
2109
2110         Service service = serviceResultEither.left().value();
2111         UiComponentDataTransfer dataTransfer = uiComponentDataConverter.getUiDataTransferFromServiceByParams(service, dataParamsToReturn);
2112         return Either.left(dataTransfer);
2113     }
2114 }