[SDC-29] catalog 1707 rebase commit.
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ComponentBusinessLogic.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 java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.EnumMap;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.function.Function;
31 import java.util.function.Predicate;
32 import java.util.stream.Collectors;
33
34 import org.apache.commons.collections.CollectionUtils;
35 import org.apache.commons.collections.MapUtils;
36 import org.apache.commons.lang3.StringUtils;
37 import org.apache.commons.lang3.tuple.ImmutablePair;
38 import org.openecomp.sdc.be.config.BeEcompErrorManager;
39 import org.openecomp.sdc.be.config.ConfigurationManager;
40 import org.openecomp.sdc.be.dao.api.ActionStatus;
41 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
42 import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum;
43 import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter;
44 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
45 import org.openecomp.sdc.be.datatypes.components.ServiceMetadataDataDefinition;
46 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
47 import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum;
48 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
49 import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum;
50 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
51 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
52 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
53 import org.openecomp.sdc.be.model.ArtifactDefinition;
54 import org.openecomp.sdc.be.model.CapReqDef;
55 import org.openecomp.sdc.be.model.CapabilityDefinition;
56 import org.openecomp.sdc.be.model.Component;
57 import org.openecomp.sdc.be.model.ComponentInstance;
58 import org.openecomp.sdc.be.model.ComponentInstanceInput;
59 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
60 import org.openecomp.sdc.be.model.ComponentParametersView;
61 import org.openecomp.sdc.be.model.DataTypeDefinition;
62 import org.openecomp.sdc.be.model.IComponentInstanceConnectedElement;
63 import org.openecomp.sdc.be.model.InputDefinition;
64 import org.openecomp.sdc.be.model.LifecycleStateEnum;
65 import org.openecomp.sdc.be.model.Operation;
66 import org.openecomp.sdc.be.model.PropertyDefinition;
67 import org.openecomp.sdc.be.model.RequirementDefinition;
68 import org.openecomp.sdc.be.model.Resource;
69 import org.openecomp.sdc.be.model.User;
70 import org.openecomp.sdc.be.model.cache.ComponentCache;
71 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
72 import org.openecomp.sdc.be.model.operations.impl.ComponentOperation;
73 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
74 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
75 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
76 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
77 import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
78 import org.openecomp.sdc.be.user.Role;
79 import org.openecomp.sdc.be.utils.CommonBeUtils;
80 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
81 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
82 import org.openecomp.sdc.common.config.EcompErrorName;
83 import org.openecomp.sdc.common.datastructure.AuditingFieldsKeysEnum;
84 import org.openecomp.sdc.common.util.ValidationUtils;
85 import org.openecomp.sdc.exception.ResponseFormat;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
88 import org.springframework.beans.factory.annotation.Autowired;
89
90 import com.datastax.driver.core.UserType.Field;
91 import com.wordnik.swagger.models.auth.In;
92
93 import fj.data.Either;
94
95 public abstract class ComponentBusinessLogic extends BaseBusinessLogic {
96
97         @Autowired
98         protected ArtifactsBusinessLogic artifactsBusinessLogic;
99
100         @Autowired
101         protected ComponentCache componentCache;
102
103
104         private static Logger log = LoggerFactory.getLogger(ComponentBusinessLogic.class.getName());
105
106         private static final String TAG_FIELD_LABEL = "tag";
107
108         public abstract Either<List<String>, ResponseFormat> deleteMarkedComponents();
109
110         public abstract ComponentInstanceBusinessLogic getComponentInstanceBL();
111
112         public abstract Either<List<ComponentInstance>, ResponseFormat> getComponentInstancesFilteredByPropertiesAndInputs(String componentId, ComponentTypeEnum componentTypeEnum, String userId, String searchText);
113
114         /**
115          * 
116          * @param componentId
117          * @param dataParamsToReturn
118          * @return
119          */
120         public abstract  Either<UiComponentDataTransfer, ResponseFormat> getUiComponentDataTransferByComponentId(String componentId, List<String> dataParamsToReturn);
121
122         protected Either<User, ResponseFormat> validateUser(User user, String ecompErrorContext, Component component, AuditingActionEnum auditAction, boolean inTransaction) {
123                 Either<User, ResponseFormat> userValidationResult = validateUserNotEmpty(user, ecompErrorContext);
124                 ResponseFormat responseFormat;
125                 if (userValidationResult.isRight()) {
126                         user.setUserId("UNKNOWN");
127                         responseFormat = userValidationResult.right().value();
128                         componentsUtils.auditComponentAdmin(responseFormat, user, component, "", "", auditAction, component.getComponentType());
129                         return Either.right(responseFormat);
130                 }
131                 Either<User, ResponseFormat> userResult = validateUserExists(user, ecompErrorContext, inTransaction);
132                 if (userResult.isRight()) {
133                         responseFormat = userResult.right().value();
134                         componentsUtils.auditComponentAdmin(responseFormat, user, component, "", "", auditAction, component.getComponentType());
135                         return Either.right(responseFormat);
136                 }
137                 user = userResult.left().value();
138                 return userResult;
139         }
140
141         protected Either<Boolean, ResponseFormat> validateUserRole(User user, Component component, List<Role> roles, AuditingActionEnum auditAction, String comment) {
142                 if (roles != null && roles.isEmpty()) {
143                         roles.add(Role.ADMIN);
144                         roles.add(Role.DESIGNER);
145                 }
146                 Either<Boolean, ResponseFormat> validationResult = validateUserRole(user, roles);
147                 if (validationResult.isRight()) {
148                         ComponentTypeEnum componentType = component.getComponentType();
149                         EnumMap<AuditingFieldsKeysEnum, Object> additionalParams = new EnumMap<>(AuditingFieldsKeysEnum.class);
150                         if (componentType.equals(ComponentTypeEnum.SERVICE)) {
151                                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_COMMENT, comment);
152                                 String distributionStatus = ((ServiceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition()).getDistributionStatus();
153                                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_DPREV_STATUS, distributionStatus);
154                                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_DCURR_STATUS, distributionStatus);
155                         }
156                         componentsUtils.auditComponent(validationResult.right().value(), user, component, "", "", auditAction, componentType, additionalParams);
157                 }
158                 return validationResult;
159         }
160
161         protected Either<Boolean, ResponseFormat> validateComponentName(User user, Component component, AuditingActionEnum actionEnum) {
162                 ComponentTypeEnum type = component.getComponentType();
163                 String componentName = component.getName();
164                 if (!ValidationUtils.validateStringNotEmpty(componentName)) {
165                         log.debug("component name is empty");
166                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.MISSING_COMPONENT_NAME, type.getValue());
167                         componentsUtils.auditComponentAdmin(errorResponse, user, component, "", "", actionEnum, type);
168                         return Either.right(errorResponse);
169                 }
170
171                 if (!ValidationUtils.validateComponentNameLength(componentName)) {
172                         log.debug("Component name exceeds max length {} ", ValidationUtils.COMPONENT_NAME_MAX_LENGTH);
173                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_NAME_EXCEEDS_LIMIT, type.getValue(), "" + ValidationUtils.COMPONENT_NAME_MAX_LENGTH);
174                         componentsUtils.auditComponentAdmin(errorResponse, user, component, "", "", actionEnum, type);
175                         return Either.right(errorResponse);
176                 }
177
178                 if (!validateTagPattern(componentName)) {
179                         log.debug("Component name {} has invalid format", componentName);
180                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_COMPONENT_NAME, type.getValue());
181                         componentsUtils.auditComponentAdmin(errorResponse, user, component, "", "", actionEnum, type);
182                         return Either.right(errorResponse);
183                 }
184                 component.setNormalizedName(ValidationUtils.normaliseComponentName(componentName));
185                 component.setSystemName(ValidationUtils.convertToSystemName(componentName));
186
187                 return Either.left(true);
188         }
189
190         protected Either<Boolean, ResponseFormat> validateDescriptionAndCleanup(User user, Component component, AuditingActionEnum actionEnum) {
191                 ComponentTypeEnum type = component.getComponentType();
192                 String description = component.getDescription();
193                 if (!ValidationUtils.validateStringNotEmpty(description)) {
194                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_DESCRIPTION, type.getValue());
195                         componentsUtils.auditComponentAdmin(errorResponse, user, component, "", "", actionEnum, type);
196                         return Either.right(errorResponse);
197                 }
198
199                 description = ValidationUtils.removeNoneUtf8Chars(description);
200                 description = ValidationUtils.normaliseWhitespace(description);
201                 description = ValidationUtils.stripOctets(description);
202                 description = ValidationUtils.removeHtmlTagsOnly(description);
203
204                 Either<Boolean, ResponseFormat> validatDescription = validateComponentDescription(description, type);
205                 if (validatDescription.isRight()) {
206                         ResponseFormat responseFormat = validatDescription.right().value();
207                         componentsUtils.auditComponentAdmin(responseFormat, user, component, "", "", actionEnum, type);
208                         return Either.right(responseFormat);
209                 }
210                 component.setDescription(description);
211                 return Either.left(true);
212         }
213
214         public Either<Boolean, ResponseFormat> validateComponentDescription(String description, ComponentTypeEnum type) {
215                 if (description != null) {
216                         if (!ValidationUtils.validateDescriptionLength(description)) {
217                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_DESCRIPTION_EXCEEDS_LIMIT, type.getValue(), "" + ValidationUtils.COMPONENT_DESCRIPTION_MAX_LENGTH));
218                         }
219
220                         if (!ValidationUtils.validateIsEnglish(description)) {
221                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INVALID_DESCRIPTION, type.getValue()));
222                         }
223                         return Either.left(true);
224                 }
225                 return Either.left(false);
226         }
227
228         protected Either<Boolean, ResponseFormat> validateComponentNameUnique(User user, Component component, AuditingActionEnum actionEnum) {
229                 ComponentTypeEnum type = component.getComponentType();
230                 ResourceTypeEnum resourceType = null;
231                 if(component instanceof Resource){
232                         resourceType = ((Resource)component).getResourceType();
233                 }
234                 Either<Boolean, StorageOperationStatus> dataModelResponse = toscaOperationFacade.validateComponentNameExists(component.getName(), resourceType, type);
235
236                 if (dataModelResponse.isLeft()) {
237                         if ( !dataModelResponse.left().value()) {
238                                 return Either.left(true);
239                         } else {
240                                 log.info("Component with name {} already exists", component.getName());
241                                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, type.getValue(), component.getName());
242                                 componentsUtils.auditComponentAdmin(errorResponse, user, component, "", "", actionEnum, type);
243                                 return Either.right(errorResponse);
244                         }
245                 }
246                 BeEcompErrorManager.getInstance().logBeSystemError("validateComponentNameUnique");
247                 log.debug("Error while validateComponentNameUnique for component: {}", component.getName());
248                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
249                 componentsUtils.auditComponentAdmin(errorResponse, user, component, "", "", actionEnum, type);
250                 return Either.right(errorResponse);
251         }
252
253         protected Either<Boolean, ResponseFormat> validateContactId(User user, Component component, AuditingActionEnum actionEnum) {
254                 log.debug("validate component contactId");
255                 ComponentTypeEnum type = component.getComponentType();
256                 String contactId = component.getContactId();
257
258                 if (!ValidationUtils.validateStringNotEmpty(contactId)) {
259                         log.info("contact is missing.");
260                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_CONTACT, type.getValue());
261                         componentsUtils.auditComponentAdmin(errorResponse, user, component, "", "", actionEnum, type);
262                         return Either.right(errorResponse);
263                 }
264
265                 Either<Boolean, ResponseFormat> validateContactIdResponse = validateContactId(contactId, type);
266                 if (validateContactIdResponse.isRight()) {
267                         ResponseFormat responseFormat = validateContactIdResponse.right().value();
268                         componentsUtils.auditComponentAdmin(responseFormat, user, component, "", "", actionEnum, type);
269                 }
270                 return validateContactIdResponse;
271         }
272
273         private Either<Boolean, ResponseFormat> validateContactId(String contactId, ComponentTypeEnum type) {
274                 if (contactId != null) {
275                         if (!ValidationUtils.validateContactId(contactId)) {
276                                 log.info("contact is invalid.");
277                                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INVALID_CONTACT, type.getValue());
278                                 return Either.right(errorResponse);
279                         }
280                         return Either.left(true);
281                 }
282                 return Either.left(false);
283         }
284
285         
286         public Either<Boolean, ResponseFormat> validateConformanceLevel(String componentId, ComponentTypeEnum componentTypeEnum, String userId) {
287                 log.trace("validate conformance level");
288                 
289                 if (componentTypeEnum != ComponentTypeEnum.SERVICE) {
290                         log.error("conformance level validation for non service component, id {}", componentId);
291                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
292                         return Either.right(errorResponse);
293                 }
294                 
295                 Either<User, ResponseFormat> resp = validateUserExists(userId, "validateConformanceLevel", false);
296                 if (resp.isRight()) {
297                         log.error("can't validate conformance level, user is not validated, id {}, userId {}", componentId, userId);
298                         return Either.right(resp.right().value());
299                 }
300                 
301                 ComponentParametersView filter = new ComponentParametersView(true);
302                 Either<Component, ResponseFormat> eitherComponent = validateComponentExists(componentId, componentTypeEnum, filter);
303                 if (eitherComponent.isRight()) {
304                         log.error("can't validate conformance level, component not found, id {}", componentId);
305                         BeEcompErrorManager.getInstance().logBeComponentMissingError("validateConformanceLevel", componentTypeEnum.getValue(), componentId);
306                         return Either.right(eitherComponent.right().value());
307                 }
308                 
309                 Component component = eitherComponent.left().value();
310                 if (component.getConformanceLevel() == null || "".equals(component.getConformanceLevel())) {
311                         log.error("component conformance level property is null or empty, id {}", componentId);
312                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
313                         return Either.right(errorResponse);
314                 }
315                 
316                 String configConformanceLevel = ConfigurationManager.getConfigurationManager().getConfiguration().getMinToscaConformanceLevel();
317                 Boolean result = true;
318                 if (CommonBeUtils.conformanceLevelCompare(component.getConformanceLevel(), configConformanceLevel) < 0) {
319                         log.error("invalid asset conformance level, id {}, asset conformanceLevel {}, config conformanceLevel {}", componentId, component.getConformanceLevel(), configConformanceLevel);
320                         result = false;
321                 }
322                 log.trace("conformance level validation finished");
323                 
324                 return Either.left(result);
325         }
326         
327         protected Either<Boolean, ResponseFormat> validateIcon(User user, Component component, AuditingActionEnum actionEnum) {
328                 log.debug("validate Icon");
329                 ComponentTypeEnum type = component.getComponentType();
330                 String icon = component.getIcon();
331                 if (!ValidationUtils.validateStringNotEmpty(icon)) {
332                         log.info("icon is missing.");
333                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_ICON, type.getValue());
334                         componentsUtils.auditComponentAdmin(errorResponse, user, component, "", "", actionEnum, type);
335                         return Either.right(errorResponse);
336                 }
337
338                 Either<Boolean, ResponseFormat> validateIcon = validateIcon(icon, type);
339                 if (validateIcon.isRight()) {
340                         ResponseFormat responseFormat = validateIcon.right().value();
341                         componentsUtils.auditComponentAdmin(responseFormat, user, component, "", "", actionEnum, type);
342                 }
343                 return validateIcon;
344         }
345
346         private Either<Boolean, ResponseFormat> validateIcon(String icon, ComponentTypeEnum type) {
347                 if (icon != null) {
348                         if (!ValidationUtils.validateIconLength(icon)) {
349                                 log.debug("icon exceeds max length");
350                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ICON_EXCEEDS_LIMIT, type.getValue(), "" + ValidationUtils.ICON_MAX_LENGTH));
351                         }
352
353                         if (!ValidationUtils.validateIcon(icon)) {
354                                 log.info("icon is invalid.");
355                                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INVALID_ICON, type.getValue());
356                                 return Either.right(errorResponse);
357                         }
358                         return Either.left(true);
359                 }
360                 return Either.left(false);
361         }
362
363         protected Either<Boolean, ResponseFormat> validateTagsListAndRemoveDuplicates(User user, Component component, AuditingActionEnum actionEnum) {
364                 List<String> tagsList = component.getTags();
365
366                 Either<Boolean, ResponseFormat> validateTags = validateComponentTags(tagsList, component.getName(), component.getComponentType());
367                 if (validateTags.isRight()) {
368                         ResponseFormat responseFormat = validateTags.right().value();
369                         componentsUtils.auditComponentAdmin(responseFormat, user, component, "", "", actionEnum, component.getComponentType());
370                         return Either.right(responseFormat);
371                 }
372                 ValidationUtils.removeDuplicateFromList(tagsList);
373                 return Either.left(true);
374         }
375
376         protected Either<Boolean, ResponseFormat> validateComponentTags(List<String> tags, String name, ComponentTypeEnum componentType) {
377                 log.debug("validate component tags");
378                 boolean includesComponentName = false;
379                 int tagListSize = 0;
380                 if (tags != null && !tags.isEmpty()) {
381                         for (String tag : tags) {
382                                 if (!ValidationUtils.validateTagLength(tag)) {
383                                         log.debug("tag length exceeds limit {}", ValidationUtils.TAG_MAX_LENGTH);
384                                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SINGLE_TAG_EXCEED_LIMIT, "" + ValidationUtils.TAG_MAX_LENGTH));
385                                 }
386                                 if (validateTagPattern(tag)) {
387                                         if (!includesComponentName) {
388                                                 includesComponentName = name.equals(tag);
389                                         }
390                                 } else {
391                                         log.debug("invalid tag {}", tag);
392                                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FIELD_FORMAT, componentType.getValue(), TAG_FIELD_LABEL));
393                                 }
394                                 tagListSize += tag.length() + 1;
395                         }
396                         if (tagListSize > 0) {
397                                 tagListSize--;
398                         }
399
400                         if (!includesComponentName) {
401                                 log.debug("tags must include component name");
402                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INVALID_TAGS_NO_COMP_NAME));
403                         }
404                         if (!ValidationUtils.validateTagListLength(tagListSize)) {
405                                 log.debug("overall tags length exceeds limit {}", ValidationUtils.TAG_LIST_MAX_LENGTH);
406                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_TAGS_EXCEED_LIMIT, "" + ValidationUtils.TAG_LIST_MAX_LENGTH));
407                         }
408                         return Either.left(true);
409                 }
410                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_TAGS));
411         }
412
413         protected boolean validateTagPattern(String tag) {
414                 return ValidationUtils.validateComponentNamePattern(tag);
415         }
416
417         protected Either<Boolean, ResponseFormat> validateProjectCode(User user, Component component, AuditingActionEnum actionEnum) {
418                 if (ComponentTypeEnum.RESOURCE.equals(component.getComponentType())) {
419                         return Either.left(true);
420                 }
421                 log.debug("validate ProjectCode name ");
422                 String projectCode = component.getProjectCode();
423
424                 if (!ValidationUtils.validateStringNotEmpty(projectCode)) {
425                         log.info("projectCode is missing.");
426                         ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.MISSING_PROJECT_CODE);
427                         componentsUtils.auditComponentAdmin(errorResponse, user, component, "", "", actionEnum, component.getComponentType());
428                         return Either.right(errorResponse);
429                 }
430
431                 Either<Boolean, ResponseFormat> validateProjectCodeResponse = validateProjectCode(projectCode);
432                 if (validateProjectCodeResponse.isRight()) {
433                         ResponseFormat responseFormat = validateProjectCodeResponse.right().value();
434                         componentsUtils.auditComponentAdmin(responseFormat, user, component, "", "", actionEnum, component.getComponentType());
435                 }
436                 return validateProjectCodeResponse;
437
438         }
439
440         private Either<Boolean, ResponseFormat> validateProjectCode(String projectCode) {
441                 if (projectCode != null) {
442                         if (!ValidationUtils.validateProjectCode(projectCode)) {
443                                 log.info("projectCode  is not valid.");
444                                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_PROJECT_CODE);
445                                 return Either.right(errorResponse);
446                         }
447                         return Either.left(true);
448                 }
449                 return Either.left(false);
450         }
451
452         protected void checkComponentFieldsForOverrideAttempt(Component component) {
453                 if (component.getLifecycleState() != null) {
454                         log.info("LifecycleState cannot be defined by user. This field will be overridden by the application");
455                 }
456                 if (component.getVersion() != null) {
457                         log.info("Version cannot be defined by user. This field will be overridden by the application");
458                 }
459                 if ((component.getCreatorUserId() != null) || (component.getCreatorFullName() != null)) {
460                         log.info("Creator cannot be defined by user. This field will be overridden by the application");
461                 }
462                 if ((component.getLastUpdaterUserId() != null) || (component.getLastUpdaterFullName() != null)) {
463                         log.info("Last Updater cannot be defined by user. This field will be overridden by the application");
464                 }
465                 if ((component.getCreationDate() != null)) {
466                         log.info("Creation Date cannot be defined by user. This field will be overridden by the application");
467                 }
468                 if ((component.isHighestVersion() != null)) {
469                         log.info("Is Highest Version cannot be defined by user. This field will be overridden by the application");
470                 }
471                 if ((component.getUUID() != null)) {
472                         log.info("UUID cannot be defined by user. This field will be overridden by the application");
473                 }
474                 if ((component.getLastUpdateDate() != null)) {
475                         log.info("Last Update Date cannot be defined by user. This field will be overridden by the application");
476                 }
477                 if (component.getUniqueId() != null) {
478                         log.info("uid cannot be defined by user. This field will be overridden by the application.");
479                         component.setUniqueId(null);
480                 }
481                 if (component.getInvariantUUID() != null) {
482                         log.info("Invariant UUID cannot be defined by user. This field will be overridden by the application.");
483                 }
484         }
485
486         protected Either<Boolean, ResponseFormat> validateComponentFieldsBeforeCreate(User user, Component component, AuditingActionEnum actionEnum) {
487                 // validate component name uniqueness
488                 log.debug("validate component name ");
489                 Either<Boolean, ResponseFormat> componentNameValidation = validateComponentName(user, component, actionEnum);
490                 if (componentNameValidation.isRight()) {
491                         return componentNameValidation;
492                 }
493
494                 // validate description
495                 log.debug("validate description");
496                 Either<Boolean, ResponseFormat> descValidation = validateDescriptionAndCleanup(user, component, actionEnum);
497                 if (descValidation.isRight()) {
498                         return descValidation;
499                 }
500
501                 // validate tags
502                 log.debug("validate tags");
503                 Either<Boolean, ResponseFormat> tagsValidation = validateTagsListAndRemoveDuplicates(user, component, actionEnum);
504                 if (tagsValidation.isRight()) {
505                         return tagsValidation;
506                 }
507
508                 // validate contact info
509                 log.debug("validate contact info");
510                 Either<Boolean, ResponseFormat> contactIdValidation = validateContactId(user, component, actionEnum);
511                 if (contactIdValidation.isRight()) {
512                         return contactIdValidation;
513                 }
514
515                 // validate icon
516                 log.debug("validate icon");
517                 Either<Boolean, ResponseFormat> iconValidation = validateIcon(user, component, actionEnum);
518                 if (iconValidation.isRight()) {
519                         return iconValidation;
520                 }
521                 return Either.left(true);
522         }
523
524         /***
525          * Fetches Component From the DB
526          * 
527          * @param componentId
528          * @param componentTypeEnum
529          * @return
530          */
531         public <R extends Component> Either<R, StorageOperationStatus> getComponent(String componentId, ComponentTypeEnum componentTypeEnum) {
532                 return toscaOperationFacade.getToscaElement(componentId);
533         }
534
535         public Either<CapReqDef, ResponseFormat> getRequirementsAndCapabilities(String componentId, ComponentTypeEnum componentTypeEnum, String userId) {
536
537                 Either<User, ResponseFormat> resp = validateUserExists(userId, "create Component Instance", false);
538                 if (resp.isRight()) {
539                         return Either.right(resp.right().value());
540                 }
541                 Either<CapReqDef, ResponseFormat> eitherRet = null;
542                 ComponentParametersView filter = new ComponentParametersView(true);
543                 filter.setIgnoreCapabilities(false);
544                 filter.setIgnoreRequirements(false);
545                 filter.setIgnoreComponentInstances(false);
546                 Either<Component, ResponseFormat> eitherComponent = validateComponentExists(componentId, componentTypeEnum, filter);
547                 if (eitherComponent.isLeft()) {
548                         eitherRet = Either.left(new CapReqDef(eitherComponent.left().value().getRequirements(), eitherComponent.left().value().getCapabilities()));
549                 } else {
550                         BeEcompErrorManager.getInstance().logBeComponentMissingError("getRequirementsAndCapabilities", componentTypeEnum.getValue(), componentId);
551                         eitherRet = Either.right(eitherComponent.right().value());
552                 }
553                 return eitherRet;
554         }
555
556         public Either<List<Component>, ResponseFormat> getLatestVersionNotAbstractComponents(boolean isAbstractAbstract, HighestFilterEnum highestFilter, ComponentTypeEnum componentTypeEnum, String internalComponentType, List<String> componentUids,
557                         String userId) {
558                 ResponseFormat responseFormat = null;
559                 try{
560                         Either<User, ResponseFormat> resp = validateUserExists(userId, "get Latest Version Not Abstract Components", false);
561                         
562                         if (resp.isLeft()) {
563                                 List<Component> result = new ArrayList<>();
564                                 List<String> componentsUidToFetch = new ArrayList<>();
565                                 componentsUidToFetch.addAll(componentUids);
566         
567                                 if (componentsUidToFetch.size() > 0) {
568                                         log.debug("Number of Components to fetch from graph is {}", componentsUidToFetch.size());
569                                         Boolean isHighest = isHighest(highestFilter);
570                                         Either<List<Component>, StorageOperationStatus> nonCheckoutCompResponse = toscaOperationFacade.getLatestVersionNotAbstractComponents(isAbstractAbstract, isHighest, componentTypeEnum, internalComponentType, componentsUidToFetch);
571         
572                                         if (nonCheckoutCompResponse.isLeft()) {
573                                                 log.debug("Retrived Resource successfully.");
574                                                 result.addAll(nonCheckoutCompResponse.left().value());
575                                         } else {
576                                                 responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(nonCheckoutCompResponse.right().value()));
577                                         }
578                                 }
579                                 return Either.left(result);
580                         } else {
581                                 responseFormat = resp.right().value();
582                         }
583                 }
584                 finally{
585                         titanDao.commit();
586                 }
587                 return Either.right(responseFormat);
588         }
589
590         private Boolean isHighest(HighestFilterEnum highestFilter) {
591                 Boolean isHighest = null;
592                 switch (highestFilter) {
593                 case ALL:
594                         break;
595                 case HIGHEST_ONLY:
596                         isHighest = true;
597                         break;
598                 case NON_HIGHEST_ONLY:
599                         isHighest = false;
600                         break;
601                 default:
602                         break;
603                 }
604                 return isHighest;
605         }
606
607         public Either<List<Component>, ResponseFormat> getLatestVersionNotAbstractComponentsMetadata(boolean isAbstractAbstract, HighestFilterEnum highestFilter, ComponentTypeEnum componentTypeEnum, String internalComponentType, String userId) {
608                 ResponseFormat responseFormat = null;
609
610                 try{
611                         Either<User, ResponseFormat> resp = validateUserExists(userId, "get Latest Version Not Abstract Components", false);
612                         if (resp.isLeft()) {
613         
614                                 Boolean isHighest = isHighest(highestFilter);
615                                 Either<List<Component>, StorageOperationStatus> nonCheckoutCompResponse = toscaOperationFacade.getLatestVersionNotAbstractMetadataOnly(isAbstractAbstract, isHighest, componentTypeEnum, internalComponentType);
616
617                                 if (nonCheckoutCompResponse.isLeft()) {
618                                         log.debug("Retrived Resource successfully.");
619                                         return Either.left(nonCheckoutCompResponse.left().value());
620                                 }
621                                 responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(nonCheckoutCompResponse.right().value()));
622                         } else {
623                                 responseFormat = resp.right().value();
624                         }
625                 } finally {
626                         titanDao.commit();
627                 }
628                 return Either.right(responseFormat);
629         }
630
631         public void setDeploymentArtifactsPlaceHolder(Component component, User user) {
632
633         }
634
635         @SuppressWarnings("unchecked")
636         public void setToscaArtifactsPlaceHolders(Component component, User user) {
637                 Map<String, ArtifactDefinition> artifactMap = component.getToscaArtifacts();
638                 if (artifactMap == null) {
639                         artifactMap = new HashMap<String, ArtifactDefinition>();
640                 }
641                 String componentUniqueId = component.getUniqueId();
642                 String componentSystemName = component.getSystemName();
643                 String componentType = component.getComponentType().getValue().toLowerCase();
644                 Map<String, Object> toscaArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration().getToscaArtifacts();
645
646                 if (toscaArtifacts != null) {
647                         for (Entry<String, Object> artifactInfoMap : toscaArtifacts.entrySet()) {
648                                 Map<String, Object> artifactInfo = (Map<String, Object>) artifactInfoMap.getValue();
649                                 ArtifactDefinition artifactDefinition = artifactsBusinessLogic.createArtifactPlaceHolderInfo(componentUniqueId, artifactInfoMap.getKey(), artifactInfo, user, ArtifactGroupTypeEnum.TOSCA);
650                                 artifactDefinition.setArtifactName(componentType + "-" + componentSystemName + artifactInfo.get("artifactName"));
651                                 artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition);
652                         }
653                 }
654                 component.setToscaArtifacts(artifactMap);
655         }
656
657         public Either<Either<ArtifactDefinition, Operation>, ResponseFormat> populateToscaArtifacts(Component component, User user, boolean isInCertificationRequest, boolean inTransaction, boolean shouldLock) {
658                 return populateToscaArtifacts(component, user, isInCertificationRequest, inTransaction, shouldLock, true);
659         }
660
661         public Either<Either<ArtifactDefinition, Operation>, ResponseFormat> populateToscaArtifacts(Component component, User user, boolean isInCertificationRequest, boolean inTransaction, boolean shouldLock, boolean fetchTemplatesFromDB) {
662                 Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade.getToscaFullElement(component.getUniqueId());
663                 if ( toscaElement.isRight() ){
664                         ResponseFormat response = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(toscaElement.right().value(), component.getComponentType()));
665                         return Either.right(response);
666                 }
667                 component = toscaElement.left().value();
668                 Either<Either<ArtifactDefinition, Operation>, ResponseFormat> generateToscaRes = null;
669                 if (component.getToscaArtifacts() != null && !component.getToscaArtifacts().isEmpty()) {
670                         ArtifactDefinition toscaArtifact = component.getToscaArtifacts().values().stream()
671                                         .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.TOSCA_TEMPLATE.getType()))
672                                         .findAny().get();
673                         generateToscaRes = saveToscaArtifactPayload(toscaArtifact, component, user, isInCertificationRequest, shouldLock, inTransaction, fetchTemplatesFromDB);
674                         if (generateToscaRes.isRight()) {
675                                 return generateToscaRes;
676                         }
677                         toscaArtifact = generateToscaRes.left().value().left().value();
678                         component.getToscaArtifacts().put(toscaArtifact.getArtifactLabel(), toscaArtifact);
679                         toscaArtifact = component.getToscaArtifacts().values().stream()
680                                         .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.TOSCA_CSAR.getType()))
681                                         .findAny().get();
682                         generateToscaRes = saveToscaArtifactPayload(toscaArtifact, component, user, isInCertificationRequest, shouldLock, inTransaction, true);
683                 }
684                 if (generateToscaRes.isRight()) {
685                         return generateToscaRes;
686                 }
687                 ArtifactDefinition toscaArtifact = generateToscaRes.left().value().left().value();
688                 component.getToscaArtifacts().put(toscaArtifact.getArtifactLabel(), toscaArtifact);
689                 return generateToscaRes;
690         }
691
692         public Either<Either<ArtifactDefinition, Operation>, ResponseFormat> saveToscaArtifactPayload(ArtifactDefinition artifactDefinition, org.openecomp.sdc.be.model.Component component, User user, boolean isInCertificationRequest, boolean shouldLock,
693                         boolean inTransaction, boolean fetchTemplatesFromDB) {
694                 return artifactsBusinessLogic.generateAndSaveToscaArtifact(artifactDefinition, component, user, isInCertificationRequest, shouldLock, inTransaction, fetchTemplatesFromDB);
695         }
696
697         public Either<ImmutablePair<String, byte[]>, ResponseFormat> getToscaModelByComponentUuid(ComponentTypeEnum componentType, String uuid, EnumMap<AuditingFieldsKeysEnum, Object> additionalParam) {
698                 
699                 Either<List<Component>, StorageOperationStatus> latestVersionEither = toscaOperationFacade.getComponentListByUuid(uuid, null);
700                 
701                 if (latestVersionEither.isRight()) {
702                         ResponseFormat response = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(latestVersionEither.right().value(), componentType));
703                         return Either.right(response);
704                 }
705                 
706                 List<Component> components = latestVersionEither.left().value();
707                 
708                 Component component = components.stream().filter(c -> c.isHighestVersion()).findFirst().orElse(null);
709                 if(component == null){
710                         component = components.stream().filter(c -> c.getLifecycleState() == LifecycleStateEnum.CERTIFIED).findFirst().orElse(null);
711                 }
712                 
713                 if(component == null){
714                         ResponseFormat response = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND, componentType));
715                         return Either.right(response);
716                 }
717                 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName());
718                 // TODO remove after migration - handle artifact not found(no
719                 // placeholder)
720                 if (null == component.getToscaArtifacts() || component.getToscaArtifacts().isEmpty()) {
721                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND, ArtifactTypeEnum.TOSCA_CSAR.name()));
722                 }
723                 ArtifactDefinition csarArtifact = component.getToscaArtifacts().values().stream()
724                                 .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.TOSCA_CSAR.getType()))
725                                 .findAny().get();
726                 return artifactsBusinessLogic.handleDownloadToscaModelRequest(component, csarArtifact);
727         }
728
729         protected StorageOperationStatus markComponentToDelete(Component component) {
730
731                 ComponentTypeEnum componentType = component.getComponentType();
732                 String uniqueId = component.getUniqueId();
733                 if ((component.getIsDeleted() != null) && (component.getIsDeleted() == true)) {
734                         log.info("component {} already marked as deleted. id= {}, type={}", component.getName(), uniqueId, componentType);
735                         return StorageOperationStatus.NOT_FOUND;
736                 }
737
738                 StorageOperationStatus markResourceToDelete = toscaOperationFacade.markComponentToDelete(component);
739                 if (StorageOperationStatus.OK != markResourceToDelete) {
740                         log.debug("failed to mark component {} of type {} for delete. error = {}", uniqueId, componentType, markResourceToDelete);
741                         return markResourceToDelete;
742                 } else {
743                         log.debug("Component {}  of type {} was marked as deleted", uniqueId, componentType);
744                         return StorageOperationStatus.OK;
745                 }
746         }
747
748         public Either<Boolean, ResponseFormat> validateAndUpdateDescription(User user, Component currentComponent, Component updatedComponent, AuditingActionEnum audatingAction) {
749                 String descriptionUpdated = updatedComponent.getDescription();
750                 String descriptionCurrent = currentComponent.getDescription();
751                 if (descriptionUpdated != null && !descriptionCurrent.equals(descriptionUpdated)) {
752                         Either<Boolean, ResponseFormat> validateDescriptionResponse = validateDescriptionAndCleanup(user, updatedComponent, audatingAction);
753                         if (validateDescriptionResponse.isRight()) {
754                                 ResponseFormat errorRespons = validateDescriptionResponse.right().value();
755                                 return Either.right(errorRespons);
756                         }
757                         currentComponent.setDescription(updatedComponent.getDescription());
758                 }
759                 return Either.left(true);
760         }
761
762         public Either<Boolean, ResponseFormat> validateAndUpdateProjectCode(User user, Component currentComponent, Component updatedComponent) {
763                 String projectCodeUpdated = updatedComponent.getProjectCode();
764                 String projectCodeCurrent = currentComponent.getProjectCode();
765                 if (projectCodeUpdated != null && !projectCodeCurrent.equals(projectCodeUpdated)) {
766                         Either<Boolean, ResponseFormat> validatProjectCodeResponse = validateProjectCode(user, updatedComponent, null);
767                         if (validatProjectCodeResponse.isRight()) {
768                                 ResponseFormat errorRespons = validatProjectCodeResponse.right().value();
769                                 return Either.right(errorRespons);
770                         }
771                         currentComponent.setProjectCode(updatedComponent.getProjectCode());
772                 }
773                 return Either.left(true);
774         }
775
776         public Either<Boolean, ResponseFormat> validateAndUpdateIcon(User user, Component currentComponent, Component updatedComponent, boolean hasBeenCertified) {
777                 String iconUpdated = updatedComponent.getIcon();
778                 String iconCurrent = currentComponent.getIcon();
779                 if (iconUpdated != null && !iconCurrent.equals(iconUpdated)) {
780                         if (!hasBeenCertified) {
781                                 Either<Boolean, ResponseFormat> validatIconResponse = validateIcon(user, updatedComponent, null);
782                                 if (validatIconResponse.isRight()) {
783                                         ResponseFormat errorRespons = validatIconResponse.right().value();
784                                         return Either.right(errorRespons);
785                                 }
786                                 currentComponent.setIcon(updatedComponent.getIcon());
787                         } else {
788                                 log.info("icon {} cannot be updated once the component has been certified once.", iconUpdated);
789                                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_PARAMETER_CANNOT_BE_CHANGED, "Icon", currentComponent.getComponentType().name().toLowerCase());
790                                 return Either.right(errorResponse);
791                         }
792                 }
793                 return Either.left(true);
794         }
795
796         protected Either<List<String>, ResponseFormat> deleteMarkedComponents(ComponentTypeEnum componentType) {
797
798 //              List<String> deletedComponents = new ArrayList<String>();
799                 log.trace("start deleteMarkedComponents");
800                 Either<List<String>, StorageOperationStatus> deleteMarkedElements = toscaOperationFacade.deleteMarkedElements(componentType);
801                 
802                 titanDao.commit();
803                 if ( deleteMarkedElements.isRight()){
804                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteMarkedElements.right().value(), componentType));
805                         return Either.right(responseFormat);
806                 }
807 //              ComponentOperation componentOperation = getComponentOperation(componentType);
808 //              Either<List<String>, StorageOperationStatus> resourcesToDelete = componentOperation.getAllComponentsMarkedForDeletion();
809 //              if (resourcesToDelete.isRight()) {
810 //                      ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resourcesToDelete.right().value(), componentType));
811 //                      return Either.right(responseFormat);
812 //              }
813 //
814 //              for (String resourceToDelete : resourcesToDelete.left().value()) {
815 //
816 //                      Either<String, ResponseFormat> deleteMarkedResource = deleteMarkedComponent(resourceToDelete, componentType);
817 //                      if (deleteMarkedResource.isLeft()) {
818 //                              deletedComponents.add(deleteMarkedResource.left().value());
819 //                      }
820 //              }
821 //              if(deletedComponents.size() == 0) {
822 //                      log.debug("Component list to delete is empty. do commit");
823 //                      titanGenericDao.commit();
824 //              }
825                 log.trace("end deleteMarkedComponents");
826                 return Either.left(deleteMarkedElements.left().value());
827         }
828
829         private Either<String, ResponseFormat> deleteMarkedComponent(String componentToDelete, ComponentTypeEnum componentType) {
830
831                 Either<String, ResponseFormat> result = null;
832                 NodeTypeEnum compNodeType = componentType.getNodeType();
833                 StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentToDelete, compNodeType);
834                 if (!lockResult.equals(StorageOperationStatus.OK)) {
835                         BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeFailedLockObjectError, "Delete marked component");
836                         log.debug("Failed to lock component {} error - {}", componentToDelete, lockResult);
837                         result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
838                         return result;
839                 }
840                 try {
841
842                         // check if resource has relations
843                         Either<Boolean, StorageOperationStatus> isResourceInUse = toscaOperationFacade.isComponentInUse(componentToDelete);
844                         if (isResourceInUse.isRight()) {
845                                 log.info("deleteMarkedResource - failed to find relations to resource. id = {}, type = {}, error = {}", componentToDelete, componentType, isResourceInUse.right().value().name());
846                                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
847                                 result = Either.right(responseFormat);
848                                 return result;
849                         }
850
851                         if (isResourceInUse.isLeft() && isResourceInUse.left().value() == false) {
852
853                                 // delete resource and its artifacts in one transaction
854                                 Either<List<ArtifactDefinition>, StorageOperationStatus> artifactsRes = getComponentArtifactsForDelete(componentToDelete, compNodeType, true);
855                                 if (artifactsRes.isRight() && !artifactsRes.right().value().equals(StorageOperationStatus.NOT_FOUND)) {
856                                         log.info("failed to check artifacts for component node. id = {}, type = {}, error = {}", componentToDelete, componentType, artifactsRes.right().value().name());
857                                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
858                                         result = Either.right(responseFormat);
859                                         return result;
860                                 }
861                                 List<ArtifactDefinition> artifactsToDelete = new ArrayList<>();
862                                 if (artifactsRes.isLeft()) {
863                                         artifactsToDelete = artifactsRes.left().value();
864                                 }
865                                 
866                                 Either<Component, StorageOperationStatus> deleteComponentRes = toscaOperationFacade.deleteToscaComponent(componentToDelete);
867                                 if (deleteComponentRes.isRight()) {
868                                         log.info("failed to delete component. id = {}, type = {}, error = {}", componentToDelete, componentType, deleteComponentRes.right().value().name());
869                                         ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(deleteComponentRes.right().value());
870                                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(actionStatus, componentToDelete);
871                                         result = Either.right(responseFormat);
872                                 } else {
873                                         log.trace("component was deleted, id = {}, type = {}", componentToDelete, componentType);
874                                         // delete related artifacts
875                                         StorageOperationStatus deleteFromEsRes = artifactsBusinessLogic.deleteAllComponentArtifactsIfNotOnGraph(artifactsToDelete);
876                                         if (!deleteFromEsRes.equals(StorageOperationStatus.OK)) {
877                                                 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(deleteFromEsRes);
878                                                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(actionStatus, componentToDelete);
879                                                 result = Either.right(responseFormat);
880                                                 return result;
881                                         }
882                                         log.debug("component and all its artifacts were deleted, id = {}, type = {}", componentToDelete, componentType);
883                                         result = Either.left(componentToDelete);
884                                 }
885                         } else {
886                                 // resource in use
887                                 log.debug("componentis marked for delete but still in use, id = {}, type = {}", componentToDelete, componentType);
888                                 ActionStatus actionStatus = ActionStatus.RESTRICTED_OPERATION;
889                                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(actionStatus, componentToDelete);
890                                 result = Either.right(responseFormat);
891                                 return result;
892                         }
893                 } finally {
894                         if (result == null || result.isRight()) {
895                                 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, "delete marked component");
896                                 log.debug("operation failed. do rollback");
897                                 titanDao.rollback();
898                         } else {
899                                 log.debug("operation success. do commit");
900                                 titanDao.commit();
901                         }
902                         graphLockOperation.unlockComponent(componentToDelete, compNodeType);
903                 }
904
905                 return result;
906         }
907         
908         public Either<List<ArtifactDefinition>, StorageOperationStatus> getComponentArtifactsForDelete(String parentId, NodeTypeEnum parentType, boolean inTransacton) {
909                 List<ArtifactDefinition> artifacts = new ArrayList<ArtifactDefinition>();
910                 Either<Map<String, ArtifactDefinition>, StorageOperationStatus> artifactsResponse = artifactToscaOperation.getArtifacts(parentId);
911                 if (artifactsResponse.isRight()) {
912                         if (!artifactsResponse.right().value().equals(StorageOperationStatus.NOT_FOUND)) {
913                                 log.debug("failed to retrieve artifacts for {} {}", parentType, parentId);
914                                 return Either.right(artifactsResponse.right().value());
915                         }
916                 } else {
917                         artifacts.addAll(artifactsResponse.left().value().values());
918                 }
919
920 //              if (NodeTypeEnum.Resource.equals(parentType)) {
921 //                      Either<List<ArtifactDefinition>, StorageOperationStatus> interfacesArtifactsForResource = getAdditionalArtifacts(parentId, false, true);
922 //                      if (artifactsResponse.isRight() && !interfacesArtifactsForResource.right().value().equals(StorageOperationStatus.NOT_FOUND)) {
923 //                              log.debug("failed to retrieve interface artifacts for {} {}", parentType, parentId);
924 //                              return Either.right(interfacesArtifactsForResource.right().value());
925 //                      } else if (artifactsResponse.isLeft()) {
926 //                              artifacts.addAll(interfacesArtifactsForResource.left().value());
927 //                      }
928 //              }
929                 return Either.left(artifacts);
930         }
931         
932         /**
933          * 
934          * @param componentId
935          * @param user
936          * @param dataParamsToReturn - ui list of params to return
937          * @return
938          */
939         
940         public Either<UiComponentDataTransfer, ResponseFormat> getComponentDataFilteredByParams(String componentId, User user, List<String> dataParamsToReturn) {
941
942                 if (user != null) {
943                         Either<User, ResponseFormat> eitherCreator = validateUserExists(user, "Get Component by filtered by ui params", false);
944                         if (eitherCreator.isRight()) {
945                                 return Either.right(eitherCreator.right().value());
946                         }
947                 }
948
949                 UiComponentDataTransfer result =  new UiComponentDataTransfer();
950                 
951             if(dataParamsToReturn == null ||  dataParamsToReturn.isEmpty()) {
952                 Either.left(result);
953                 
954             } else {
955                 Either<UiComponentDataTransfer, ResponseFormat> uiDataTransferEither = getUiComponentDataTransferByComponentId(componentId, dataParamsToReturn);
956                 if(uiDataTransferEither.isRight()){
957                         return Either.right(uiDataTransferEither.right().value());
958                 }
959                 result = uiDataTransferEither.left().value();
960             }
961
962             return Either.left(result);
963         }
964         
965         protected <T extends Component> void generateInputsFromGenericTypeProperties(T component, Resource genericType) {
966         
967                 List<PropertyDefinition> genericTypeProps = genericType.getProperties();
968                 if(null != genericTypeProps) {
969                         String genericUniqueId = genericType.getUniqueId();
970                         List<InputDefinition> inputs = convertGenericTypePropertiesToInputsDefintion(genericTypeProps, genericUniqueId);
971                         if(null != component.getInputs())
972                                 inputs.addAll(component.getInputs());
973                         component.setInputs(inputs);
974                 }
975         }
976         
977         private List<InputDefinition> convertGenericTypePropertiesToInputsDefintion(List<PropertyDefinition> genericTypeProps, String genericUniqueId) {
978                 return genericTypeProps.stream()
979                         .map(p -> setInputDefinitionFromProp(p, genericUniqueId))
980                         .collect(Collectors.toList());
981         }
982         
983         private InputDefinition setInputDefinitionFromProp(PropertyDefinition prop, String genericUniqueId){
984                 InputDefinition input = new InputDefinition(prop);
985                 input.setOwnerId(genericUniqueId);
986                 return input;
987         }
988         
989         protected <T extends Component> Either<Resource, ResponseFormat> fetchAndSetDerivedFromGenericType(T component){
990                 
991                 String genericTypeToscaName = component.fetchGenericTypeToscaNameFromConfig();
992                 if(null == genericTypeToscaName)
993                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
994                 Either<Resource, StorageOperationStatus> findLatestGeneric = toscaOperationFacade.getLatestCertifiedNodeTypeByToscaResourceName(genericTypeToscaName);
995                 if(findLatestGeneric.isRight())
996                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERIC_TYPE_NOT_FOUND, component.assetType(), genericTypeToscaName));
997                 Resource genericTypeResource = findLatestGeneric.left().value();
998                 component.setDerivedFromGenericInfo(genericTypeResource);
999                 return Either.left(genericTypeResource);
1000         }
1001
1002         public Either<Map<String, List<IComponentInstanceConnectedElement>>, ResponseFormat> getFilteredComponentInstanceProperties(String componentId, Map<FilterKeyEnum, List<String>> filters, String userId) {
1003                 Either<Map<String, List<IComponentInstanceConnectedElement>>, ResponseFormat> response = null;
1004                 Either<Component, StorageOperationStatus> getResourceRes = null;
1005                 try{
1006                         if(!filters.containsKey(FilterKeyEnum.NAME_FRAGMENT) && StringUtils.isEmpty(filters.get(FilterKeyEnum.NAME_FRAGMENT).get(0))){
1007                                 response = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1008                         }
1009                         if (userId != null && response == null) {
1010                                 Either<User, ResponseFormat> validateUserRes = validateUserExists(userId, "Get filtered component instance properties", false);
1011                                 if (validateUserRes.isRight()) {
1012                                         response = Either.right(validateUserRes.right().value());
1013                                 }
1014                         }
1015                         if(response == null){
1016                                 getResourceRes = toscaOperationFacade.getToscaElement(componentId);
1017                                 if(getResourceRes.isRight()){
1018                                         response = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(getResourceRes.right().value())));
1019                                 }
1020                         }
1021                         if(response == null){
1022                                 response = getFilteredComponentInstancesProperties(getResourceRes.left().value(), filters);
1023                         }
1024                 } catch(Exception e){
1025                         log.debug("The exception {} occured during filtered instance properties fetching. the  containing component is {}. ", e, componentId);
1026                         response = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1027                 } finally{
1028                         if (response.isLeft()){
1029                                 toscaOperationFacade.commit();
1030                         } else {
1031                                 toscaOperationFacade.rollback();
1032                         }
1033                 }
1034                 return response;
1035         }
1036
1037         private Either<Map<String, List<IComponentInstanceConnectedElement>>, ResponseFormat> getFilteredComponentInstancesProperties(Component component, Map<FilterKeyEnum, List<String>> filters) {
1038                 
1039                 Map<String,  List<IComponentInstanceConnectedElement>> filteredProperties = new HashMap<>();
1040                 Either<Map<String, List<IComponentInstanceConnectedElement>>, ResponseFormat> result = Either.left(filteredProperties);
1041                 List<ComponentInstance> filteredInstances = getFilteredInstances(component, filters.get(FilterKeyEnum.RESOURCE_TYPE));
1042                 String propertyNameFragment= filters.get(FilterKeyEnum.NAME_FRAGMENT).get(0);
1043                 boolean searchByFragment = propertyNameFragment.length() > 3 ;
1044                 if(CollectionUtils.isNotEmpty(filteredInstances)){
1045                         for(ComponentInstance instance : filteredInstances){
1046                                 if(component.getComponentInstancesProperties()!=null &&component.getComponentInstancesProperties().containsKey(instance.getUniqueId())){
1047                                         List<IComponentInstanceConnectedElement> currProperties =  getFilteredComponentInstanceProperties(component.getComponentInstancesProperties().get(instance.getUniqueId()), propertyNameFragment, searchByFragment);
1048                                         if(CollectionUtils.isNotEmpty(currProperties)){
1049                                                 filteredProperties.put(instance.getUniqueId(), currProperties);
1050                                         }
1051                                 }
1052                                 if(component.getComponentInstancesInputs()!=null && component.getComponentInstancesInputs().containsKey(instance.getUniqueId())){
1053                                         List<IComponentInstanceConnectedElement> currInputs =  getFilteredComponentInstanceInputs(component.getComponentInstancesInputs().get(instance.getUniqueId()), propertyNameFragment, searchByFragment);
1054                                         if(CollectionUtils.isNotEmpty(currInputs)){
1055                                                 if(filteredProperties.get(instance.getUniqueId())!=null){
1056                                                         filteredProperties.get(instance.getUniqueId()).addAll(currInputs);
1057                                                 } else {
1058                                                         filteredProperties.put(instance.getUniqueId(), currInputs);
1059                                                 }
1060                                         }
1061                                 }
1062                         }
1063                 }
1064                 return result;
1065         }
1066         
1067         private List<IComponentInstanceConnectedElement> getFilteredComponentInstanceInputs(List<ComponentInstanceInput> inputs, String propertyNameFragment, boolean searchByFragment) {
1068                 return inputs.stream().filter(i -> isMatchingInput(i, propertyNameFragment, searchByFragment)).collect(Collectors.toList());
1069         }
1070
1071         private List<IComponentInstanceConnectedElement> getFilteredComponentInstanceProperties(List<ComponentInstanceProperty> instanceProperties, String propertyNameFragment, boolean searchByFragment) {
1072                 return instanceProperties.stream().filter(p -> isMatchingProperty(p, propertyNameFragment, searchByFragment)).collect(Collectors.toList());
1073         }
1074
1075         private boolean isMatchingInput(ComponentInstanceInput input, String propertyNameFragment, boolean searchByFragment) {
1076                 boolean isMatching = false;
1077                 if(searchByFragment && input.getName().toLowerCase().contains(propertyNameFragment)){
1078                         isMatching = true;
1079                 }
1080                 if(!searchByFragment && input.getName().equalsIgnoreCase(propertyNameFragment)){
1081                         isMatching = true;
1082                 }
1083                 return isMatching;
1084         }
1085         
1086         private boolean isMatchingProperty(ComponentInstanceProperty property, String propertyNameFragment, boolean searchByFragment) {
1087                 boolean isMatching = false;
1088                 if(searchByFragment && property.getName().toLowerCase().contains(propertyNameFragment)){
1089                         isMatching = true;
1090                 }
1091                 if(!searchByFragment && property.getName().equalsIgnoreCase(propertyNameFragment)){
1092                         isMatching = true;
1093                 }
1094                 if (!isMatching && !ToscaPropertyType.isPrimitiveType(property.getType())){
1095                         isMatching = isMatchingComplexPropertyByRecursively(property, propertyNameFragment, searchByFragment);
1096                 }
1097                 return isMatching;
1098         }
1099
1100         private boolean isMatchingComplexPropertyByRecursively(PropertyDataDefinition property, String propertyNameFragment,  boolean searchByFragment) {
1101                 String propertyType;
1102                 List<PropertyDefinition>  dataTypeProperties;
1103                 DataTypeDefinition currentProperty;
1104                 if(searchByFragment && property.getName().toLowerCase().contains(propertyNameFragment.toLowerCase())){
1105                         return true;
1106                 }
1107                 if(!searchByFragment && property.getName().equalsIgnoreCase(propertyNameFragment)){
1108                         return true;
1109                 }
1110                 
1111                 propertyType = isEmptyInnerType(property) ? property.getType() : property.getSchema().getProperty().getType();
1112
1113                 if(ToscaPropertyType.isScalarType(propertyType)){
1114                         return false;
1115                 }
1116                 Either<DataTypeDefinition, StorageOperationStatus>  getDataTypeByNameRes = propertyOperation.getDataTypeByName(propertyType);
1117                 if(getDataTypeByNameRes.isRight()){
1118                         return false;
1119                 }
1120                 currentProperty = getDataTypeByNameRes.left().value();
1121                 dataTypeProperties = currentProperty.getProperties();
1122                 
1123                 if(CollectionUtils.isNotEmpty(dataTypeProperties)){
1124                         for(PropertyDefinition prop : dataTypeProperties){
1125                                 if(isMatchingComplexPropertyByRecursively(prop, propertyNameFragment, searchByFragment)){
1126                                         return true;
1127                                 }
1128                         }
1129                 }
1130                 dataTypeProperties = currentProperty.getDerivedFrom().getProperties();
1131                 if(CollectionUtils.isNotEmpty(dataTypeProperties)){
1132                         for(PropertyDefinition prop : dataTypeProperties){
1133                                 if(isMatchingComplexPropertyByRecursively(prop, propertyNameFragment, searchByFragment)){
1134                                         return true;
1135                                 }
1136                         }
1137                 }
1138                 return false;
1139         }
1140
1141         private boolean isEmptyInnerType(PropertyDataDefinition property) {
1142                 return property == null|| property.getSchema() == null || property.getSchema().getProperty() == null || property.getSchema().getProperty().getType() == null;
1143         }
1144
1145         public Either<Boolean, ResponseFormat> shouldUpgradeToLatestGeneric(Component clonedComponent) {
1146             
1147                 if(!clonedComponent.deriveFromGeneric())
1148                         return Either.left(false);
1149                 Boolean shouldUpgrade = false;
1150                 String currentGenericType = clonedComponent.getDerivedFromGenericType();
1151                 String currentGenericVersion = clonedComponent.getDerivedFromGenericVersion();
1152                 Either<Resource, ResponseFormat> fetchAndSetLatestGeneric = fetchAndSetDerivedFromGenericType(clonedComponent);
1153                 if(fetchAndSetLatestGeneric.isRight())
1154                         return Either.right(fetchAndSetLatestGeneric.right().value());
1155                 Resource genericTypeResource = fetchAndSetLatestGeneric.left().value();
1156                 if(null == currentGenericType || !currentGenericType.equals(genericTypeResource.getToscaResourceName()) || !currentGenericVersion.equals(genericTypeResource.getVersion())){
1157                         List<PropertyDefinition> genericTypeProps = genericTypeResource.getProperties();
1158                         List<InputDefinition> genericTypeInputs = null == genericTypeProps? null : convertGenericTypePropertiesToInputsDefintion(genericTypeProps, genericTypeResource.getUniqueId());
1159                         shouldUpgrade = upgradeToLatestGeneric(clonedComponent, genericTypeInputs);
1160                         if(!shouldUpgrade) {
1161                                 reverntUpdateOfGenericVersion(clonedComponent, currentGenericType, currentGenericVersion);
1162                         }
1163                 }
1164                 return Either.left(shouldUpgrade);
1165         }
1166
1167         private void reverntUpdateOfGenericVersion(Component clonedComponent, String currentGenericType, String currentGenericVersion) {
1168                 clonedComponent.setDerivedFromGenericType(currentGenericType);
1169                 clonedComponent.setDerivedFromGenericVersion(currentGenericVersion);
1170         } 
1171         
1172         
1173         private boolean upgradeToLatestGeneric(Component componentToCheckOut, List<InputDefinition> upgradedList) {
1174                 
1175                 if (!componentToCheckOut.shouldGenerateInputs())
1176                         return true;
1177                 
1178                 List<InputDefinition> currentList = new ArrayList<>();  
1179             // nullify existing ownerId from existing list and merge into updated list
1180                 if (null != componentToCheckOut.getInputs()) {
1181                         for(InputDefinition input : componentToCheckOut.getInputs()) {
1182                                 InputDefinition copy = new InputDefinition(input);
1183                                 copy.setOwnerId(null);
1184                                 currentList.add(copy);
1185                         }
1186                 }
1187                 if (null == upgradedList) {
1188                         componentToCheckOut.setInputs(currentList);
1189                         return true;
1190                 }
1191                 Map<String, InputDefinition> currentMap = PropertyDataDefinition.listToMapByName(currentList);
1192                 Map<String, InputDefinition> upgradedMap = PropertyDataDefinition.listToMapByName(upgradedList);
1193                 Either<Map<String, InputDefinition>, String> eitherMerged = PropertyDataDefinition.mergeProperties(upgradedMap, currentMap, true);
1194                 if (eitherMerged.isRight()) { 
1195                         log.debug("property {} cannot be overriden, check out performed without upgrading to latest generic", eitherMerged.right().value());
1196                         return false;
1197                 }
1198                 componentToCheckOut.setInputs(new ArrayList<InputDefinition>(eitherMerged.left().value().values()));
1199                 return true;
1200         }
1201
1202         private List<ComponentInstance> getFilteredInstances(Component component, List<String> resourceTypes) {
1203                 List<ComponentInstance> filteredInstances = null;
1204                 if(CollectionUtils.isEmpty(resourceTypes)){
1205                         filteredInstances = component.getComponentInstances();
1206                 }
1207                 else if(CollectionUtils.isNotEmpty(component.getComponentInstances())){
1208                         filteredInstances = component.getComponentInstances()
1209                                         .stream().filter(i -> isMatchingType(i.getOriginType(), resourceTypes)).collect(Collectors.toList());
1210                 }
1211                 if(filteredInstances == null){
1212                         filteredInstances = new ArrayList<>();
1213                 }
1214                 return filteredInstances;
1215         }
1216
1217         private boolean isMatchingType(OriginTypeEnum originType, List<String> resourceTypes) {
1218                 boolean isMatchingType = false;
1219                 for(String resourceType : resourceTypes){
1220                         if(originType == OriginTypeEnum.findByValue(resourceType.toUpperCase())){
1221                                 isMatchingType = true;
1222                                 break;
1223                         }
1224                 }
1225                 return isMatchingType;
1226         }
1227
1228 }
1229
1230