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 GET_PROPERTIES_BY_INPUT = "get Properties by input";
95 private static final String FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR = "Failed to found input {} under component {}, error: {}";
96 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP = "Going to execute rollback on create group.";
97 private static final String GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP = "Going to execute commit on create group.";
98 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_UPDATE_INPUT = "Going to execute rollback on update input.";
99 private static final String GOING_TO_EXECUTE_COMMIT_ON_UPDATE_INPUT = "Going to execute commit on update input.";
100 private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(InputsBusinessLogic.class.getName());
101 private final PropertyDeclarationOrchestrator propertyDeclarationOrchestrator;
102 private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
103 private final DataTypeBusinessLogic dataTypeBusinessLogic;
106 public InputsBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
107 IGroupTypeOperation groupTypeOperation, InterfaceOperation interfaceOperation,
108 InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
109 PropertyDeclarationOrchestrator propertyDeclarationOrchestrator,
110 ComponentInstanceBusinessLogic componentInstanceBusinessLogic, DataTypeBusinessLogic dataTypeBusinessLogic,
111 ArtifactsOperations artifactToscaOperation) {
112 super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
113 artifactToscaOperation);
114 this.propertyDeclarationOrchestrator = propertyDeclarationOrchestrator;
115 this.componentInstanceBusinessLogic = componentInstanceBusinessLogic;
116 this.dataTypeBusinessLogic = dataTypeBusinessLogic;
120 * associate inputs to a given component with paging
126 public Either<List<InputDefinition>, ResponseFormat> getInputs(String userId, String componentId) {
127 validateUserExists(userId);
128 ComponentParametersView filters = new ComponentParametersView();
129 filters.disableAll();
130 filters.setIgnoreInputs(false);
131 Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
132 .getToscaElement(componentId, filters);
133 if (getComponentEither.isRight()) {
134 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
135 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
136 return Either.right(componentsUtils.getResponseFormat(actionStatus));
138 org.openecomp.sdc.be.model.Component component = getComponentEither.left().value();
139 List<InputDefinition> inputs = component.getInputs();
140 return Either.left(inputs);
143 public Either<List<ComponentInstanceInput>, ResponseFormat> getComponentInstanceInputs(String userId, String componentId,
144 String componentInstanceId) {
145 validateUserExists(userId);
146 ComponentParametersView filters = new ComponentParametersView();
147 filters.disableAll();
148 filters.setIgnoreInputs(false);
149 filters.setIgnoreComponentInstances(false);
150 filters.setIgnoreComponentInstancesInputs(false);
151 Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
152 .getToscaElement(componentId, filters);
153 if (getComponentEither.isRight()) {
154 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
155 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
156 return Either.right(componentsUtils.getResponseFormat(actionStatus));
158 org.openecomp.sdc.be.model.Component component = getComponentEither.left().value();
159 if (!ComponentValidations.validateComponentInstanceExist(component, componentInstanceId)) {
160 ActionStatus actionStatus = ActionStatus.COMPONENT_INSTANCE_NOT_FOUND;
161 log.debug("Failed to found component instance inputs {}, error: {}", componentInstanceId, actionStatus);
162 loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, component.getComponentMetadataForSupportLog(), StatusCode.ERROR,
163 "Failed to found component instance inputs componentInstanceId: {}", componentInstanceId);
164 return Either.right(componentsUtils.getResponseFormat(actionStatus));
166 Map<String, List<ComponentInstanceInput>> ciInputs = Optional.ofNullable(component.getComponentInstancesInputs())
167 .orElse(Collections.emptyMap());
168 // Set Constraints on Input
169 MapUtils.emptyIfNull(ciInputs).values()
170 .forEach(inputs -> ListUtils.emptyIfNull(inputs).forEach(input -> input.setConstraints(setInputConstraint(input))));
171 return Either.left(ciInputs.getOrDefault(componentInstanceId, Collections.emptyList()));
175 * associate properties to a given component instance input
182 public Either<List<ComponentInstanceProperty>, ResponseFormat> getComponentInstancePropertiesByInputId(String userId, String componentId,
183 String instanceId, String inputId) {
184 validateUserExists(userId);
185 String parentId = componentId;
186 org.openecomp.sdc.be.model.Component component;
187 ComponentParametersView filters = new ComponentParametersView();
188 filters.disableAll();
189 filters.setIgnoreComponentInstances(false);
190 if (!instanceId.equals(inputId)) {
191 Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
192 .getToscaElement(parentId, filters);
193 if (getComponentEither.isRight()) {
194 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
195 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, parentId, actionStatus);
196 return Either.right(componentsUtils.getResponseFormat(actionStatus));
198 component = getComponentEither.left().value();
199 Optional<ComponentInstance> ciOp = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(instanceId)).findAny();
200 if (ciOp.isPresent()) {
201 parentId = ciOp.get().getComponentUid();
204 filters.setIgnoreInputs(false);
205 filters.setIgnoreComponentInstancesProperties(false);
206 filters.setIgnoreComponentInstancesInputs(false);
207 filters.setIgnoreProperties(false);
208 Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
209 .getToscaElement(parentId, filters);
210 if (getComponentEither.isRight()) {
211 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
212 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, parentId, actionStatus);
213 return Either.right(componentsUtils.getResponseFormat(actionStatus));
215 component = getComponentEither.left().value();
216 Optional<InputDefinition> op = component.getInputs().stream().filter(in -> in.getUniqueId().equals(inputId)).findFirst();
217 if (!op.isPresent()) {
218 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
219 log.debug(FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR, inputId, parentId, actionStatus);
220 return Either.right(componentsUtils.getResponseFormat(actionStatus));
222 return Either.left(componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(component, inputId));
225 private String updateInputObjectValue(InputDefinition currentInput, InputDefinition newInput, Map<String, DataTypeDefinition> dataTypes) {
226 String innerType = null;
227 String propertyType = currentInput.getType();
228 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
229 log.debug("The type of the property {} is {}", currentInput.getUniqueId(), propertyType);
230 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
231 SchemaDefinition def = currentInput.getSchema();
233 log.debug("Schema doesn't exists for property of type {}", type);
234 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE));
236 PropertyDataDefinition propDef = def.getProperty();
237 if (propDef == null) {
238 log.debug("Property in Schema Definition inside property of type {} doesn't exist", type);
239 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE));
241 innerType = propDef.getType();
243 // Specific Update Logic
244 Either<Object, Boolean> isValid = propertyOperation
245 .validateAndUpdatePropertyValue(propertyType, newInput.getDefaultValue(), true, innerType, dataTypes);
246 String newValue = newInput.getDefaultValue();
247 if (isValid.isRight()) {
248 Boolean res = isValid.right().value();
249 if (Boolean.FALSE.equals(res)) {
250 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(
251 DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)));
254 Object object = isValid.left().value();
255 if (object != null) {
256 newValue = object.toString();
262 private InputDefinition getInputFromInputsListById(List<InputDefinition> componentsOldInputs, InputDefinition input) {
263 return componentsOldInputs.stream().filter(in -> in.getUniqueId().equals(input.getUniqueId())).findFirst().orElse(null);
266 public Either<List<InputDefinition>, ResponseFormat> updateInputsValue(ComponentTypeEnum componentType, String componentId,
267 List<InputDefinition> inputs, String userId, boolean shouldLockComp,
268 boolean inTransaction) {
269 List<InputDefinition> returnInputs = new ArrayList<>();
270 Either<List<InputDefinition>, ResponseFormat> result = null;
271 org.openecomp.sdc.be.model.Component component = null;
273 validateUserExists(userId);
274 ComponentParametersView componentParametersView = new ComponentParametersView();
275 componentParametersView.disableAll();
276 componentParametersView.setIgnoreInputs(false);
277 componentParametersView.setIgnoreUsers(false);
278 componentParametersView.setIgnoreProperties(false);
279 componentParametersView.setIgnoreComponentInstancesProperties(false);
280 componentParametersView.setIgnoreComponentInstances(false);
281 component = validateComponentExists(componentId, componentType, componentParametersView);
282 if (shouldLockComp) {
284 lockComponent(component, UPDATE_INPUT);
285 } catch (ComponentException e) {
286 log.error("Failed to lock component", e);
287 result = Either.right(e.getResponseFormat());
291 //Validate value and Constraint of input
292 Either<Boolean, ResponseFormat> constraintValidatorResponse = validateInputValueConstraint(inputs);
293 if (constraintValidatorResponse.isRight()) {
294 log.error("Failed validation value and constraint of property: {}", constraintValidatorResponse.right().value());
295 return Either.right(constraintValidatorResponse.right().value());
297 validateCanWorkOnComponent(component, userId);
298 Map<String, DataTypeDefinition> dataTypes;
299 dataTypes = getAllDataTypes(applicationDataTypeCache);
300 List<InputDefinition> componentsOldInputs = Optional.ofNullable(component.getInputs()).orElse(Collections.emptyList());
301 for (InputDefinition newInput : inputs) {
302 InputDefinition currInput = getInputFromInputsListById(componentsOldInputs, newInput);
303 if (currInput == null) {
304 ActionStatus actionStatus = ActionStatus.COMPONENT_NOT_FOUND;
305 log.debug("Failed to found newInput {} under component {}, error: {}", newInput.getUniqueId(), componentId, actionStatus);
306 result = Either.right(componentsUtils.getResponseFormat(actionStatus));
309 String updateInputObjectValue = updateInputObjectValue(currInput, newInput, dataTypes);
310 currInput.setDefaultValue(updateInputObjectValue);
311 currInput.setOwnerId(userId);
312 currInput.setMetadata(newInput.getMetadata());
313 if (newInput.isRequired() != null) {
314 currInput.setRequired(newInput.isRequired());
316 Either<InputDefinition, StorageOperationStatus> status = toscaOperationFacade.updateInputOfComponent(component, currInput);
317 if (status.isRight()) {
318 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForResourceInstanceProperty(status.right().value());
319 result = Either.right(componentsUtils.getResponseFormat(actionStatus, ""));
322 returnInputs.add(status.left().value());
325 result = Either.left(returnInputs);
326 } catch (ComponentException e) {
327 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_UPDATE_INPUT);
328 unlockRollbackWithException(component, e);
329 } catch (Exception e) {
330 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_UPDATE_INPUT);
331 unlockRollbackWithException(component, new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR));
333 log.debug(GOING_TO_EXECUTE_COMMIT_ON_UPDATE_INPUT);
334 unlockWithCommit(component);
338 private Either<Boolean, ResponseFormat> validateInputValueConstraint(List<InputDefinition> inputs) {
339 PropertyValueConstraintValidationUtil propertyValueConstraintValidationUtil = PropertyValueConstraintValidationUtil.getInstance();
340 List<InputDefinition> inputDefinitions = new ArrayList<>();
341 for (InputDefinition inputDefinition : inputs) {
342 InputDefinition inputDef = new InputDefinition();
343 inputDefinition.setDefaultValue(inputDefinition.getDefaultValue());
344 inputDefinition.setInputPath(inputDefinition.getSubPropertyInputPath());
345 inputDefinition.setType(inputDefinition.getType());
346 if (Objects.nonNull(inputDefinition.getParentPropertyType())) {
347 ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty();
348 propertyDefinition.setType(inputDefinition.getParentPropertyType());
349 inputDefinition.setProperties(Collections.singletonList(propertyDefinition));
351 inputDefinitions.add(inputDef);
353 return propertyValueConstraintValidationUtil.validatePropertyConstraints(inputDefinitions, applicationDataTypeCache);
356 public Either<List<ComponentInstanceInput>, ResponseFormat> getInputsForComponentInput(String userId, String componentId, String inputId) {
357 validateUserExists(userId);
358 org.openecomp.sdc.be.model.Component component = null;
359 ComponentParametersView filters = new ComponentParametersView();
360 filters.disableAll();
361 filters.setIgnoreComponentInstances(false);
362 filters.setIgnoreInputs(false);
363 filters.setIgnoreComponentInstancesInputs(false);
364 filters.setIgnoreProperties(false);
365 Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
366 .getToscaElement(componentId, filters);
367 if (getComponentEither.isRight()) {
368 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
369 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
370 return Either.right(componentsUtils.getResponseFormat(actionStatus));
372 component = getComponentEither.left().value();
373 Optional<InputDefinition> op = component.getInputs().stream().filter(in -> in.getUniqueId().equals(inputId)).findFirst();
374 if (!op.isPresent()) {
375 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
376 log.debug(FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR, inputId, componentId, actionStatus);
377 return Either.right(componentsUtils.getResponseFormat(actionStatus));
379 return Either.left(componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(component, inputId));
383 public Either<List<InputDefinition>, ResponseFormat> declareProperties(String userId, String componentId, ComponentTypeEnum componentTypeEnum,
384 ComponentInstInputsMap componentInstInputsMap) {
385 return createMultipleInputs(userId, componentId, componentTypeEnum, componentInstInputsMap, true, false);
388 public Either<List<InputDefinition>, ResponseFormat> createMultipleInputs(String userId, String componentId, ComponentTypeEnum componentType,
389 ComponentInstInputsMap componentInstInputsMapUi, boolean shouldLockComp,
390 boolean inTransaction) {
391 Either<List<InputDefinition>, ResponseFormat> result = null;
392 org.openecomp.sdc.be.model.Component component = null;
394 validateUserExists(userId);
395 component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
396 result = propertyDeclarationOrchestrator.declarePropertiesToInputs(component, componentInstInputsMapUi).left()
397 .bind(inputsToCreate -> prepareInputsForCreation(userId, componentId, inputsToCreate)).right()
398 .map(componentsUtils::getResponseFormat);
400 } catch (ByResponseFormatComponentException e) {
401 log.error("#createMultipleInputs: Exception thrown: ", e);
402 result = Either.right(e.getResponseFormat());
405 if (!inTransaction) {
406 if (result == null || result.isRight()) {
407 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
408 janusGraphDao.rollback();
410 log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
411 janusGraphDao.commit();
415 if (shouldLockComp && component != null) {
416 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
422 * Creates a list input with a data type which has properties specified.
424 * @param userId User ID
425 * @param componentId Component ID
426 * @param componentType Component type
427 * @param componentListInput Properties to be declared and input to be created
428 * @param shouldLockComp true if the component should be locked
429 * @param inTransaction true if already in transaction
431 public Either<List<InputDefinition>, ResponseFormat> createListInput(String userId, String componentId, ComponentTypeEnum componentType,
432 ComponentInstListInput componentListInput, boolean shouldLockComp,
433 boolean inTransaction) {
434 Either<List<InputDefinition>, ResponseFormat> result = null;
435 org.openecomp.sdc.be.model.Component component = null;
436 log.trace("#createListInput: enter");
438 /* check if user exists */
439 validateUserExists(userId);
441 component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
443 InputDefinition listInput = componentListInput.getListInput();
444 DataTypeDefinition dataType =
445 prepareDataTypeForListInput(componentListInput.getComponentInstInputsMap(), listInput);
446 Map<String, DataTypeDefinition> dataTypesMap = new HashMap<>();
447 dataTypesMap.put(dataType.getName(), dataType);
448 if (log.isDebugEnabled()) {
449 log.debug("#createListInput: dataTypesMap={}", ReflectionToStringBuilder.toString(dataTypesMap));
452 Either<List<DataTypeDefinition>, StorageOperationStatus> dataTypeResult =
453 toscaOperationFacade.addDataTypesToComponent(dataTypesMap, componentId);
454 if (dataTypeResult.isRight()) {
455 log.debug("#createListInput: DataType creation failed.");
456 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(dataTypeResult.right().value()));
460 listInput.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(componentId, listInput.getName()));
461 listInput.setInstanceUniqueId(
462 propertyDeclarationOrchestrator.getPropOwnerId(componentListInput.getComponentInstInputsMap()));
463 listInput.setIsDeclaredListInput(true);
464 Map<String, InputDefinition> listInputMap = new HashMap<>();
465 listInputMap.put(listInput.getName(), listInput);
466 result = createListInputsInGraph(listInputMap, dataTypesMap, component);
467 if (result.isRight()) {
468 log.debug("#createListInput: createListInputsInGraph failed.");
469 throw new ByResponseFormatComponentException(result.right().value());
473 result = propertyDeclarationOrchestrator
474 .declarePropertiesToListInput(component, componentListInput.getComponentInstInputsMap(), listInput)
475 .right().map(err -> componentsUtils.getResponseFormat(err))
476 .left().map(Arrays::asList);
478 log.trace("#createListInput: leave");
482 } catch (ByResponseFormatComponentException e) {
483 log.error("#createListInput: Exception thrown", e);
484 result = Either.right(e.getResponseFormat());
488 if (!inTransaction) {
489 if (result == null || result.isRight()) {
490 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
491 janusGraphDao.rollback();
493 log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
494 janusGraphDao.commit();
498 if (shouldLockComp && component != null) {
499 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
504 private ComponentParametersView getBaseComponentParametersView() {
505 ComponentParametersView componentParametersView = new ComponentParametersView();
506 componentParametersView.disableAll();
507 componentParametersView.setIgnoreInputs(false);
508 componentParametersView.setIgnoreComponentInstances(false);
509 componentParametersView.setIgnoreComponentInstancesInputs(false);
510 componentParametersView.setIgnoreComponentInstancesProperties(false);
511 componentParametersView.setIgnorePolicies(false);
512 componentParametersView.setIgnoreGroups(false);
513 componentParametersView.setIgnoreUsers(false);
514 return componentParametersView;
517 private org.openecomp.sdc.be.model.Component getAndValidateComponentForCreate(
518 String userId, String componentId, ComponentTypeEnum componentType, boolean shouldLockComp
520 ComponentParametersView componentParametersView = getBaseComponentParametersView();
521 org.openecomp.sdc.be.model.Component component = validateComponentExists(componentId, componentType, componentParametersView);
522 if (shouldLockComp) {
523 // lock the component
524 lockComponent(component, CREATE_INPUT);
526 validateCanWorkOnComponent(component, userId);
530 private DataTypeDefinition prepareDataTypeForListInput(ComponentInstInputsMap inputsMap, InputDefinition input) {
531 // Confirm if type is list
532 if (StringUtils.isEmpty(input.getType()) || !input.getType().equals(ToscaPropertyType.LIST.getType())) {
533 log.debug("#prepareDataTypeForListInput: Type of input is not list.");
534 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_TYPE));
537 // Confirm schema type is not empty
538 String desiredTypeName = input.getSchemaType();
539 if (StringUtils.isEmpty(desiredTypeName)) {
540 log.debug("#prepareDataTypeForListInput: Schema type of list input is empty.");
541 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_INNER_TYPE));
544 DataTypeDefinition dataType = new DataTypeDefinition();
545 List<ComponentInstancePropInput> propInputs = inputsMap.resolvePropertiesToDeclare().getRight();
546 dataType.setName(desiredTypeName);
547 dataType.setDerivedFromName(ToscaPropertyType.ROOT.getType());
548 // Copy properties from inputsMap
549 dataType.setProperties(propInputs.stream().map(PropertyDefinition::new).collect(Collectors.toList()));
553 private Either<List<InputDefinition>, StorageOperationStatus> prepareInputsForCreation(String userId, String cmptId,
554 List<InputDefinition> inputsToCreate) {
555 Map<String, InputDefinition> inputsToPersist = MapUtil.toMap(inputsToCreate, InputDefinition::getName);
556 assignOwnerIdToInputs(userId, inputsToPersist);
557 inputsToPersist.values()
558 .forEach(input -> input.setConstraints(componentInstanceBusinessLogic.setInputConstraint(input)));
560 return toscaOperationFacade.addInputsToComponent(inputsToPersist, cmptId)
562 .map(persistedInputs -> inputsToCreate);
565 private void assignOwnerIdToInputs(String userId, Map<String, InputDefinition> inputsToCreate) {
566 inputsToCreate.values().forEach(inputDefinition -> inputDefinition.setOwnerId(userId));
569 public Either<List<InputDefinition>, ResponseFormat> createInputsInGraph(Map<String, InputDefinition> inputs,
570 org.openecomp.sdc.be.model.Component component) {
572 List<InputDefinition> resourceProperties = component.getInputs();
574 Map<String, DataTypeDefinition> dataTypes = getAllDataTypes(applicationDataTypeCache);
576 for (Map.Entry<String, InputDefinition> inputDefinition : inputs.entrySet()) {
577 String inputName = inputDefinition.getKey();
578 inputDefinition.getValue().setName(inputName);
580 Either<InputDefinition, ResponseFormat> preparedInputEither = prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes);
581 if (preparedInputEither.isRight()) {
582 return Either.right(preparedInputEither.right().value());
586 if (resourceProperties != null) {
587 Map<String, InputDefinition> generatedInputs = resourceProperties.stream()
588 .collect(Collectors.toMap(PropertyDataDefinition::getName, i -> i));
589 Either<Map<String, InputDefinition>, String> mergeEither = ToscaDataDefinition.mergeDataMaps(generatedInputs, inputs);
590 if (mergeEither.isRight()) {
591 return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_ALREADY_EXIST, mergeEither.right().value()));
593 inputs = mergeEither.left().value();
596 Either<List<InputDefinition>, StorageOperationStatus> associateInputsEither = toscaOperationFacade
597 .createAndAssociateInputs(inputs, component.getUniqueId());
598 if (associateInputsEither.isRight()) {
599 log.debug("Failed to create inputs under component {}. Status is {}", component.getUniqueId(), associateInputsEither.right().value());
601 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(associateInputsEither.right().value())));
603 return Either.left(associateInputsEither.left().value());
606 private Either<List<InputDefinition>, ResponseFormat> createListInputsInGraph(Map<String, InputDefinition> inputs,
607 Map<String, DataTypeDefinition> privateDataTypes,
608 org.openecomp.sdc.be.model.Component component) {
610 log.trace("#createListInputsInGraph: enter");
612 Map<String, DataTypeDefinition> dataTypes = getAllDataTypes(
613 applicationDataTypeCache);
614 dataTypes.putAll(privateDataTypes);
616 for (Map.Entry<String, InputDefinition> inputDefinition : inputs.entrySet()) {
617 String inputName = inputDefinition.getKey();
618 inputDefinition.getValue().setName(inputName);
620 Either<InputDefinition, ResponseFormat> preparedInputEither =
621 prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes);
622 if (preparedInputEither.isRight()) {
623 return Either.right(preparedInputEither.right().value());
627 Either<List<InputDefinition>, StorageOperationStatus> addInputsEither = toscaOperationFacade
628 .addInputsToComponent(inputs, component.getUniqueId());
629 if (addInputsEither.isRight()) {
630 log.debug("#createListInputsInGraph: Failed to create inputs under component {}. Status is {}",
631 component.getUniqueId(), addInputsEither.right().value());
632 return Either.right(componentsUtils.getResponseFormat(
633 componentsUtils.convertFromStorageResponse(addInputsEither.right().value())));
635 log.trace("#createListInputsInGraph: leave");
636 return Either.left(addInputsEither.left().value());
640 * Delete input from service
647 public InputDefinition deleteInput(String componentId, String userId, String inputId) {
648 Either<InputDefinition, ResponseFormat> deleteEither = null;
649 if (log.isDebugEnabled()) {
650 log.debug("Going to delete input id: {}", inputId);
652 validateUserExists(userId);
653 ComponentParametersView componentParametersView = getBaseComponentParametersView();
654 componentParametersView.setIgnoreInterfaces(false);
655 componentParametersView.setIgnoreDataType(false);
656 componentParametersView.setIgnoreProperties(false);
657 Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentEither = toscaOperationFacade
658 .getToscaElement(componentId, componentParametersView);
659 if (componentEither.isRight()) {
660 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(componentEither.right().value()));
662 org.openecomp.sdc.be.model.Component component = componentEither.left().value();
663 // Validate inputId is child of the component
664 Optional<InputDefinition> optionalInput = component.getInputs().stream().
666 filter(input -> input.getUniqueId().equals(inputId)).
669 if (!optionalInput.isPresent()) {
670 throw new ByActionStatusComponentException(ActionStatus.INPUT_IS_NOT_CHILD_OF_COMPONENT, inputId, componentId);
672 InputDefinition inputForDelete = optionalInput.get();
674 lockComponent(componentId, component, "deleteInput");
675 // Delete input operations
676 boolean failed = false;
678 StorageOperationStatus status = toscaOperationFacade.deleteInputOfResource(component, inputForDelete.getName());
679 if (status != StorageOperationStatus.OK) {
680 log.debug("Component id: {} delete input id: {} failed", componentId, inputId);
681 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status), component.getName());
683 if (BooleanUtils.isTrue(inputForDelete.getIsDeclaredListInput())) {
684 deleteEither = deleteListInput(componentId, inputId, component, inputForDelete, status);
685 if (deleteEither.isRight()) {
686 throw new ByResponseFormatComponentException(deleteEither.right().value());
688 return deleteEither.left().value();
690 StorageOperationStatus storageOperationStatus = propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(component, inputForDelete);
691 if (storageOperationStatus != StorageOperationStatus.OK) {
692 log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId);
693 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(storageOperationStatus), component.getName());
695 return inputForDelete;
696 } catch (ComponentException e) {
700 unlockComponent(failed, component);
704 private Either<InputDefinition, ResponseFormat> deleteListInput(String componentId, String inputId,
705 org.openecomp.sdc.be.model.Component component, InputDefinition inputForDelete,
706 StorageOperationStatus status) {
707 // the input is created by 'Declare List'.
709 // need to 1. undeclare properties, 2. delete input, 3. delete private data type
710 StorageOperationStatus storageOperationStatus = propertyDeclarationOrchestrator.unDeclarePropertiesAsListInputs(component, inputForDelete);
711 if (storageOperationStatus != StorageOperationStatus.OK) {
712 log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId);
713 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), component.getName()));
715 Either<DataTypeDefinition, StorageOperationStatus> deleteResult = dataTypeBusinessLogic
716 .deletePrivateDataType(component, inputForDelete.getSchemaType());
717 if (deleteResult.isRight()) {
718 log.debug("Component id: {} delete datatype name: {} failed", componentId, inputForDelete.getSchemaType());
720 componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteResult.right().value()), component.getName()));
722 log.trace("deleteInput: deletePrivateDataType (OK)");
723 return Either.left(inputForDelete);
726 private Either<InputDefinition, ResponseFormat> prepareAndValidateInputBeforeCreate(InputDefinition newInputDefinition,
727 Map<String, DataTypeDefinition> dataTypes) {
728 // validate input default values
729 Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newInputDefinition, dataTypes);
730 if (defaultValuesValidation.isRight()) {
731 return Either.right(defaultValuesValidation.right().value());
734 ToscaPropertyType type = getType(newInputDefinition.getType());
736 PropertyValueConverter converter = type.getConverter();
738 SchemaDefinition schema = newInputDefinition.getSchema();
739 String innerType = null;
740 if (schema != null) {
741 PropertyDataDefinition prop = schema.getProperty();
743 innerType = prop.getType();
746 String convertedValue;
747 if (newInputDefinition.getDefaultValue() != null) {
748 convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, dataTypes);
749 newInputDefinition.setDefaultValue(convertedValue);
752 return Either.left(newInputDefinition);
755 public Either<InputDefinition, ResponseFormat> getInputsAndPropertiesForComponentInput(String userId, String componentId, String inputId,
756 boolean inTransaction) {
757 Either<InputDefinition, ResponseFormat> result = null;
759 validateUserExists(userId);
760 ComponentParametersView filters = new ComponentParametersView();
761 filters.disableAll();
762 filters.setIgnoreComponentInstances(false);
763 filters.setIgnoreInputs(false);
764 filters.setIgnoreComponentInstancesInputs(false);
765 filters.setIgnoreComponentInstancesProperties(false);
766 filters.setIgnoreProperties(false);
767 Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getComponentEither = toscaOperationFacade
768 .getToscaElement(componentId, filters);
769 if (getComponentEither.isRight()) {
770 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
771 log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
772 return Either.right(componentsUtils.getResponseFormat(actionStatus));
774 org.openecomp.sdc.be.model.Component component = getComponentEither.left().value();
775 Optional<InputDefinition> op = component.getInputs().stream().filter(in -> in.getUniqueId().equals(inputId)).findFirst();
776 if (!op.isPresent()) {
777 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
778 log.debug(FAILED_TO_FOUND_INPUT_UNDER_COMPONENT_ERROR, inputId, componentId, actionStatus);
779 return Either.right(componentsUtils.getResponseFormat(actionStatus));
781 InputDefinition resObj = op.get();
782 List<ComponentInstanceInput> inputCIInput = componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(component, inputId);
783 resObj.setInputs(inputCIInput);
784 List<ComponentInstanceProperty> inputProps = componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(component, inputId);
785 resObj.setProperties(inputProps);
786 result = Either.left(resObj);
789 if (!inTransaction) {
790 if (result == null || result.isRight()) {
791 log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
792 janusGraphDao.rollback();
794 log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
795 janusGraphDao.commit();
801 public Either<EntryData<String, InputDefinition>, ResponseFormat> addInputToComponent(String componentId, String inputName,
802 InputDefinition newInputDefinition, String userId) {
803 Either<EntryData<String, InputDefinition>, ResponseFormat> result = null;
804 validateUserExists(userId);
805 Either<Component, StorageOperationStatus> serviceElement = toscaOperationFacade.getToscaElement(componentId);
806 if (serviceElement.isRight()) {
807 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
810 Component component = serviceElement.left().value();
811 NodeTypeEnum nodeType = component.getComponentType().getNodeType();
812 StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType);
813 if (!lockResult.equals(StorageOperationStatus.OK)) {
814 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_INPUT, nodeType.name().toLowerCase(), componentId);
815 log.info("Failed to lock component {}. Error - {}", componentId, lockResult);
816 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
820 if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) {
821 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
824 List<InputDefinition> inputs = component.getInputs();
825 if (CollectionUtils.isEmpty(inputs)) {
826 inputs = new ArrayList<>();
828 if (isInputExistInComponent(inputs, inputName)) {
829 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUT_ALREADY_EXIST, inputName));
832 Map<String, DataTypeDefinition> allDataTypes = getAllDataTypes(applicationDataTypeCache);
833 // validate input default values
834 Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newInputDefinition, allDataTypes);
835 if (defaultValuesValidation.isRight()) {
836 result = Either.right(defaultValuesValidation.right().value());
840 ToscaPropertyType type = getType(newInputDefinition.getType());
842 PropertyValueConverter converter = type.getConverter();
844 String innerType = null;
845 SchemaDefinition schema = newInputDefinition.getSchema();
846 if (schema != null) {
847 PropertyDataDefinition prop = schema.getProperty();
849 innerType = prop.getType();
852 if (newInputDefinition.getDefaultValue() != null) {
853 String convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, allDataTypes);
854 newInputDefinition.setDefaultValue(convertedValue);
857 newInputDefinition.setMappedToComponentProperty(false);
858 Either<InputDefinition, StorageOperationStatus> addInputEither = toscaOperationFacade
859 .addInputToComponent(inputName, newInputDefinition, component);
860 if (addInputEither.isRight()) {
861 log.info("Failed to add new input {}. Error - {}", componentId, addInputEither.right().value());
862 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
865 result = Either.left(new EntryData<>(inputName, newInputDefinition));
868 commitOrRollback(result);
870 graphLockOperation.unlockComponent(componentId, nodeType);
874 private boolean isInputExistInComponent(List<InputDefinition> inputs, String inputName) {
875 return CollectionUtils.isNotEmpty(inputs) && inputs.stream().anyMatch(input -> input.getName().equals(inputName));