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