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