2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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 * ================================================================================
22 package org.openecomp.sdc.be.components.impl;
24 import fj.data.Either;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.List;
31 import java.util.Objects;
32 import java.util.Optional;
33 import java.util.stream.Collectors;
34 import org.apache.commons.collections.CollectionUtils;
35 import org.apache.commons.collections4.ListUtils;
36 import org.apache.commons.collections4.MapUtils;
37 import org.apache.commons.lang3.BooleanUtils;
38 import org.apache.commons.lang3.StringUtils;
39 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
40 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
41 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
42 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
43 import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator;
44 import org.openecomp.sdc.be.components.validation.ComponentValidations;
45 import org.openecomp.sdc.be.config.BeEcompErrorManager;
46 import org.openecomp.sdc.be.dao.api.ActionStatus;
47 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
48 import org.openecomp.sdc.be.dao.utils.MapUtil;
49 import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil;
50 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
51 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
52 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
53 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
54 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
55 import org.openecomp.sdc.be.model.Component;
56 import org.openecomp.sdc.be.model.ComponentInstInputsMap;
57 import org.openecomp.sdc.be.model.ComponentInstListInput;
58 import org.openecomp.sdc.be.model.ComponentInstance;
59 import org.openecomp.sdc.be.model.ComponentInstanceInput;
60 import org.openecomp.sdc.be.model.ComponentInstancePropInput;
61 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
62 import org.openecomp.sdc.be.model.ComponentParametersView;
63 import org.openecomp.sdc.be.model.DataTypeDefinition;
64 import org.openecomp.sdc.be.model.InputDefinition;
65 import org.openecomp.sdc.be.model.PropertyDefinition;
66 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
67 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
68 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
69 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
70 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
71 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
72 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
73 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
74 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
75 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
76 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
77 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
78 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
79 import org.openecomp.sdc.be.resources.data.EntryData;
80 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
81 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
82 import org.openecomp.sdc.common.log.enums.StatusCode;
83 import org.openecomp.sdc.common.log.wrappers.Logger;
84 import org.openecomp.sdc.exception.ResponseFormat;
85 import org.springframework.beans.factory.annotation.Autowired;
87 @org.springframework.stereotype.Component("inputsBusinessLogic")
88 public class InputsBusinessLogic extends BaseBusinessLogic {
90 private static final String CREATE_INPUT = "CreateInput";
91 private static final String UPDATE_INPUT = "UpdateInput";
92 private static final Logger log = Logger.getLogger(InputsBusinessLogic.class);
93 private static final String FAILED_TO_FOUND_COMPONENT_ERROR = "Failed to found component {}, error: {}";
94 private static final String FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR = "Failed to found input {} under component {}, error: {}";
95 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP = "Going to execute rollback on create group.";
96 private static final String GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP = "Going to execute commit on create group.";
97 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_UPDATE_INPUT = "Going to execute rollback on update input.";
98 private static final String GOING_TO_EXECUTE_COMMIT_ON_UPDATE_INPUT = "Going to execute commit on update input.";
99 private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(InputsBusinessLogic.class.getName());
100 private final PropertyDeclarationOrchestrator propertyDeclarationOrchestrator;
101 private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
102 private final DataTypeBusinessLogic dataTypeBusinessLogic;
105 public InputsBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
106 IGroupTypeOperation groupTypeOperation, InterfaceOperation interfaceOperation,
107 InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
108 PropertyDeclarationOrchestrator propertyDeclarationOrchestrator,
109 ComponentInstanceBusinessLogic componentInstanceBusinessLogic, DataTypeBusinessLogic dataTypeBusinessLogic,
110 ArtifactsOperations artifactToscaOperation) {
111 super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
112 artifactToscaOperation);
113 this.propertyDeclarationOrchestrator = propertyDeclarationOrchestrator;
114 this.componentInstanceBusinessLogic = componentInstanceBusinessLogic;
115 this.dataTypeBusinessLogic = dataTypeBusinessLogic;
119 * associate inputs to a given component with paging
125 public Either<List<InputDefinition>, ResponseFormat> getInputs(String userId, String componentId) {
126 validateUserExists(userId);
127 ComponentParametersView filters = new ComponentParametersView();
128 filters.disableAll();
129 filters.setIgnoreInputs(false);
130 Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
131 .getToscaElement(componentId, filters);
132 if (getComponentEither.isRight()) {
133 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
134 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
135 return Either.right(componentsUtils.getResponseFormat(actionStatus));
137 Component component = getComponentEither.left().value();
138 List<InputDefinition> inputs = component.getInputs();
139 return Either.left(inputs);
142 public Either<List<ComponentInstanceInput>, ResponseFormat> getComponentInstanceInputs(String userId, String componentId,
143 String componentInstanceId) {
144 validateUserExists(userId);
145 ComponentParametersView filters = new ComponentParametersView();
146 filters.disableAll();
147 filters.setIgnoreInputs(false);
148 filters.setIgnoreComponentInstances(false);
149 filters.setIgnoreComponentInstancesInputs(false);
150 Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
151 .getToscaElement(componentId, filters);
152 if (getComponentEither.isRight()) {
153 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
154 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
155 return Either.right(componentsUtils.getResponseFormat(actionStatus));
157 Component component = getComponentEither.left().value();
158 if (!ComponentValidations.validateComponentInstanceExist(component, componentInstanceId)) {
159 ActionStatus actionStatus = ActionStatus.COMPONENT_INSTANCE_NOT_FOUND;
160 log.debug("Failed to found component instance inputs {}, error: {}", componentInstanceId, actionStatus);
161 loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, component.getComponentMetadataForSupportLog(), StatusCode.ERROR,
162 "Failed to found component instance inputs componentInstanceId: {}", componentInstanceId);
163 return Either.right(componentsUtils.getResponseFormat(actionStatus));
165 Map<String, List<ComponentInstanceInput>> ciInputs = Optional.ofNullable(component.getComponentInstancesInputs())
166 .orElse(Collections.emptyMap());
167 // Set Constraints on Input
168 MapUtils.emptyIfNull(ciInputs).values()
169 .forEach(inputs -> ListUtils.emptyIfNull(inputs).forEach(input -> input.setConstraints(setInputConstraint(input))));
170 return Either.left(ciInputs.getOrDefault(componentInstanceId, Collections.emptyList()));
174 * associate properties to a given component instance input
181 public Either<List<ComponentInstanceProperty>, ResponseFormat> getComponentInstancePropertiesByInputId(String userId, String componentId,
182 String instanceId, String inputId) {
183 validateUserExists(userId);
184 String parentId = componentId;
186 ComponentParametersView filters = new ComponentParametersView();
187 filters.disableAll();
188 filters.setIgnoreComponentInstances(false);
189 if (!instanceId.equals(inputId)) {
190 Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
191 .getToscaElement(parentId, filters);
192 if (getComponentEither.isRight()) {
193 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
194 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, parentId, actionStatus);
195 return Either.right(componentsUtils.getResponseFormat(actionStatus));
197 component = getComponentEither.left().value();
198 Optional<ComponentInstance> ciOp = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(instanceId)).findAny();
199 if (ciOp.isPresent()) {
200 parentId = ciOp.get().getComponentUid();
203 filters.setIgnoreInputs(false);
204 filters.setIgnoreComponentInstancesProperties(false);
205 filters.setIgnoreComponentInstancesInputs(false);
206 filters.setIgnoreProperties(false);
207 Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
208 .getToscaElement(parentId, filters);
209 if (getComponentEither.isRight()) {
210 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
211 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, parentId, actionStatus);
212 return Either.right(componentsUtils.getResponseFormat(actionStatus));
214 component = getComponentEither.left().value();
215 Optional<InputDefinition> op = component.getInputs().stream().filter(in -> in.getUniqueId().equals(inputId)).findFirst();
216 if (!op.isPresent()) {
217 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
218 log.debug(FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR, inputId, parentId, actionStatus);
219 return Either.right(componentsUtils.getResponseFormat(actionStatus));
221 return Either.left(componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(component, inputId));
224 private String updateInputObjectValue(InputDefinition currentInput, InputDefinition newInput, Map<String, DataTypeDefinition> dataTypes) {
225 String innerType = null;
226 String propertyType = currentInput.getType();
227 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
228 log.debug("The type of the property {} is {}", currentInput.getUniqueId(), propertyType);
229 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
230 SchemaDefinition def = currentInput.getSchema();
232 log.debug("Schema doesn't exists for property of type {}", type);
233 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE));
235 PropertyDataDefinition propDef = def.getProperty();
236 if (propDef == null) {
237 log.debug("Property in Schema Definition inside property of type {} doesn't exist", type);
238 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE));
240 innerType = propDef.getType();
242 // Specific Update Logic
243 Either<Object, Boolean> isValid = propertyOperation
244 .validateAndUpdatePropertyValue(propertyType, newInput.getDefaultValue(), true, innerType, dataTypes);
245 String newValue = newInput.getDefaultValue();
246 if (isValid.isRight()) {
247 Boolean res = isValid.right().value();
248 if (Boolean.FALSE.equals(res)) {
249 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(
250 DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)));
253 Object object = isValid.left().value();
254 if (object != null) {
255 newValue = object.toString();
261 private InputDefinition getInputFromInputsListById(List<InputDefinition> componentsOldInputs, InputDefinition input) {
262 return componentsOldInputs.stream().filter(in -> in.getUniqueId().equals(input.getUniqueId())).findFirst().orElse(null);
265 public Either<List<InputDefinition>, ResponseFormat> updateInputsValue(ComponentTypeEnum componentType, String componentId,
266 List<InputDefinition> inputs, String userId, boolean shouldLockComp) {
267 List<InputDefinition> returnInputs = new ArrayList<>();
268 Either<List<InputDefinition>, ResponseFormat> result = null;
269 Component component = null;
271 validateUserExists(userId);
272 ComponentParametersView componentParametersView = new ComponentParametersView();
273 componentParametersView.disableAll();
274 componentParametersView.setIgnoreInputs(false);
275 componentParametersView.setIgnoreUsers(false);
276 componentParametersView.setIgnoreProperties(false);
277 componentParametersView.setIgnoreComponentInstancesProperties(false);
278 componentParametersView.setIgnoreComponentInstances(false);
279 component = validateComponentExists(componentId, componentType, componentParametersView);
280 if (shouldLockComp) {
282 lockComponent(component, UPDATE_INPUT);
283 } catch (ComponentException e) {
284 log.error("Failed to lock component", e);
285 result = Either.right(e.getResponseFormat());
289 //Validate value and Constraint of input
290 Either<Boolean, ResponseFormat> constraintValidatorResponse = validateInputValueConstraint(inputs, component.getModel());
291 if (constraintValidatorResponse.isRight()) {
292 log.error("Failed validation value and constraint of property: {}", constraintValidatorResponse.right().value());
293 unlockComponent(true, component);
294 return Either.right(constraintValidatorResponse.right().value());
296 validateCanWorkOnComponent(component, userId);
297 Map<String, DataTypeDefinition> dataTypes;
298 dataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel());
299 List<InputDefinition> componentsOldInputs = Optional.ofNullable(component.getInputs()).orElse(Collections.emptyList());
300 for (InputDefinition newInput : inputs) {
301 InputDefinition currInput = getInputFromInputsListById(componentsOldInputs, newInput);
302 if (currInput == null) {
303 ActionStatus actionStatus = ActionStatus.COMPONENT_NOT_FOUND;
304 log.debug("Failed to found newInput {} under component {}, error: {}", newInput.getUniqueId(), componentId, actionStatus);
305 unlockComponent(true, component);
306 return Either.right(componentsUtils.getResponseFormat(actionStatus));
308 String updateInputObjectValue = updateInputObjectValue(currInput, newInput, dataTypes);
309 currInput.setDefaultValue(updateInputObjectValue);
310 currInput.setOwnerId(userId);
311 currInput.setMetadata(newInput.getMetadata());
312 if (newInput.getConstraints() != null) {
313 currInput.setConstraints(newInput.getConstraints());
315 if (newInput.isRequired() != null) {
316 currInput.setRequired(newInput.isRequired());
318 Either<InputDefinition, StorageOperationStatus> status = toscaOperationFacade.updateInputOfComponent(component, currInput);
319 if (status.isRight()) {
320 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForResourceInstanceProperty(status.right().value());
321 unlockComponent(true, component);
322 return Either.right(componentsUtils.getResponseFormat(actionStatus, ""));
324 returnInputs.add(status.left().value());
327 result = Either.left(returnInputs);
328 } catch (ComponentException e) {
329 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_UPDATE_INPUT);
330 unlockRollbackWithException(component, e);
331 } catch (Exception e) {
332 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_UPDATE_INPUT);
333 unlockRollbackWithException(component, new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR));
335 log.debug(GOING_TO_EXECUTE_COMMIT_ON_UPDATE_INPUT);
336 unlockWithCommit(component);
340 private Either<Boolean, ResponseFormat> validateInputValueConstraint(List<InputDefinition> inputs, final String model) {
341 PropertyValueConstraintValidationUtil propertyValueConstraintValidationUtil = new PropertyValueConstraintValidationUtil();
342 List<InputDefinition> inputDefinitions = new ArrayList<>();
343 for (InputDefinition inputDefinition : inputs) {
344 InputDefinition inputDef = new InputDefinition();
345 inputDef.setName(inputDefinition.getName());
346 inputDef.setDefaultValue(inputDefinition.getDefaultValue());
347 inputDef.setInputPath(inputDefinition.getSubPropertyInputPath());
348 inputDef.setType(inputDefinition.getType());
349 inputDef.setConstraints(inputDefinition.getConstraints());
350 if (Objects.nonNull(inputDefinition.getParentPropertyType())) {
351 ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty();
352 propertyDefinition.setType(inputDefinition.getParentPropertyType());
353 inputDef.setProperties(Collections.singletonList(propertyDefinition));
355 inputDefinitions.add(inputDef);
357 return propertyValueConstraintValidationUtil.validatePropertyConstraints(inputDefinitions, applicationDataTypeCache, model);
360 public Either<List<ComponentInstanceInput>, ResponseFormat> getInputsForComponentInput(String userId, String componentId, String inputId) {
361 validateUserExists(userId);
362 Component component = null;
363 ComponentParametersView filters = new ComponentParametersView();
364 filters.disableAll();
365 filters.setIgnoreComponentInstances(false);
366 filters.setIgnoreInputs(false);
367 filters.setIgnoreComponentInstancesInputs(false);
368 filters.setIgnoreProperties(false);
369 Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
370 .getToscaElement(componentId, filters);
371 if (getComponentEither.isRight()) {
372 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
373 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
374 return Either.right(componentsUtils.getResponseFormat(actionStatus));
376 component = getComponentEither.left().value();
377 Optional<InputDefinition> op = component.getInputs().stream().filter(in -> in.getUniqueId().equals(inputId)).findFirst();
378 if (!op.isPresent()) {
379 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
380 log.debug(FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR, inputId, componentId, actionStatus);
381 return Either.right(componentsUtils.getResponseFormat(actionStatus));
383 return Either.left(componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(component, inputId));
387 public Either<List<InputDefinition>, ResponseFormat> declareProperties(String userId, String componentId, ComponentTypeEnum componentTypeEnum,
388 ComponentInstInputsMap componentInstInputsMap) {
389 return createMultipleInputs(userId, componentId, componentTypeEnum, componentInstInputsMap, true, false);
392 private Either<List<InputDefinition>, ResponseFormat> createMultipleInputs(String userId, String componentId, ComponentTypeEnum componentType,
393 ComponentInstInputsMap componentInstInputsMapUi,
394 boolean shouldLockComp,
395 boolean inTransaction) {
396 Either<List<InputDefinition>, ResponseFormat> result = null;
397 Component component = null;
399 validateUserExists(userId);
400 component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
401 result = propertyDeclarationOrchestrator.declarePropertiesToInputs(component, componentInstInputsMapUi).left()
402 .bind(inputsToCreate -> prepareInputsForCreation(userId, componentId, inputsToCreate)).right()
403 .map(componentsUtils::getResponseFormat);
405 } catch (ByResponseFormatComponentException e) {
406 log.error("#createMultipleInputs: Exception thrown: ", e);
407 result = Either.right(e.getResponseFormat());
410 if (!inTransaction) {
411 if (result == null || result.isRight()) {
412 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
413 janusGraphDao.rollback();
415 log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
416 janusGraphDao.commit();
420 if (shouldLockComp && component != null) {
421 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
427 * Creates a list input with a data type which has properties specified.
429 * @param userId User ID
430 * @param componentId Component ID
431 * @param componentType Component type
432 * @param componentListInput Properties to be declared and input to be created
433 * @param shouldLockComp true if the component should be locked
434 * @param inTransaction true if already in transaction
436 public Either<List<InputDefinition>, ResponseFormat> createListInput(String userId, String componentId, ComponentTypeEnum componentType,
437 ComponentInstListInput componentListInput, boolean shouldLockComp,
438 boolean inTransaction) {
439 Either<List<InputDefinition>, ResponseFormat> result = null;
440 Component component = null;
441 log.trace("#createListInput: enter");
443 /* check if user exists */
444 validateUserExists(userId);
446 component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
448 InputDefinition listInput = componentListInput.getListInput();
449 DataTypeDefinition dataType =
450 prepareDataTypeForListInput(componentListInput.getComponentInstInputsMap(), listInput);
451 Map<String, DataTypeDefinition> dataTypesMap = new HashMap<>();
452 dataTypesMap.put(dataType.getName(), dataType);
453 if (log.isDebugEnabled()) {
454 log.debug("#createListInput: dataTypesMap={}", ReflectionToStringBuilder.toString(dataTypesMap));
457 Either<List<DataTypeDefinition>, StorageOperationStatus> dataTypeResult =
458 toscaOperationFacade.addDataTypesToComponent(dataTypesMap, componentId);
459 if (dataTypeResult.isRight()) {
460 log.debug("#createListInput: DataType creation failed.");
461 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(dataTypeResult.right().value()));
465 listInput.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(componentId, listInput.getName()));
466 listInput.setInstanceUniqueId(
467 propertyDeclarationOrchestrator.getPropOwnerId(componentListInput.getComponentInstInputsMap()));
468 listInput.setIsDeclaredListInput(true);
469 Map<String, InputDefinition> listInputMap = new HashMap<>();
470 listInputMap.put(listInput.getName(), listInput);
471 result = createListInputsInGraph(listInputMap, dataTypesMap, component);
472 if (result.isRight()) {
473 log.debug("#createListInput: createListInputsInGraph failed.");
474 throw new ByResponseFormatComponentException(result.right().value());
478 result = propertyDeclarationOrchestrator
479 .declarePropertiesToListInput(component, componentListInput.getComponentInstInputsMap(), listInput)
480 .right().map(err -> componentsUtils.getResponseFormat(err))
481 .left().map(Arrays::asList);
483 log.trace("#createListInput: leave");
487 } catch (ByResponseFormatComponentException e) {
488 log.error("#createListInput: Exception thrown", e);
489 result = Either.right(e.getResponseFormat());
493 if (!inTransaction) {
494 if (result == null || result.isRight()) {
495 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
496 janusGraphDao.rollback();
498 log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
499 janusGraphDao.commit();
503 if (shouldLockComp && component != null) {
504 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
509 private ComponentParametersView getBaseComponentParametersView() {
510 ComponentParametersView componentParametersView = new ComponentParametersView();
511 componentParametersView.disableAll();
512 componentParametersView.setIgnoreInputs(false);
513 componentParametersView.setIgnoreComponentInstances(false);
514 componentParametersView.setIgnoreComponentInstancesInputs(false);
515 componentParametersView.setIgnoreComponentInstancesProperties(false);
516 componentParametersView.setIgnorePolicies(false);
517 componentParametersView.setIgnoreGroups(false);
518 componentParametersView.setIgnoreUsers(false);
519 return componentParametersView;
522 private Component getAndValidateComponentForCreate(
523 String userId, String componentId, ComponentTypeEnum componentType, boolean shouldLockComp
525 ComponentParametersView componentParametersView = getBaseComponentParametersView();
526 Component component = validateComponentExists(componentId, componentType, componentParametersView);
527 if (shouldLockComp) {
528 // lock the component
529 lockComponent(component, CREATE_INPUT);
531 validateCanWorkOnComponent(component, userId);
535 private DataTypeDefinition prepareDataTypeForListInput(ComponentInstInputsMap inputsMap, InputDefinition input) {
536 // Confirm if type is list
537 if (StringUtils.isEmpty(input.getType()) || !input.getType().equals(ToscaPropertyType.LIST.getType())) {
538 log.debug("#prepareDataTypeForListInput: Type of input is not list.");
539 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_TYPE));
542 // Confirm schema type is not empty
543 String desiredTypeName = input.getSchemaType();
544 if (StringUtils.isEmpty(desiredTypeName)) {
545 log.debug("#prepareDataTypeForListInput: Schema type of list input is empty.");
546 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_INNER_TYPE));
549 DataTypeDefinition dataType = new DataTypeDefinition();
550 List<ComponentInstancePropInput> propInputs = inputsMap.resolvePropertiesToDeclare().getRight();
551 dataType.setName(desiredTypeName);
552 dataType.setDerivedFromName(ToscaPropertyType.ROOT.getType());
553 // Copy properties from inputsMap
554 dataType.setProperties(propInputs.stream().map(PropertyDefinition::new).collect(Collectors.toList()));
558 private Either<List<InputDefinition>, StorageOperationStatus> prepareInputsForCreation(String userId, String cmptId,
559 List<InputDefinition> inputsToCreate) {
560 Map<String, InputDefinition> inputsToPersist = MapUtil.toMap(inputsToCreate, InputDefinition::getName);
561 assignOwnerIdToInputs(userId, inputsToPersist);
562 inputsToPersist.values()
563 .forEach(input -> input.setConstraints(componentInstanceBusinessLogic.setInputConstraint(input)));
565 return toscaOperationFacade.addInputsToComponent(inputsToPersist, cmptId)
567 .map(persistedInputs -> inputsToCreate);
570 private void assignOwnerIdToInputs(String userId, Map<String, InputDefinition> inputsToCreate) {
571 inputsToCreate.values().forEach(inputDefinition -> inputDefinition.setOwnerId(userId));
574 public Either<List<InputDefinition>, ResponseFormat> createInputsInGraph(Map<String, InputDefinition> inputs,
575 Component component) {
577 List<InputDefinition> resourceProperties = component.getInputs();
579 final Map<String, DataTypeDefinition> dataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel());
581 for (Map.Entry<String, InputDefinition> inputDefinition : inputs.entrySet()) {
582 String inputName = inputDefinition.getKey();
583 inputDefinition.getValue().setName(inputName);
585 Either<InputDefinition, ResponseFormat> preparedInputEither = prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes);
586 if (preparedInputEither.isRight()) {
587 return Either.right(preparedInputEither.right().value());
591 if (resourceProperties != null) {
592 Map<String, InputDefinition> generatedInputs = resourceProperties.stream()
593 .collect(Collectors.toMap(PropertyDataDefinition::getName, i -> i));
594 Either<Map<String, InputDefinition>, String> mergeEither = ToscaDataDefinition.mergeDataMaps(generatedInputs, inputs);
595 if (mergeEither.isRight()) {
596 return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_ALREADY_EXIST, mergeEither.right().value()));
598 inputs = mergeEither.left().value();
601 Either<List<InputDefinition>, StorageOperationStatus> associateInputsEither = toscaOperationFacade
602 .createAndAssociateInputs(inputs, component.getUniqueId());
603 if (associateInputsEither.isRight()) {
604 log.debug("Failed to create inputs under component {}. Status is {}", component.getUniqueId(), associateInputsEither.right().value());
606 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(associateInputsEither.right().value())));
608 return Either.left(associateInputsEither.left().value());
611 private Either<List<InputDefinition>, ResponseFormat> createListInputsInGraph(Map<String, InputDefinition> inputs,
612 Map<String, DataTypeDefinition> privateDataTypes,
613 Component component) {
615 log.trace("#createListInputsInGraph: enter");
617 Map<String, DataTypeDefinition> dataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel());
618 dataTypes.putAll(privateDataTypes);
620 for (Map.Entry<String, InputDefinition> inputDefinition : inputs.entrySet()) {
621 String inputName = inputDefinition.getKey();
622 inputDefinition.getValue().setName(inputName);
624 Either<InputDefinition, ResponseFormat> preparedInputEither =
625 prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes);
626 if (preparedInputEither.isRight()) {
627 return Either.right(preparedInputEither.right().value());
631 Either<List<InputDefinition>, StorageOperationStatus> addInputsEither = toscaOperationFacade
632 .addInputsToComponent(inputs, component.getUniqueId());
633 if (addInputsEither.isRight()) {
634 log.debug("#createListInputsInGraph: Failed to create inputs under component {}. Status is {}",
635 component.getUniqueId(), addInputsEither.right().value());
636 return Either.right(componentsUtils.getResponseFormat(
637 componentsUtils.convertFromStorageResponse(addInputsEither.right().value())));
639 log.trace("#createListInputsInGraph: leave");
640 return Either.left(addInputsEither.left().value());
644 * Delete input from service
651 public InputDefinition deleteInput(String componentId, String userId, String inputId) {
652 Either<InputDefinition, ResponseFormat> deleteEither = null;
653 if (log.isDebugEnabled()) {
654 log.debug("Going to delete input id: {}", inputId);
656 validateUserExists(userId);
657 ComponentParametersView componentParametersView = getBaseComponentParametersView();
658 componentParametersView.setIgnoreInterfaces(false);
659 componentParametersView.setIgnoreDataType(false);
660 componentParametersView.setIgnoreProperties(false);
661 Either<Component, StorageOperationStatus> componentEither = toscaOperationFacade
662 .getToscaElement(componentId, componentParametersView);
663 if (componentEither.isRight()) {
664 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(componentEither.right().value()));
666 Component component = componentEither.left().value();
667 // Validate inputId is child of the component
668 Optional<InputDefinition> optionalInput = component.getInputs().stream().
670 filter(input -> input.getUniqueId().equals(inputId)).
673 if (!optionalInput.isPresent()) {
674 throw new ByActionStatusComponentException(ActionStatus.INPUT_IS_NOT_CHILD_OF_COMPONENT, inputId, componentId);
676 InputDefinition inputForDelete = optionalInput.get();
678 lockComponent(componentId, component, "deleteInput");
679 // Delete input operations
680 boolean failed = false;
682 StorageOperationStatus status = toscaOperationFacade.deleteInputOfResource(component, inputForDelete.getName());
683 if (status != StorageOperationStatus.OK) {
684 log.debug("Component id: {} delete input id: {} failed", componentId, inputId);
685 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status), component.getName());
687 if (BooleanUtils.isTrue(inputForDelete.getIsDeclaredListInput())) {
688 deleteEither = deleteListInput(componentId, inputId, component, inputForDelete, status);
689 if (deleteEither.isRight()) {
690 throw new ByResponseFormatComponentException(deleteEither.right().value());
692 return deleteEither.left().value();
694 StorageOperationStatus storageOperationStatus = propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(component, inputForDelete);
695 if (storageOperationStatus != StorageOperationStatus.OK) {
696 log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId);
697 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(storageOperationStatus), component.getName());
699 return inputForDelete;
700 } catch (ComponentException e) {
704 unlockComponent(failed, component);
708 private Either<InputDefinition, ResponseFormat> deleteListInput(String componentId, String inputId,
709 Component component, InputDefinition inputForDelete,
710 StorageOperationStatus status) {
711 // the input is created by 'Declare List'.
712 // need to 1. undeclare properties, 2. delete input, 3. delete private data type
713 StorageOperationStatus storageOperationStatus = propertyDeclarationOrchestrator.unDeclarePropertiesAsListInputs(component, inputForDelete);
714 if (storageOperationStatus != StorageOperationStatus.OK) {
715 log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId);
716 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), component.getName()));
718 Either<DataTypeDefinition, StorageOperationStatus> deleteResult = dataTypeBusinessLogic
719 .deletePrivateDataType(component, inputForDelete.getSchemaType());
720 if (deleteResult.isRight()) {
721 log.debug("Component id: {} delete datatype name: {} failed", componentId, inputForDelete.getSchemaType());
723 componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteResult.right().value()), component.getName()));
725 log.trace("deleteInput: deletePrivateDataType (OK)");
726 return Either.left(inputForDelete);
729 private Either<InputDefinition, ResponseFormat> prepareAndValidateInputBeforeCreate(InputDefinition newInputDefinition,
730 Map<String, DataTypeDefinition> dataTypes) {
731 // validate input default values
732 Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newInputDefinition, dataTypes);
733 if (defaultValuesValidation.isRight()) {
734 return Either.right(defaultValuesValidation.right().value());
737 ToscaPropertyType type = getType(newInputDefinition.getType());
739 PropertyValueConverter converter = type.getConverter();
741 SchemaDefinition schema = newInputDefinition.getSchema();
742 String innerType = null;
743 if (schema != null) {
744 PropertyDataDefinition prop = schema.getProperty();
746 innerType = prop.getType();
749 String convertedValue;
750 if (newInputDefinition.getDefaultValue() != null) {
751 convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, dataTypes);
752 newInputDefinition.setDefaultValue(convertedValue);
755 return Either.left(newInputDefinition);
758 public Either<InputDefinition, ResponseFormat> getInputsAndPropertiesForComponentInput(String userId, String componentId, String inputId,
759 boolean inTransaction) {
760 Either<InputDefinition, ResponseFormat> result = null;
762 validateUserExists(userId);
763 ComponentParametersView filters = new ComponentParametersView();
764 filters.disableAll();
765 filters.setIgnoreComponentInstances(false);
766 filters.setIgnoreInputs(false);
767 filters.setIgnoreComponentInstancesInputs(false);
768 filters.setIgnoreComponentInstancesProperties(false);
769 filters.setIgnoreProperties(false);
770 Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
771 .getToscaElement(componentId, filters);
772 if (getComponentEither.isRight()) {
773 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
774 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
775 return Either.right(componentsUtils.getResponseFormat(actionStatus));
777 Component component = getComponentEither.left().value();
778 Optional<InputDefinition> op = component.getInputs().stream().filter(in -> in.getUniqueId().equals(inputId)).findFirst();
779 if (!op.isPresent()) {
780 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
781 log.debug(FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR, inputId, componentId, actionStatus);
782 return Either.right(componentsUtils.getResponseFormat(actionStatus));
784 InputDefinition resObj = op.get();
785 List<ComponentInstanceInput> inputCIInput = componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(component, inputId);
786 resObj.setInputs(inputCIInput);
787 List<ComponentInstanceProperty> inputProps = componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(component, inputId);
788 resObj.setProperties(inputProps);
789 result = Either.left(resObj);
792 if (!inTransaction) {
793 if (result == null || result.isRight()) {
794 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
795 janusGraphDao.rollback();
797 log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
798 janusGraphDao.commit();
804 public Either<EntryData<String, InputDefinition>, ResponseFormat> addInputToComponent(String componentId, String inputName,
805 InputDefinition newInputDefinition, String userId) {
806 Either<EntryData<String, InputDefinition>, ResponseFormat> result = null;
807 validateUserExists(userId);
808 Either<Component, StorageOperationStatus> serviceElement = toscaOperationFacade.getToscaElement(componentId);
809 if (serviceElement.isRight()) {
810 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
813 Component component = serviceElement.left().value();
814 NodeTypeEnum nodeType = component.getComponentType().getNodeType();
815 StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType);
816 if (!lockResult.equals(StorageOperationStatus.OK)) {
817 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_INPUT, nodeType.name().toLowerCase(), componentId);
818 log.info("Failed to lock component {}. Error - {}", componentId, lockResult);
819 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
823 if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) {
824 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
827 List<InputDefinition> inputs = component.getInputs();
828 if (CollectionUtils.isEmpty(inputs)) {
829 inputs = new ArrayList<>();
831 if (isInputExistInComponent(inputs, inputName)) {
832 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUT_ALREADY_EXIST, inputName));
835 Map<String, DataTypeDefinition> allDataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel());
836 // validate input default values
837 Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newInputDefinition, allDataTypes);
838 if (defaultValuesValidation.isRight()) {
839 result = Either.right(defaultValuesValidation.right().value());
843 ToscaPropertyType type = getType(newInputDefinition.getType());
845 PropertyValueConverter converter = type.getConverter();
847 String innerType = null;
848 SchemaDefinition schema = newInputDefinition.getSchema();
849 if (schema != null) {
850 PropertyDataDefinition prop = schema.getProperty();
852 innerType = prop.getType();
855 if (newInputDefinition.getDefaultValue() != null) {
856 String convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, allDataTypes);
857 newInputDefinition.setDefaultValue(convertedValue);
860 newInputDefinition.setMappedToComponentProperty(false);
861 Either<InputDefinition, StorageOperationStatus> addInputEither = toscaOperationFacade
862 .addInputToComponent(inputName, newInputDefinition, component);
863 if (addInputEither.isRight()) {
864 log.info("Failed to add new input {}. Error - {}", componentId, addInputEither.right().value());
865 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
868 result = Either.left(new EntryData<>(inputName, newInputDefinition));
871 commitOrRollback(result);
873 graphLockOperation.unlockComponent(componentId, nodeType);
877 private boolean isInputExistInComponent(List<InputDefinition> inputs, String inputName) {
878 return CollectionUtils.isNotEmpty(inputs) && inputs.stream().anyMatch(input -> input.getName().equals(inputName));