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