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 return Either.right(constraintValidatorResponse.right().value());
295 validateCanWorkOnComponent(component, userId);
296 Map<String, DataTypeDefinition> dataTypes;
297 dataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel());
298 List<InputDefinition> componentsOldInputs = Optional.ofNullable(component.getInputs()).orElse(Collections.emptyList());
299 for (InputDefinition newInput : inputs) {
300 InputDefinition currInput = getInputFromInputsListById(componentsOldInputs, newInput);
301 if (currInput == null) {
302 ActionStatus actionStatus = ActionStatus.COMPONENT_NOT_FOUND;
303 log.debug("Failed to found newInput {} under component {}, error: {}", newInput.getUniqueId(), componentId, actionStatus);
304 result = Either.right(componentsUtils.getResponseFormat(actionStatus));
307 String updateInputObjectValue = updateInputObjectValue(currInput, newInput, dataTypes);
308 currInput.setDefaultValue(updateInputObjectValue);
309 currInput.setOwnerId(userId);
310 currInput.setMetadata(newInput.getMetadata());
311 if (newInput.isRequired() != null) {
312 currInput.setRequired(newInput.isRequired());
314 Either<InputDefinition, StorageOperationStatus> status = toscaOperationFacade.updateInputOfComponent(component, currInput);
315 if (status.isRight()) {
316 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForResourceInstanceProperty(status.right().value());
317 result = Either.right(componentsUtils.getResponseFormat(actionStatus, ""));
320 returnInputs.add(status.left().value());
323 result = Either.left(returnInputs);
324 } catch (ComponentException e) {
325 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_UPDATE_INPUT);
326 unlockRollbackWithException(component, e);
327 } catch (Exception e) {
328 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_UPDATE_INPUT);
329 unlockRollbackWithException(component, new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR));
331 log.debug(GOING_TO_EXECUTE_COMMIT_ON_UPDATE_INPUT);
332 unlockWithCommit(component);
336 private Either<Boolean, ResponseFormat> validateInputValueConstraint(List<InputDefinition> inputs, final String model) {
337 PropertyValueConstraintValidationUtil propertyValueConstraintValidationUtil = new PropertyValueConstraintValidationUtil();
338 List<InputDefinition> inputDefinitions = new ArrayList<>();
339 for (InputDefinition inputDefinition : inputs) {
340 InputDefinition inputDef = new InputDefinition();
341 inputDefinition.setDefaultValue(inputDefinition.getDefaultValue());
342 inputDefinition.setInputPath(inputDefinition.getSubPropertyInputPath());
343 inputDefinition.setType(inputDefinition.getType());
344 if (Objects.nonNull(inputDefinition.getParentPropertyType())) {
345 ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty();
346 propertyDefinition.setType(inputDefinition.getParentPropertyType());
347 inputDefinition.setProperties(Collections.singletonList(propertyDefinition));
349 inputDefinitions.add(inputDef);
351 return propertyValueConstraintValidationUtil.validatePropertyConstraints(inputDefinitions, applicationDataTypeCache, model);
354 public Either<List<ComponentInstanceInput>, ResponseFormat> getInputsForComponentInput(String userId, String componentId, String inputId) {
355 validateUserExists(userId);
356 Component component = null;
357 ComponentParametersView filters = new ComponentParametersView();
358 filters.disableAll();
359 filters.setIgnoreComponentInstances(false);
360 filters.setIgnoreInputs(false);
361 filters.setIgnoreComponentInstancesInputs(false);
362 filters.setIgnoreProperties(false);
363 Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
364 .getToscaElement(componentId, filters);
365 if (getComponentEither.isRight()) {
366 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
367 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
368 return Either.right(componentsUtils.getResponseFormat(actionStatus));
370 component = getComponentEither.left().value();
371 Optional<InputDefinition> op = component.getInputs().stream().filter(in -> in.getUniqueId().equals(inputId)).findFirst();
372 if (!op.isPresent()) {
373 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
374 log.debug(FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR, inputId, componentId, actionStatus);
375 return Either.right(componentsUtils.getResponseFormat(actionStatus));
377 return Either.left(componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(component, inputId));
381 public Either<List<InputDefinition>, ResponseFormat> declareProperties(String userId, String componentId, ComponentTypeEnum componentTypeEnum,
382 ComponentInstInputsMap componentInstInputsMap) {
383 return createMultipleInputs(userId, componentId, componentTypeEnum, componentInstInputsMap, true, false);
386 private Either<List<InputDefinition>, ResponseFormat> createMultipleInputs(String userId, String componentId, ComponentTypeEnum componentType,
387 ComponentInstInputsMap componentInstInputsMapUi,
388 boolean shouldLockComp,
389 boolean inTransaction) {
390 Either<List<InputDefinition>, ResponseFormat> result = null;
391 Component component = null;
393 validateUserExists(userId);
394 component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
395 result = propertyDeclarationOrchestrator.declarePropertiesToInputs(component, componentInstInputsMapUi).left()
396 .bind(inputsToCreate -> prepareInputsForCreation(userId, componentId, inputsToCreate)).right()
397 .map(componentsUtils::getResponseFormat);
399 } catch (ByResponseFormatComponentException e) {
400 log.error("#createMultipleInputs: Exception thrown: ", e);
401 result = Either.right(e.getResponseFormat());
404 if (!inTransaction) {
405 if (result == null || result.isRight()) {
406 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
407 janusGraphDao.rollback();
409 log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
410 janusGraphDao.commit();
414 if (shouldLockComp && component != null) {
415 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
421 * Creates a list input with a data type which has properties specified.
423 * @param userId User ID
424 * @param componentId Component ID
425 * @param componentType Component type
426 * @param componentListInput Properties to be declared and input to be created
427 * @param shouldLockComp true if the component should be locked
428 * @param inTransaction true if already in transaction
430 public Either<List<InputDefinition>, ResponseFormat> createListInput(String userId, String componentId, ComponentTypeEnum componentType,
431 ComponentInstListInput componentListInput, boolean shouldLockComp,
432 boolean inTransaction) {
433 Either<List<InputDefinition>, ResponseFormat> result = null;
434 Component component = null;
435 log.trace("#createListInput: enter");
437 /* check if user exists */
438 validateUserExists(userId);
440 component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
442 InputDefinition listInput = componentListInput.getListInput();
443 DataTypeDefinition dataType =
444 prepareDataTypeForListInput(componentListInput.getComponentInstInputsMap(), listInput);
445 Map<String, DataTypeDefinition> dataTypesMap = new HashMap<>();
446 dataTypesMap.put(dataType.getName(), dataType);
447 if (log.isDebugEnabled()) {
448 log.debug("#createListInput: dataTypesMap={}", ReflectionToStringBuilder.toString(dataTypesMap));
451 Either<List<DataTypeDefinition>, StorageOperationStatus> dataTypeResult =
452 toscaOperationFacade.addDataTypesToComponent(dataTypesMap, componentId);
453 if (dataTypeResult.isRight()) {
454 log.debug("#createListInput: DataType creation failed.");
455 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(dataTypeResult.right().value()));
459 listInput.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(componentId, listInput.getName()));
460 listInput.setInstanceUniqueId(
461 propertyDeclarationOrchestrator.getPropOwnerId(componentListInput.getComponentInstInputsMap()));
462 listInput.setIsDeclaredListInput(true);
463 Map<String, InputDefinition> listInputMap = new HashMap<>();
464 listInputMap.put(listInput.getName(), listInput);
465 result = createListInputsInGraph(listInputMap, dataTypesMap, component);
466 if (result.isRight()) {
467 log.debug("#createListInput: createListInputsInGraph failed.");
468 throw new ByResponseFormatComponentException(result.right().value());
472 result = propertyDeclarationOrchestrator
473 .declarePropertiesToListInput(component, componentListInput.getComponentInstInputsMap(), listInput)
474 .right().map(err -> componentsUtils.getResponseFormat(err))
475 .left().map(Arrays::asList);
477 log.trace("#createListInput: leave");
481 } catch (ByResponseFormatComponentException e) {
482 log.error("#createListInput: Exception thrown", e);
483 result = Either.right(e.getResponseFormat());
487 if (!inTransaction) {
488 if (result == null || result.isRight()) {
489 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
490 janusGraphDao.rollback();
492 log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
493 janusGraphDao.commit();
497 if (shouldLockComp && component != null) {
498 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
503 private ComponentParametersView getBaseComponentParametersView() {
504 ComponentParametersView componentParametersView = new ComponentParametersView();
505 componentParametersView.disableAll();
506 componentParametersView.setIgnoreInputs(false);
507 componentParametersView.setIgnoreComponentInstances(false);
508 componentParametersView.setIgnoreComponentInstancesInputs(false);
509 componentParametersView.setIgnoreComponentInstancesProperties(false);
510 componentParametersView.setIgnorePolicies(false);
511 componentParametersView.setIgnoreGroups(false);
512 componentParametersView.setIgnoreUsers(false);
513 return componentParametersView;
516 private Component getAndValidateComponentForCreate(
517 String userId, String componentId, ComponentTypeEnum componentType, boolean shouldLockComp
519 ComponentParametersView componentParametersView = getBaseComponentParametersView();
520 Component component = validateComponentExists(componentId, componentType, componentParametersView);
521 if (shouldLockComp) {
522 // lock the component
523 lockComponent(component, CREATE_INPUT);
525 validateCanWorkOnComponent(component, userId);
529 private DataTypeDefinition prepareDataTypeForListInput(ComponentInstInputsMap inputsMap, InputDefinition input) {
530 // Confirm if type is list
531 if (StringUtils.isEmpty(input.getType()) || !input.getType().equals(ToscaPropertyType.LIST.getType())) {
532 log.debug("#prepareDataTypeForListInput: Type of input is not list.");
533 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_TYPE));
536 // Confirm schema type is not empty
537 String desiredTypeName = input.getSchemaType();
538 if (StringUtils.isEmpty(desiredTypeName)) {
539 log.debug("#prepareDataTypeForListInput: Schema type of list input is empty.");
540 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_INNER_TYPE));
543 DataTypeDefinition dataType = new DataTypeDefinition();
544 List<ComponentInstancePropInput> propInputs = inputsMap.resolvePropertiesToDeclare().getRight();
545 dataType.setName(desiredTypeName);
546 dataType.setDerivedFromName(ToscaPropertyType.ROOT.getType());
547 // Copy properties from inputsMap
548 dataType.setProperties(propInputs.stream().map(PropertyDefinition::new).collect(Collectors.toList()));
552 private Either<List<InputDefinition>, StorageOperationStatus> prepareInputsForCreation(String userId, String cmptId,
553 List<InputDefinition> inputsToCreate) {
554 Map<String, InputDefinition> inputsToPersist = MapUtil.toMap(inputsToCreate, InputDefinition::getName);
555 assignOwnerIdToInputs(userId, inputsToPersist);
556 inputsToPersist.values()
557 .forEach(input -> input.setConstraints(componentInstanceBusinessLogic.setInputConstraint(input)));
559 return toscaOperationFacade.addInputsToComponent(inputsToPersist, cmptId)
561 .map(persistedInputs -> inputsToCreate);
564 private void assignOwnerIdToInputs(String userId, Map<String, InputDefinition> inputsToCreate) {
565 inputsToCreate.values().forEach(inputDefinition -> inputDefinition.setOwnerId(userId));
568 public Either<List<InputDefinition>, ResponseFormat> createInputsInGraph(Map<String, InputDefinition> inputs,
569 Component component) {
571 List<InputDefinition> resourceProperties = component.getInputs();
573 final Map<String, DataTypeDefinition> dataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel());
575 for (Map.Entry<String, InputDefinition> inputDefinition : inputs.entrySet()) {
576 String inputName = inputDefinition.getKey();
577 inputDefinition.getValue().setName(inputName);
579 Either<InputDefinition, ResponseFormat> preparedInputEither = prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes);
580 if (preparedInputEither.isRight()) {
581 return Either.right(preparedInputEither.right().value());
585 if (resourceProperties != null) {
586 Map<String, InputDefinition> generatedInputs = resourceProperties.stream()
587 .collect(Collectors.toMap(PropertyDataDefinition::getName, i -> i));
588 Either<Map<String, InputDefinition>, String> mergeEither = ToscaDataDefinition.mergeDataMaps(generatedInputs, inputs);
589 if (mergeEither.isRight()) {
590 return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_ALREADY_EXIST, mergeEither.right().value()));
592 inputs = mergeEither.left().value();
595 Either<List<InputDefinition>, StorageOperationStatus> associateInputsEither = toscaOperationFacade
596 .createAndAssociateInputs(inputs, component.getUniqueId());
597 if (associateInputsEither.isRight()) {
598 log.debug("Failed to create inputs under component {}. Status is {}", component.getUniqueId(), associateInputsEither.right().value());
600 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(associateInputsEither.right().value())));
602 return Either.left(associateInputsEither.left().value());
605 private Either<List<InputDefinition>, ResponseFormat> createListInputsInGraph(Map<String, InputDefinition> inputs,
606 Map<String, DataTypeDefinition> privateDataTypes,
607 Component component) {
609 log.trace("#createListInputsInGraph: enter");
611 Map<String, DataTypeDefinition> dataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel());
612 dataTypes.putAll(privateDataTypes);
614 for (Map.Entry<String, InputDefinition> inputDefinition : inputs.entrySet()) {
615 String inputName = inputDefinition.getKey();
616 inputDefinition.getValue().setName(inputName);
618 Either<InputDefinition, ResponseFormat> preparedInputEither =
619 prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes);
620 if (preparedInputEither.isRight()) {
621 return Either.right(preparedInputEither.right().value());
625 Either<List<InputDefinition>, StorageOperationStatus> addInputsEither = toscaOperationFacade
626 .addInputsToComponent(inputs, component.getUniqueId());
627 if (addInputsEither.isRight()) {
628 log.debug("#createListInputsInGraph: Failed to create inputs under component {}. Status is {}",
629 component.getUniqueId(), addInputsEither.right().value());
630 return Either.right(componentsUtils.getResponseFormat(
631 componentsUtils.convertFromStorageResponse(addInputsEither.right().value())));
633 log.trace("#createListInputsInGraph: leave");
634 return Either.left(addInputsEither.left().value());
638 * Delete input from service
645 public InputDefinition deleteInput(String componentId, String userId, String inputId) {
646 Either<InputDefinition, ResponseFormat> deleteEither = null;
647 if (log.isDebugEnabled()) {
648 log.debug("Going to delete input id: {}", inputId);
650 validateUserExists(userId);
651 ComponentParametersView componentParametersView = getBaseComponentParametersView();
652 componentParametersView.setIgnoreInterfaces(false);
653 componentParametersView.setIgnoreDataType(false);
654 componentParametersView.setIgnoreProperties(false);
655 Either<Component, StorageOperationStatus> componentEither = toscaOperationFacade
656 .getToscaElement(componentId, componentParametersView);
657 if (componentEither.isRight()) {
658 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(componentEither.right().value()));
660 Component component = componentEither.left().value();
661 // Validate inputId is child of the component
662 Optional<InputDefinition> optionalInput = component.getInputs().stream().
664 filter(input -> input.getUniqueId().equals(inputId)).
667 if (!optionalInput.isPresent()) {
668 throw new ByActionStatusComponentException(ActionStatus.INPUT_IS_NOT_CHILD_OF_COMPONENT, inputId, componentId);
670 InputDefinition inputForDelete = optionalInput.get();
672 lockComponent(componentId, component, "deleteInput");
673 // Delete input operations
674 boolean failed = false;
676 StorageOperationStatus status = toscaOperationFacade.deleteInputOfResource(component, inputForDelete.getName());
677 if (status != StorageOperationStatus.OK) {
678 log.debug("Component id: {} delete input id: {} failed", componentId, inputId);
679 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status), component.getName());
681 if (BooleanUtils.isTrue(inputForDelete.getIsDeclaredListInput())) {
682 deleteEither = deleteListInput(componentId, inputId, component, inputForDelete, status);
683 if (deleteEither.isRight()) {
684 throw new ByResponseFormatComponentException(deleteEither.right().value());
686 return deleteEither.left().value();
688 StorageOperationStatus storageOperationStatus = propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(component, inputForDelete);
689 if (storageOperationStatus != StorageOperationStatus.OK) {
690 log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId);
691 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(storageOperationStatus), component.getName());
693 return inputForDelete;
694 } catch (ComponentException e) {
698 unlockComponent(failed, component);
702 private Either<InputDefinition, ResponseFormat> deleteListInput(String componentId, String inputId,
703 Component component, InputDefinition inputForDelete,
704 StorageOperationStatus status) {
705 // the input is created by 'Declare List'.
706 // need to 1. undeclare properties, 2. delete input, 3. delete private data type
707 StorageOperationStatus storageOperationStatus = propertyDeclarationOrchestrator.unDeclarePropertiesAsListInputs(component, inputForDelete);
708 if (storageOperationStatus != StorageOperationStatus.OK) {
709 log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId);
710 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), component.getName()));
712 Either<DataTypeDefinition, StorageOperationStatus> deleteResult = dataTypeBusinessLogic
713 .deletePrivateDataType(component, inputForDelete.getSchemaType());
714 if (deleteResult.isRight()) {
715 log.debug("Component id: {} delete datatype name: {} failed", componentId, inputForDelete.getSchemaType());
717 componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteResult.right().value()), component.getName()));
719 log.trace("deleteInput: deletePrivateDataType (OK)");
720 return Either.left(inputForDelete);
723 private Either<InputDefinition, ResponseFormat> prepareAndValidateInputBeforeCreate(InputDefinition newInputDefinition,
724 Map<String, DataTypeDefinition> dataTypes) {
725 // validate input default values
726 Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newInputDefinition, dataTypes);
727 if (defaultValuesValidation.isRight()) {
728 return Either.right(defaultValuesValidation.right().value());
731 ToscaPropertyType type = getType(newInputDefinition.getType());
733 PropertyValueConverter converter = type.getConverter();
735 SchemaDefinition schema = newInputDefinition.getSchema();
736 String innerType = null;
737 if (schema != null) {
738 PropertyDataDefinition prop = schema.getProperty();
740 innerType = prop.getType();
743 String convertedValue;
744 if (newInputDefinition.getDefaultValue() != null) {
745 convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, dataTypes);
746 newInputDefinition.setDefaultValue(convertedValue);
749 return Either.left(newInputDefinition);
752 public Either<InputDefinition, ResponseFormat> getInputsAndPropertiesForComponentInput(String userId, String componentId, String inputId,
753 boolean inTransaction) {
754 Either<InputDefinition, ResponseFormat> result = null;
756 validateUserExists(userId);
757 ComponentParametersView filters = new ComponentParametersView();
758 filters.disableAll();
759 filters.setIgnoreComponentInstances(false);
760 filters.setIgnoreInputs(false);
761 filters.setIgnoreComponentInstancesInputs(false);
762 filters.setIgnoreComponentInstancesProperties(false);
763 filters.setIgnoreProperties(false);
764 Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
765 .getToscaElement(componentId, filters);
766 if (getComponentEither.isRight()) {
767 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
768 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
769 return Either.right(componentsUtils.getResponseFormat(actionStatus));
771 Component component = getComponentEither.left().value();
772 Optional<InputDefinition> op = component.getInputs().stream().filter(in -> in.getUniqueId().equals(inputId)).findFirst();
773 if (!op.isPresent()) {
774 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
775 log.debug(FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR, inputId, componentId, actionStatus);
776 return Either.right(componentsUtils.getResponseFormat(actionStatus));
778 InputDefinition resObj = op.get();
779 List<ComponentInstanceInput> inputCIInput = componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(component, inputId);
780 resObj.setInputs(inputCIInput);
781 List<ComponentInstanceProperty> inputProps = componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(component, inputId);
782 resObj.setProperties(inputProps);
783 result = Either.left(resObj);
786 if (!inTransaction) {
787 if (result == null || result.isRight()) {
788 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
789 janusGraphDao.rollback();
791 log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
792 janusGraphDao.commit();
798 public Either<EntryData<String, InputDefinition>, ResponseFormat> addInputToComponent(String componentId, String inputName,
799 InputDefinition newInputDefinition, String userId) {
800 Either<EntryData<String, InputDefinition>, ResponseFormat> result = null;
801 validateUserExists(userId);
802 Either<Component, StorageOperationStatus> serviceElement = toscaOperationFacade.getToscaElement(componentId);
803 if (serviceElement.isRight()) {
804 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
807 Component component = serviceElement.left().value();
808 NodeTypeEnum nodeType = component.getComponentType().getNodeType();
809 StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType);
810 if (!lockResult.equals(StorageOperationStatus.OK)) {
811 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_INPUT, nodeType.name().toLowerCase(), componentId);
812 log.info("Failed to lock component {}. Error - {}", componentId, lockResult);
813 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
817 if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) {
818 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
821 List<InputDefinition> inputs = component.getInputs();
822 if (CollectionUtils.isEmpty(inputs)) {
823 inputs = new ArrayList<>();
825 if (isInputExistInComponent(inputs, inputName)) {
826 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUT_ALREADY_EXIST, inputName));
829 Map<String, DataTypeDefinition> allDataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel());
830 // validate input default values
831 Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newInputDefinition, allDataTypes);
832 if (defaultValuesValidation.isRight()) {
833 result = Either.right(defaultValuesValidation.right().value());
837 ToscaPropertyType type = getType(newInputDefinition.getType());
839 PropertyValueConverter converter = type.getConverter();
841 String innerType = null;
842 SchemaDefinition schema = newInputDefinition.getSchema();
843 if (schema != null) {
844 PropertyDataDefinition prop = schema.getProperty();
846 innerType = prop.getType();
849 if (newInputDefinition.getDefaultValue() != null) {
850 String convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, allDataTypes);
851 newInputDefinition.setDefaultValue(convertedValue);
854 newInputDefinition.setMappedToComponentProperty(false);
855 Either<InputDefinition, StorageOperationStatus> addInputEither = toscaOperationFacade
856 .addInputToComponent(inputName, newInputDefinition, component);
857 if (addInputEither.isRight()) {
858 log.info("Failed to add new input {}. Error - {}", componentId, addInputEither.right().value());
859 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
862 result = Either.left(new EntryData<>(inputName, newInputDefinition));
865 commitOrRollback(result);
867 graphLockOperation.unlockComponent(componentId, nodeType);
871 private boolean isInputExistInComponent(List<InputDefinition> inputs, String inputName) {
872 return CollectionUtils.isNotEmpty(inputs) && inputs.stream().anyMatch(input -> input.getName().equals(inputName));