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