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=========================================================
21 package org.openecomp.sdc.be.model.operations.impl;
23 import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR;
25 import com.fasterxml.jackson.core.ObjectCodec;
26 import com.fasterxml.jackson.databind.DeserializationContext;
27 import com.fasterxml.jackson.databind.JsonNode;
28 import com.fasterxml.jackson.databind.node.ArrayNode;
29 import com.fasterxml.jackson.databind.node.JsonNodeType;
30 import com.google.common.collect.Maps;
31 import com.google.gson.JsonArray;
32 import com.google.gson.JsonDeserializationContext;
33 import com.google.gson.JsonDeserializer;
34 import com.google.gson.JsonElement;
35 import com.google.gson.JsonObject;
36 import com.google.gson.JsonParseException;
37 import com.google.gson.JsonParser;
38 import com.google.gson.JsonPrimitive;
39 import com.google.gson.JsonSerializationContext;
40 import com.google.gson.JsonSerializer;
41 import com.google.gson.JsonSyntaxException;
42 import fj.data.Either;
43 import java.io.IOException;
44 import java.lang.reflect.InvocationTargetException;
45 import java.lang.reflect.Type;
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.Collection;
49 import java.util.Collections;
50 import java.util.HashMap;
51 import java.util.Iterator;
52 import java.util.List;
54 import java.util.Map.Entry;
56 import java.util.function.Consumer;
57 import java.util.regex.Matcher;
58 import java.util.regex.Pattern;
59 import java.util.stream.Collectors;
60 import org.apache.commons.collections.CollectionUtils;
61 import org.apache.commons.collections.MapUtils;
62 import org.apache.commons.lang3.StringUtils;
63 import org.apache.commons.lang3.tuple.ImmutablePair;
64 import org.apache.tinkerpop.gremlin.structure.Edge;
65 import org.apache.tinkerpop.gremlin.structure.Vertex;
66 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
67 import org.janusgraph.core.JanusGraph;
68 import org.janusgraph.core.JanusGraphVertex;
69 import org.janusgraph.core.JanusGraphVertexProperty;
70 import org.openecomp.sdc.be.config.BeEcompErrorManager;
71 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
72 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
73 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
74 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
75 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
76 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
77 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
78 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
79 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
80 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
81 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
82 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
83 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
84 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
85 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
86 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
87 import org.openecomp.sdc.be.model.Component;
88 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
89 import org.openecomp.sdc.be.model.DataTypeDefinition;
90 import org.openecomp.sdc.be.model.IComplexDefaultValue;
91 import org.openecomp.sdc.be.model.PropertyConstraint;
92 import org.openecomp.sdc.be.model.PropertyDefinition;
93 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
94 import org.openecomp.sdc.be.model.operations.api.IPropertyOperation;
95 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
96 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
97 import org.openecomp.sdc.be.model.tosca.ToscaType;
98 import org.openecomp.sdc.be.model.tosca.constraints.ConstraintUtil;
99 import org.openecomp.sdc.be.model.tosca.constraints.EqualConstraint;
100 import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint;
101 import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
102 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
103 import org.openecomp.sdc.be.model.tosca.constraints.LengthConstraint;
104 import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
105 import org.openecomp.sdc.be.model.tosca.constraints.LessThanConstraint;
106 import org.openecomp.sdc.be.model.tosca.constraints.MaxLengthConstraint;
107 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
108 import org.openecomp.sdc.be.model.tosca.constraints.PatternConstraint;
109 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
110 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
111 import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator;
112 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
113 import org.openecomp.sdc.be.resources.data.DataTypeData;
114 import org.openecomp.sdc.be.resources.data.ModelData;
115 import org.openecomp.sdc.be.resources.data.PropertyData;
116 import org.openecomp.sdc.be.resources.data.PropertyValueData;
117 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
118 import org.openecomp.sdc.be.resources.data.UniqueIdData;
119 import org.openecomp.sdc.common.log.wrappers.Logger;
120 import org.springframework.beans.factory.annotation.Autowired;
122 @org.springframework.stereotype.Component("property-operation")
123 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
125 private static final String AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS = "After retrieving DERIVED_FROM node of {}. status is {}";
126 private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
127 private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
128 private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
129 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
130 private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS =
131 "Failed to associate resource {} to property {} in graph. status is {}";
132 private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
133 private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
134 private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
135 private static final String PROPERTY = "Property";
136 private static final String UPDATE_DATA_TYPE = "UpdateDataType";
137 private static final Logger log = Logger.getLogger(PropertyOperation.class.getName());
138 private final DerivedFromOperation derivedFromOperation;
139 private ToscaFunctionValidator toscaFunctionValidator;
140 private DataTypeOperation dataTypeOperation;
143 public PropertyOperation(final HealingJanusGraphGenericDao janusGraphGenericDao, final DerivedFromOperation derivedFromOperation) {
144 this.janusGraphGenericDao = janusGraphGenericDao;
145 this.derivedFromOperation = derivedFromOperation;
149 public void setToscaFunctionValidator(final ToscaFunctionValidator toscaFunctionValidator) {
150 this.toscaFunctionValidator = toscaFunctionValidator;
153 //circular dependency DataTypeOperation->ModelOperation->ModelElementOperation->PropertyOperation
155 public void setDataTypeOperation(DataTypeOperation dataTypeOperation) {
156 this.dataTypeOperation = dataTypeOperation;
159 public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
160 log.debug("The object returned after create property is {}", propertyDataResult);
161 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
162 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
163 propertyDefResult.setName(propertyName);
164 return propertyDefResult;
167 public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
168 Either<PropertyData, JanusGraphOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
169 if (either.isRight()) {
170 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
171 return Either.right(storageStatus);
173 return Either.left(either.left().value());
177 * @param propertyDefinition
181 public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
182 log.trace("Going to validate property type and value. {}", propertyDefinition);
183 String propertyType = propertyDefinition.getType();
184 String value = propertyDefinition.getDefaultValue();
185 ToscaPropertyType type = getType(propertyType);
187 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
188 if (dataTypeDefinition == null) {
189 log.debug("The type {} of property cannot be found.", propertyType);
190 return StorageOperationStatus.INVALID_TYPE;
192 return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
194 String innerType = null;
195 Either<String, JanusGraphOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
196 if (checkInnerType.isRight()) {
197 return StorageOperationStatus.INVALID_TYPE;
199 innerType = checkInnerType.left().value();
200 log.trace("After validating property type {}", propertyType);
201 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
202 if (!isValidProperty) {
203 log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
204 return StorageOperationStatus.INVALID_VALUE;
206 PropertyValueConverter converter = type.getConverter();
207 if (isEmptyValue(value)) {
208 log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
209 propertyDefinition.setDefaultValue(EMPTY_VALUE);
210 } else if (!isEmptyValue(value)) {
211 String convertedValue = converter.convert(value, innerType, dataTypes);
212 propertyDefinition.setDefaultValue(convertedValue);
214 return StorageOperationStatus.OK;
217 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition,
219 ResourceMetadataData resourceData = new ResourceMetadataData();
220 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
221 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
222 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
223 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
224 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
225 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
226 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
227 if (createNodeResult.isRight()) {
228 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
229 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
230 return Either.right(operationStatus);
232 Map<String, Object> props = new HashMap<>();
233 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
234 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
235 .createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
236 if (createRelResult.isRight()) {
237 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
238 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
239 return Either.right(operationStatus);
241 return Either.left(createNodeResult.left().value());
244 public JanusGraphOperationStatus addPropertyToGraphByVertex(JanusGraphVertex metadataVertex, String propertyName,
245 PropertyDefinition propertyDefinition, String resourceId) {
246 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
247 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
248 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
249 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
250 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData);
251 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
252 if (createNodeResult.isRight()) {
253 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
254 log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
255 return operationStatus;
257 Map<String, Object> props = new HashMap<>();
258 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
259 JanusGraphVertex propertyVertex = createNodeResult.left().value();
260 JanusGraphOperationStatus createRelResult = janusGraphGenericDao.createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
261 if (!createRelResult.equals(JanusGraphOperationStatus.OK)) {
262 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
263 return createRelResult;
265 return createRelResult;
268 public JanusGraphGenericDao getJanusGraphGenericDao() {
269 return janusGraphGenericDao;
275 * @param janusGraphGenericDao
277 public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
278 this.janusGraphGenericDao = janusGraphGenericDao;
281 public Either<PropertyData, JanusGraphOperationStatus> deletePropertyFromGraph(String propertyId) {
282 log.debug("Before deleting property from graph {}", propertyId);
283 return janusGraphGenericDao.deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
286 public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition,
287 Map<String, DataTypeDefinition> dataTypes) {
288 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
289 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
290 return Either.right(validateAndUpdateProperty);
292 Either<PropertyData, JanusGraphOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
293 if (either.isRight()) {
294 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
295 return Either.right(storageStatus);
297 return Either.left(either.left().value());
300 public Either<PropertyData, JanusGraphOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
301 if (log.isDebugEnabled()) {
302 log.debug("Before updating property on graph {}", propertyId);
304 // get the original property data
305 Either<PropertyData, JanusGraphOperationStatus> statusProperty = janusGraphGenericDao
306 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
307 if (statusProperty.isRight()) {
308 log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
309 return Either.right(statusProperty.right().value());
311 PropertyData orgPropertyData = statusProperty.left().value();
312 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
313 // create new property data to update
314 PropertyData newPropertyData = new PropertyData();
315 newPropertyData.setPropertyDataDefinition(propertyDefinition);
316 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
317 // update the original property data with new values
318 if (orgPropertyDataDefinition.getDefaultValue() == null) {
319 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
321 if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
322 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
325 if (orgPropertyDataDefinition.getDescription() == null) {
326 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
328 if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
329 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
332 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
333 orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
335 if (newPropertyData.getConstraints() != null) {
336 orgPropertyData.setConstraints(newPropertyData.getConstraints());
338 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
339 return janusGraphGenericDao.updateNode(orgPropertyData, PropertyData.class);
342 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition,
343 NodeTypeEnum nodeType, String uniqueId) {
344 return addPropertyToNodeType(propertyName, propertyDefinition, nodeType, uniqueId, true);
347 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(final String propertyName,
348 final PropertyDefinition propertyDefinition,
349 final NodeTypeEnum nodeType, final String uniqueId,
350 final boolean inTransaction) {
351 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
352 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
353 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
354 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
355 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
356 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
357 if (createNodeResult.isRight()) {
358 if (!inTransaction) {
359 janusGraphGenericDao.rollback();
361 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
362 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
363 return Either.right(operationStatus);
365 Map<String, Object> props = new HashMap<>();
366 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
367 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
368 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
369 Either<GraphRelation, JanusGraphOperationStatus> createRelResult =
370 janusGraphGenericDao.createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
371 if (createRelResult.isRight()) {
372 if (!inTransaction) {
373 janusGraphGenericDao.rollback();
375 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
376 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
377 return Either.right(operationStatus);
379 if (!inTransaction) {
380 janusGraphGenericDao.commit();
382 return Either.left(createNodeResult.left().value());
385 public Either<PropertyDefinition, JanusGraphOperationStatus> updatePropertyAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
386 PropertyDefinition newProperty) {
387 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
389 if (oldPropertiesRes.isRight()) {
390 return Either.right(oldPropertiesRes.right().value());
392 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
393 PropertyDefinition oldPropDef = oldProperties.get(newProperty.getName());
394 JanusGraphOperationStatus status = updateOldProperty(newProperty, oldPropDef);
395 if (status != JanusGraphOperationStatus.OK) {
396 return Either.right(status);
399 return Either.left(newProperty);
402 public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
403 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
404 Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
405 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
407 if (childrenNodes.isRight()) {
408 JanusGraphOperationStatus operationStatus = childrenNodes.right().value();
409 return Either.right(operationStatus);
411 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
412 if (values != null) {
413 for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
414 GraphEdge edge = immutablePair.getValue();
415 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
416 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
417 PropertyData propertyData = immutablePair.getKey();
418 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
419 resourceProps.put(propertyName, propertyDefinition);
422 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
423 return Either.left(resourceProps);
426 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
427 return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId).right()
428 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
431 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
432 Map<String, PropertyDefinition> newProperties) {
433 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
434 Map<String, PropertyDefinition> reallyNewProperties;
435 Map<String, PropertyData> unchangedPropsData;
436 if (oldPropertiesRes.isRight()) {
437 JanusGraphOperationStatus err = oldPropertiesRes.right().value();
438 if (err == JanusGraphOperationStatus.NOT_FOUND) {
439 reallyNewProperties = newProperties;
440 unchangedPropsData = Collections.emptyMap();
442 return Either.right(err);
445 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
446 reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
447 for (Entry<String, PropertyDefinition> oldEntry : oldProperties.entrySet()) {
448 String key = oldEntry.getKey();
449 PropertyDefinition newPropDef = newProperties != null ? newProperties.get(key) : null;
450 PropertyDefinition oldPropDef = oldEntry.getValue();
451 JanusGraphOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
452 if (status != JanusGraphOperationStatus.OK) {
453 return Either.right(status);
456 unchangedPropsData = oldProperties.entrySet().stream()
457 .collect(Collectors.toMap(Entry::getKey, e -> new PropertyData(e.getValue(), null)));
459 // add other properties
460 return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
464 * @param newProperties
465 * @param oldProperties
468 private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties,
469 Map<String, PropertyDefinition> oldProperties) {
470 return newProperties != null ? newProperties.entrySet().stream().filter(entry -> !oldProperties.containsKey(entry.getKey()))
471 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)) : null;
478 private JanusGraphOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
479 if (!isUpdateAllowed(newPropDef, oldPropDef)) {
480 return JanusGraphOperationStatus.MATCH_NOT_FOUND;
482 if (isUpdateRequired(newPropDef, oldPropDef)) {
483 modifyOldPropByNewOne(newPropDef, oldPropDef);
484 List<PropertyConstraint> constraints = oldPropDef.getConstraints();
485 PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
486 Either<PropertyData, JanusGraphOperationStatus> updateResult = janusGraphGenericDao.updateNode(node, PropertyData.class);
487 if (updateResult.isRight()) {
488 return updateResult.right().value();
491 return JanusGraphOperationStatus.OK;
498 private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
499 if (newPropDef == null) {
500 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
503 // If the property type is missing it's something that we could want to fix
504 if (oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
505 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
512 * Update only fields which modification is permitted.
517 private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
518 oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
519 oldPropDef.setDescription(newPropDef.getDescription());
520 oldPropDef.setRequired(newPropDef.isRequired());
521 oldPropDef.setConstraints(newPropDef.getConstraints());
522 // Type is updated to fix possible null type issue in janusGraph DB
523 oldPropDef.setType(newPropDef.getType());
526 private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
527 return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) || !StringUtils
528 .equals(oldPropDef.getDescription(), newPropDef.getDescription()) || oldPropDef.isRequired() != newPropDef.isRequired();
532 * Adds newProperties and returns in case of success (left part of Either) map of all properties i. e. added ones and contained in
537 * @param newProperties
538 * @param unchangedPropsData
541 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId,
542 Map<String, PropertyDefinition> newProperties,
543 Map<String, PropertyData> unchangedPropsData) {
544 return addPropertiesToElementType(uniqueId, nodeType, newProperties).left().map(m -> {
545 m.putAll(unchangedPropsData);
550 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType,
552 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
553 if (propertiesOfNodeRes.isRight()) {
554 JanusGraphOperationStatus status = propertiesOfNodeRes.right().value();
555 if (status == JanusGraphOperationStatus.NOT_FOUND) {
556 return Either.right(StorageOperationStatus.OK);
558 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
560 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
561 for (PropertyDefinition propertyDefinition : value.values()) {
562 String propertyUid = propertyDefinition.getUniqueId();
563 Either<PropertyData, JanusGraphOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
564 if (deletePropertyRes.isRight()) {
565 log.error("Failed to delete property with id {}", propertyUid);
566 JanusGraphOperationStatus status = deletePropertyRes.right().value();
567 if (status == JanusGraphOperationStatus.NOT_FOUND) {
568 status = JanusGraphOperationStatus.INVALID_ID;
570 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
573 log.debug("The properties deleted from node {} are {}", uniqueId, value);
574 return Either.left(value);
578 * Checks existence of a property with the same name belonging to the same resource or existence of property with the same name and different type
579 * (including derived from hierarchy)
583 * @param propertyName
584 * @param propertyType
587 public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
588 boolean result = false;
589 if (!CollectionUtils.isEmpty(properties)) {
590 for (PropertyDefinition propertyDefinition : properties) {
591 if (propertyDefinition.getName().equals(propertyName) && (propertyDefinition.getParentUniqueId().equals(resourceUid)
592 || !propertyDefinition.getType().equals(propertyType))) {
601 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType,
602 Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
603 if (rules == null || rules.isEmpty()) {
604 return new ImmutablePair<>(null, true);
606 for (PropertyRule rule : rules) {
607 String value = rule.getValue();
608 Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
609 if (updateResult.isRight()) {
610 Boolean status = updateResult.right().value();
612 return new ImmutablePair<>(value, status);
615 String newValue = null;
616 Object object = updateResult.left().value();
617 if (object != null) {
618 newValue = object.toString();
620 rule.setValue(newValue);
623 return new ImmutablePair<>(null, true);
626 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
627 String resourceInstanceId) {
628 List<PropertyRule> rules = resourceInstanceProperty.getRules();
630 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
631 rules = new ArrayList<>();
632 rules.add(propertyRule);
634 rules = sortRules(rules);
636 propertyValueData.setRules(rules);
639 private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
640 String resourceInstanceId) {
641 List<String> path = resourceInstanceProperty.getPath();
642 // FOR BC. Since old Property values on VFC/VF does not have rules on
646 // Update could be done on one level only, thus we can use this
648 // operation to avoid migration.
649 if (path == null || path.isEmpty()) {
650 path = new ArrayList<>();
651 path.add(resourceInstanceId);
653 PropertyRule propertyRule = new PropertyRule();
654 propertyRule.setRule(path);
655 propertyRule.setValue(propertyValueData.getValue());
659 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
660 // TODO: sort the rules by size and binary representation.
662 // (x, y, .+) --> 110 6 priority 1
664 // (x, .+, z) --> 101 5 priority 2
668 public ImmutablePair<JanusGraphOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
669 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
670 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllRes = this
671 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
672 if (getAllRes.isRight()) {
673 JanusGraphOperationStatus status = getAllRes.right().value();
674 log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
675 return new ImmutablePair<>(status, null);
677 List<ComponentInstanceProperty> list = getAllRes.left().value();
679 for (ComponentInstanceProperty instanceProperty : list) {
680 String propertyUniqueId = instanceProperty.getUniqueId();
681 String valueUniqueUid = instanceProperty.getValueUniqueUid();
682 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
683 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
684 log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
685 return new ImmutablePair<>(JanusGraphOperationStatus.ALREADY_EXIST, valueUniqueUid);
689 return new ImmutablePair<>(JanusGraphOperationStatus.NOT_FOUND, null);
692 public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
693 String resourceInstanceId) {
694 List<PropertyRule> currentRules = propertyValueData.getRules();
695 List<PropertyRule> rules = resourceInstanceProperty.getRules();
696 // if rules are not supported.
698 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
699 rules = new ArrayList<>();
700 rules.add(propertyRule);
701 if (currentRules != null) {
702 rules = mergeRules(currentRules, rules);
705 // Full mode. all rules are sent in update operation.
706 rules = sortRules(rules);
708 propertyValueData.setRules(rules);
711 private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
712 List<PropertyRule> mergedRules = new ArrayList<>();
713 if (newRules == null || newRules.isEmpty()) {
716 for (PropertyRule rule : currentRules) {
717 PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
718 mergedRules.add(propertyRule);
720 for (PropertyRule rule : newRules) {
721 PropertyRule foundRule = findRuleInList(rule, mergedRules);
722 if (foundRule != null) {
723 foundRule.setValue(rule.getValue());
725 mergedRules.add(rule);
731 private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
732 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
735 PropertyRule foundRule = null;
736 for (PropertyRule propertyRule : rules) {
737 if (rule.getRuleSize() != propertyRule.getRuleSize()) {
740 boolean equals = propertyRule.compareRule(rule);
742 foundRule = propertyRule;
750 * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
752 * @param resourceInstanceUid
755 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
756 String resourceInstanceUid) {
757 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
760 public Either<PropertyValueData, JanusGraphOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
761 Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
762 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
763 if (findResInstanceRes.isRight()) {
764 JanusGraphOperationStatus status = findResInstanceRes.right().value();
765 if (status == JanusGraphOperationStatus.NOT_FOUND) {
766 status = JanusGraphOperationStatus.INVALID_ID;
768 return Either.right(status);
770 Either<PropertyValueData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
771 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
772 if (findPropertyDefRes.isRight()) {
773 JanusGraphOperationStatus status = findPropertyDefRes.right().value();
774 if (status == JanusGraphOperationStatus.NOT_FOUND) {
775 status = JanusGraphOperationStatus.INVALID_ID;
777 return Either.right(status);
779 Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
780 .getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
781 if (relation.isRight()) {
782 // TODO: add error in case of error
783 JanusGraphOperationStatus status = relation.right().value();
784 if (status == JanusGraphOperationStatus.NOT_FOUND) {
785 status = JanusGraphOperationStatus.INVALID_ID;
787 return Either.right(status);
789 Either<PropertyValueData, JanusGraphOperationStatus> deleteNode = janusGraphGenericDao
790 .deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
791 if (deleteNode.isRight()) {
792 return Either.right(deleteNode.right().value());
794 PropertyValueData value = deleteNode.left().value();
795 return Either.left(value);
798 public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid,
799 String resourceInstanceId,
800 boolean inTransaction) {
801 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
803 Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = this
804 .removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
805 if (eitherStatus.isRight()) {
806 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId,
807 eitherStatus.right().value().name());
808 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
811 PropertyValueData propertyValueData = eitherStatus.left().value();
812 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
813 propertyValueResult.setUniqueId(resourceInstanceId);
814 propertyValueResult.setValue(propertyValueData.getValue());
815 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
816 result = Either.left(propertyValueResult);
820 if (!inTransaction) {
821 if (result == null || result.isRight()) {
822 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
823 janusGraphGenericDao.rollback();
825 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
826 janusGraphGenericDao.commit();
832 public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData,
833 ComponentInstanceProperty resourceInstanceProperty) {
834 String value = propertyValueData.getValue();
835 String uid = propertyValueData.getUniqueId();
836 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
837 instanceProperty.setPath(resourceInstanceProperty.getPath());
838 return instanceProperty;
842 public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
843 if (propertyDefinition == null) {
846 String innerType = null;
847 String propertyType = propertyDefinition.getType();
848 ToscaPropertyType type = getType(propertyType);
849 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
850 SchemaDefinition def = propertyDefinition.getSchema();
854 PropertyDataDefinition propDef = def.getProperty();
855 if (propDef == null) {
858 innerType = propDef.getType();
860 String value = propertyDefinition.getDefaultValue();
862 return isValidValue(type, value, innerType, dataTypes);
864 log.trace("The given type {} is not a pre defined one.", propertyType);
865 DataTypeDefinition foundDt = dataTypes.get(propertyType);
866 if (foundDt != null) {
867 return isValidComplexValue(foundDt, value, dataTypes);
874 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final String model) {
875 if (property == null) {
878 if (ToscaPropertyType.isValidType(property.getType()) == null) {
879 Either<Boolean, JanusGraphOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType(), model);
880 if (definedInDataTypes.isRight()) {
883 Boolean isExist = definedInDataTypes.left().value();
884 return isExist.booleanValue();
890 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final Map<String, DataTypeDefinition> dataTypes) {
891 if (property == null) {
894 return ToscaPropertyType.isValidType(property.getType()) != null || dataTypes.containsKey(property.getType());
898 public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
899 if (property == null) {
900 return new ImmutablePair<>(null, false);
902 SchemaDefinition schema;
903 PropertyDataDefinition innerProp;
904 String innerType = null;
905 if ((schema = property.getSchema()) != null) {
906 if ((innerProp = schema.getProperty()) != null) {
907 innerType = innerProp.getType();
910 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
911 if (innerToscaType == null) {
912 DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
913 if (dataTypeDefinition == null) {
914 log.debug("The inner type {} is not a data type.", innerType);
915 return new ImmutablePair<>(innerType, false);
917 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
920 return new ImmutablePair<>(innerType, true);
923 private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
924 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
925 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
926 return validateAndUpdate.right.booleanValue();
929 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
930 String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
931 Either<JanusGraphVertex, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
932 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
933 if (findResInstanceRes.isRight()) {
934 JanusGraphOperationStatus status = findResInstanceRes.right().value();
935 if (status == JanusGraphOperationStatus.NOT_FOUND) {
936 status = JanusGraphOperationStatus.INVALID_ID;
938 return Either.right(status);
940 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> propertyImplNodes = janusGraphGenericDao
941 .getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
942 if (propertyImplNodes.isRight()) {
943 JanusGraphOperationStatus status = propertyImplNodes.right().value();
944 return Either.right(status);
946 List<ImmutablePair<JanusGraphVertex, Edge>> list = propertyImplNodes.left().value();
947 if (list == null || list.isEmpty()) {
948 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
950 List<ComponentInstanceProperty> result = new ArrayList<>();
951 for (ImmutablePair<JanusGraphVertex, Edge> propertyValue : list) {
952 JanusGraphVertex propertyValueDataVertex = propertyValue.getLeft();
953 String propertyValueUid = (String) janusGraphGenericDao
954 .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
955 String value = (String) janusGraphGenericDao.getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
956 ImmutablePair<JanusGraphVertex, Edge> propertyDefPair = janusGraphGenericDao
957 .getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
958 if (propertyDefPair == null) {
959 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
961 Map<String, Object> properties = janusGraphGenericDao.getProperties(propertyValueDataVertex);
962 PropertyValueData propertyValueData = GraphElementFactory
963 .createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
964 String propertyUniqueId = (String) janusGraphGenericDao
965 .getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
966 ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
967 // set property original unique id
968 resourceInstanceProperty.setUniqueId(propertyUniqueId);
971 // TODO: esofer add resource id
972 resourceInstanceProperty.setParentUniqueId(null);
974 resourceInstanceProperty.setValue(value);
975 // set property value unique id
976 resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
978 resourceInstanceProperty.setRules(propertyValueData.getRules());
979 result.add(resourceInstanceProperty);
981 return Either.left(result);
985 * Find the default value from the list of component instances. Start the search from the second component instance
987 * @param pathOfComponentInstances
988 * @param propertyUniqueId
989 * @param defaultValue
992 public Either<String, JanusGraphOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances,
993 String propertyUniqueId, String defaultValue) {
994 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
995 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
996 return Either.left(defaultValue);
998 String result = defaultValue;
999 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
1000 String compInstanceId = pathOfComponentInstances.get(i);
1001 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> propertyValuesResult = this
1002 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
1003 log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
1004 if (propertyValuesResult.isRight()) {
1005 JanusGraphOperationStatus status = propertyValuesResult.right().value();
1006 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1007 return Either.right(status);
1012 ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
1013 log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
1014 if (foundCompInstanceProperty == null) {
1017 List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i),
1018 foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
1019 log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
1020 PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
1021 log.trace("Match rule is {}", matchedRule);
1022 if (matchedRule != null) {
1023 result = matchedRule.getValue();
1027 return Either.left(result);
1030 private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
1031 ComponentInstanceProperty result = null;
1035 for (ComponentInstanceProperty instProperty : list) {
1036 if (instProperty.getUniqueId().equals(propertyUniqueId)) {
1037 result = instProperty;
1044 private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
1045 if (rules != null) {
1048 rules = buildDefaultRule(compInstanceId, ruleSize, value);
1052 private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
1053 List<PropertyRule> rules = componentInstanceProperty.getRules();
1054 if (rules == null) {
1055 rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
1060 private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
1061 List<PropertyRule> rules = new ArrayList<>();
1062 List<String> rule = new ArrayList<>();
1063 rule.add(componentInstanceId);
1064 for (int i = 0; i < size - 1; i++) {
1065 rule.add(PropertyRule.getRuleAnyMatch());
1067 PropertyRule propertyRule = new PropertyRule(rule, value);
1068 rules.add(propertyRule);
1072 private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1073 PropertyRule propertyRule = null;
1074 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1075 String firstCompInstance = pathOfInstances.get(level);
1076 if (rules != null) {
1077 for (PropertyRule rule : rules) {
1078 int ruleSize = rule.getRule().size();
1079 // check the length of the rule equals to the length of the
1082 if (ruleSize != pathOfInstances.size() - level) {
1085 // check that the rule starts with correct component instance id
1086 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1089 String secondToken = rule.getToken(2);
1090 if (secondToken != null && (secondToken.equals(PropertyRule.getForceAll()) || secondToken.equals(PropertyRule.getALL()))) {
1091 propertyRule = rule;
1094 String patternStr = buildStringForMatch(rule.getRule(), 0);
1095 Pattern pattern = Pattern.compile(patternStr);
1096 Matcher matcher = pattern.matcher(stringForMatch);
1097 if (matcher.matches()) {
1098 if (log.isTraceEnabled()) {
1099 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1101 propertyRule = rule;
1106 return propertyRule;
1109 private boolean checkFirstItem(String left, String right) {
1110 return left != null && left.equals(right);
1113 private String buildStringForMatch(List<String> pathOfInstances, int level) {
1114 StringBuilder builder = new StringBuilder();
1115 for (int i = level; i < pathOfInstances.size(); i++) {
1116 builder.append(pathOfInstances.get(i));
1117 if (i < pathOfInstances.size() - 1) {
1118 builder.append("#");
1121 return builder.toString();
1124 public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty,
1125 Map<String, ComponentInstanceProperty> instanceIdToValue) {
1126 List<String> pathOfInstances = instanceProperty.getPath();
1128 int size = pathOfInstances.size();
1129 int numberOfMatches = 0;
1130 for (String instanceId : pathOfInstances) {
1131 ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1132 if (componentInstanceProperty != null) {
1133 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1134 // If it is the first level instance, then update valueUniuqeId
1136 // parameter in order to know on update that
1138 // we should update and not create new node on graph.
1140 instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1141 instanceProperty.setRules(rules);
1143 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1146 String value = rule.getValue();
1147 if (numberOfMatches == 1) {
1148 instanceProperty.setValue(value);
1149 if (log.isDebugEnabled()) {
1150 log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1151 pathOfInstances, value);
1153 } else if (numberOfMatches == 2) {
1154 // In case of another property value match, then use the
1156 // value to be the default value of the property.
1157 instanceProperty.setDefaultValue(value);
1158 if (log.isDebugEnabled()) {
1159 log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1160 pathOfInstances, value);
1171 * Add data type to graph.
1173 * 1. Add data type node
1175 * 2. Add edge between the former node to its parent(if exists)
1177 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1179 * @param dataTypeDefinition
1182 private Either<DataTypeData, JanusGraphOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1183 log.debug("Got data type {}", dataTypeDefinition);
1184 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getModel(), dataTypeDefinition.getName());
1185 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1186 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1187 Either<DataTypeData, JanusGraphOperationStatus> createDataTypeResult = janusGraphGenericDao.createNode(dataTypeData, DataTypeData.class);
1188 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1189 if (createDataTypeResult.isRight()) {
1190 JanusGraphOperationStatus operationStatus = createDataTypeResult.right().value();
1191 log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1192 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1193 return Either.right(operationStatus);
1195 DataTypeData resultCTD = createDataTypeResult.left().value();
1196 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1197 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(),
1198 dataTypeDefinition.getModel(),
1200 if (addPropertiesToDataType.isRight()) {
1201 log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1202 return Either.right(addPropertiesToDataType.right().value());
1205 final Either<GraphRelation, JanusGraphOperationStatus> modelRelationship = addDataTypeToModel(dataTypeDefinition);
1206 if (modelRelationship.isRight()) {
1207 return Either.right(modelRelationship.right().value());
1210 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1211 if (derivedFrom != null) {
1212 final Either<DataTypeDefinition, JanusGraphOperationStatus> derivedFromDataType = getDataTypeByNameValidForModel(derivedFrom,
1213 dataTypeDefinition.getModel());
1214 if (derivedFromDataType.isRight()) {
1215 return Either.right(derivedFromDataType.right().value());
1218 log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1219 UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1220 final String deriveFromUid = derivedFromDataType.left().value().getUniqueId();
1221 UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1222 Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
1223 .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1224 log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1225 if (createRelation.isRight()) {
1226 return Either.right(createRelation.right().value());
1229 return Either.left(createDataTypeResult.left().value());
1232 private Either<GraphRelation, JanusGraphOperationStatus> addDataTypeToModel(final DataTypeDefinition dataTypeDefinition) {
1233 final String model = dataTypeDefinition.getModel();
1234 if (model == null) {
1235 return Either.left(null);
1237 final GraphNode from = new UniqueIdData(NodeTypeEnum.Model, UniqueIdBuilder.buildModelUid(model));
1238 final GraphNode to = new UniqueIdData(NodeTypeEnum.DataType, dataTypeDefinition.getUniqueId());
1239 log.info("Connecting model {} to type {}", from, to);
1240 return janusGraphGenericDao.createRelation(from, to, GraphEdgeLabels.MODEL_ELEMENT, Collections.emptyMap());
1243 private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1244 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1245 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1246 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1247 if (creationDate == null) {
1248 creationDate = System.currentTimeMillis();
1250 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1251 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1252 return dataTypeData;
1256 * add properties to capability type.
1258 * Per property, add a property node and associate it to the capability type
1264 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType(final String uniqueId, final String modelName,
1265 final List<PropertyDefinition> properties) {
1266 Map<String, PropertyData> propertiesData = new HashMap<>();
1267 if (properties != null && !properties.isEmpty()) {
1268 for (PropertyDefinition propertyDefinition : properties) {
1269 String propertyName = propertyDefinition.getName();
1270 String propertyType = propertyDefinition.getType();
1271 Either<Boolean, JanusGraphOperationStatus> validPropertyType = isValidPropertyType(propertyType, modelName);
1272 if (validPropertyType.isRight()) {
1273 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1274 return Either.right(validPropertyType.right().value());
1276 Boolean isValid = validPropertyType.left().value();
1277 if (isValid == null || !isValid.booleanValue()) {
1278 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1279 return Either.right(JanusGraphOperationStatus.INVALID_TYPE);
1281 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1282 .addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1283 if (addPropertyToNodeType.isRight()) {
1284 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1285 log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1286 BeEcompErrorManager.getInstance()
1287 .logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus,
1288 ErrorSeverity.ERROR);
1289 return Either.right(operationStatus);
1291 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1293 DataTypeData dataTypeData = new DataTypeData();
1294 Either<DataTypeDefinition, StorageOperationStatus> existingNode = getDataTypeByUidWithoutDerived(uniqueId, true);
1295 if (existingNode.isLeft()) {
1296 dataTypeData.getDataTypeDataDefinition().setNormative(existingNode.left().value().isNormative());
1298 dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1300 long modificationTime = System.currentTimeMillis();
1301 dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1302 Either<DataTypeData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao.updateNode(dataTypeData, DataTypeData.class);
1303 if (updateNode.isRight()) {
1304 JanusGraphOperationStatus operationStatus = updateNode.right().value();
1305 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1306 BeEcompErrorManager.getInstance()
1307 .logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1308 return Either.right(operationStatus);
1310 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1313 return Either.left(propertiesData);
1316 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByNameValidForModel(final String name, final String modelName) {
1317 final Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1318 .getNode(GraphPropertiesDictionary.NAME.getProperty(), name, DataTypeData.class, modelName);
1319 if (dataTypesRes.isRight()) {
1320 final JanusGraphOperationStatus status = dataTypesRes.right().value();
1321 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, name, status);
1322 return Either.right(status);
1324 final DataTypeData dataType = dataTypesRes.left().value();
1325 final DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(dataType.getDataTypeDataDefinition());
1326 final JanusGraphOperationStatus propertiesStatus = fillProperties(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1327 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1328 log.error(BUSINESS_PROCESS_ERROR, FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, dataTypeDefinition.getUniqueId());
1329 return Either.right(propertiesStatus);
1331 final Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1332 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeDefinition.getUniqueId(), GraphEdgeLabels.DERIVED_FROM,
1333 NodeTypeEnum.DataType,
1334 DataTypeData.class);
1335 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, dataTypeDefinition.getUniqueId(), parentNode);
1336 if (parentNode.isRight()) {
1337 final JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1338 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1339 log.error(BUSINESS_PROCESS_ERROR, "Failed to find the parent data type of data type {}. status is {}",
1340 dataTypeDefinition.getUniqueId(), janusGraphOperationStatus);
1341 return Either.right(janusGraphOperationStatus);
1344 // derived from node was found
1345 final ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1346 final DataTypeData parentDataType = immutablePair.getKey();
1347 final Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentDataType.getUniqueId());
1348 if (dataTypeByUid.isRight()) {
1349 return Either.right(dataTypeByUid.right().value());
1351 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1352 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1354 return Either.left(dataTypeDefinition);
1358 * Build Data type object from graph by unique id
1363 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUid(String uniqueId) {
1364 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1365 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1366 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1367 if (dataTypesRes.isRight()) {
1368 JanusGraphOperationStatus status = dataTypesRes.right().value();
1369 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1370 return Either.right(status);
1372 DataTypeData ctData = dataTypesRes.left().value();
1373 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1374 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1375 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1376 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1377 return Either.right(propertiesStatus);
1379 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1380 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1381 DataTypeData.class);
1382 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1383 if (parentNode.isRight()) {
1384 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1385 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1386 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1387 result = Either.right(janusGraphOperationStatus);
1391 // derived from node was found
1392 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1393 DataTypeData parentCT = immutablePair.getKey();
1394 String parentUniqueId = parentCT.getUniqueId();
1395 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1396 if (dataTypeByUid.isRight()) {
1397 return Either.right(dataTypeByUid.right().value());
1399 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1400 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1402 result = Either.left(dataTypeDefinition);
1406 private JanusGraphOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1407 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this
1408 .findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1409 if (findPropertiesOfNode.isRight()) {
1410 JanusGraphOperationStatus janusGraphOperationStatus = findPropertiesOfNode.right().value();
1411 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, janusGraphOperationStatus);
1412 if (JanusGraphOperationStatus.NOT_FOUND.equals(janusGraphOperationStatus)) {
1413 return JanusGraphOperationStatus.OK;
1415 return janusGraphOperationStatus;
1418 Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1419 if (properties != null && !properties.isEmpty()) {
1420 List<PropertyDefinition> listOfProps = new ArrayList<>();
1421 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1422 String propName = entry.getKey();
1423 PropertyDefinition propertyDefinition = entry.getValue();
1424 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1425 newPropertyDefinition.setName(propName);
1426 listOfProps.add(newPropertyDefinition);
1428 dataTypeDefinition.setProperties(listOfProps);
1430 return JanusGraphOperationStatus.OK;
1434 private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1435 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1437 Either<DataTypeData, JanusGraphOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1438 if (eitherStatus.isRight()) {
1439 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1440 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1441 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1444 DataTypeData capabilityTypeData = eitherStatus.left().value();
1445 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1446 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1447 result = Either.left(dataTypeDefResult);
1451 if (!inTransaction) {
1452 if (result == null || result.isRight()) {
1453 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1454 janusGraphGenericDao.rollback();
1456 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1457 janusGraphGenericDao.commit();
1464 public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1465 return addDataType(dataTypeDefinition, true);
1469 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel,
1470 final boolean inTransaction) {
1471 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1473 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByNameValidForModel(name, validForModel);
1474 if (ctResult.isRight()) {
1475 JanusGraphOperationStatus status = ctResult.right().value();
1476 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1477 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1479 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1482 result = Either.left(ctResult.left().value());
1485 if (!inTransaction) {
1486 if (result == null || result.isRight()) {
1487 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1488 janusGraphGenericDao.rollback();
1490 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1491 janusGraphGenericDao.commit();
1498 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel) {
1499 return getDataTypeByName(name, validForModel, true);
1502 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByUidWithoutDerived(String uid, boolean inTransaction) {
1503 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1505 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1506 if (ctResult.isRight()) {
1507 JanusGraphOperationStatus status = ctResult.right().value();
1508 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1509 log.error(BUSINESS_PROCESS_ERROR, "Failed to retrieve information on data type {} status is {}", uid, status);
1511 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1514 result = Either.left(ctResult.left().value());
1517 if (!inTransaction) {
1518 if (result == null || result.isRight()) {
1519 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1520 janusGraphGenericDao.rollback();
1522 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1523 janusGraphGenericDao.commit();
1529 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1530 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1531 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1532 if (dataTypesRes.isRight()) {
1533 JanusGraphOperationStatus status = dataTypesRes.right().value();
1534 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1535 return Either.right(status);
1537 DataTypeData ctData = dataTypesRes.left().value();
1538 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1539 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1540 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1541 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1542 return Either.right(propertiesStatus);
1544 return Either.left(dataTypeDefinition);
1548 * convert between graph Node object to Java object
1550 * @param dataTypeData
1553 protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1554 log.debug("The object returned after create data type is {}", dataTypeData);
1555 return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1558 private Either<Boolean, JanusGraphOperationStatus> isValidPropertyType(String propertyType, final String modelName) {
1559 if (propertyType == null || propertyType.isEmpty()) {
1560 return Either.left(false);
1562 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1563 if (toscaPropertyType == null) {
1564 return isDefinedInDataTypes(propertyType, modelName);
1566 return Either.left(true);
1570 public Either<Boolean, JanusGraphOperationStatus> isDefinedInDataTypes(final String propertyType, final String modelName) {
1571 Either<DataTypeDefinition, JanusGraphOperationStatus> dataType = getDataTypeByNameValidForModel(propertyType, modelName);
1572 if (dataType.isRight()) {
1573 JanusGraphOperationStatus status = dataType.right().value();
1574 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1575 return Either.left(false);
1577 return Either.right(status);
1579 return Either.left(true);
1582 public Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> getAllDataTypes() {
1583 final Map<String, Map<String, DataTypeDefinition>> dataTypes = new HashMap<>();
1584 Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> result = Either.left(dataTypes);
1585 final Map<String, DataTypeDefinition> allDataTypesFound = new HashMap<>();
1587 final Map<String, List<String>> dataTypeUidstoModels = dataTypeOperation.getAllDataTypeUidsToModels();
1589 if (dataTypeUidstoModels != null) {
1590 log.trace("Number of data types to load is {}", dataTypeUidstoModels.size());
1591 for (final Map.Entry<String, List<String>> entry : dataTypeUidstoModels.entrySet()) {
1592 final String key = entry.getKey();
1593 log.trace("Going to fetch data type with uid {}", key);
1594 final Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getAndAddDataTypeByUid(key, allDataTypesFound);
1595 if (dataTypeByUid.isRight()) {
1596 JanusGraphOperationStatus status = dataTypeByUid.right().value();
1597 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1598 status = JanusGraphOperationStatus.INVALID_ID;
1600 return Either.right(status);
1602 for (final String model : entry.getValue()) {
1603 if (!dataTypes.containsKey(model)) {
1604 dataTypes.put(model, new HashMap<>());
1606 DataTypeDefinition dataTypeDefinition = allDataTypesFound.get(entry.getKey());
1607 dataTypes.get(model).put(dataTypeDefinition.getName(), dataTypeDefinition);
1611 if (log.isTraceEnabled()) {
1612 if (result.isRight()) {
1613 log.trace("After fetching all data types {}", result);
1615 Map<String, Map<String, DataTypeDefinition>> map = result.left().value();
1617 String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1618 log.trace("After fetching all data types {} ", types);
1626 * Build Data type object from graph by unique id
1631 private Either<DataTypeDefinition, JanusGraphOperationStatus> getAndAddDataTypeByUid(String uniqueId,
1632 Map<String, DataTypeDefinition> allDataTypes) {
1633 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1634 if (allDataTypes.containsKey(uniqueId)) {
1635 return Either.left(allDataTypes.get(uniqueId));
1637 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1638 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1639 if (dataTypesRes.isRight()) {
1640 JanusGraphOperationStatus status = dataTypesRes.right().value();
1641 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1642 return Either.right(status);
1644 DataTypeData ctData = dataTypesRes.left().value();
1645 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1646 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1647 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1648 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1649 return Either.right(propertiesStatus);
1651 allDataTypes.put(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1652 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1653 if (allDataTypes.containsKey(derivedFrom)) {
1654 DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1655 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1656 return Either.left(dataTypeDefinition);
1658 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1659 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1660 DataTypeData.class);
1661 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1662 if (parentNode.isRight()) {
1663 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1664 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1665 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1666 result = Either.right(janusGraphOperationStatus);
1670 // derived from node was found
1671 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1672 DataTypeData parentCT = immutablePair.getKey();
1673 String parentUniqueId = parentCT.getUniqueId();
1674 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1675 if (dataTypeByUid.isRight()) {
1676 return Either.right(dataTypeByUid.right().value());
1678 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1679 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1680 final var model = getModel(uniqueId);
1681 if (StringUtils.isNotEmpty(model)) {
1682 dataTypeDefinition.setModel(model);
1685 result = Either.left(dataTypeDefinition);
1689 private String getModel(final String uniqueId) {
1690 final Either<ImmutablePair<ModelData, GraphEdge>, JanusGraphOperationStatus> model = janusGraphGenericDao.getParentNode(
1691 UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.MODEL_ELEMENT,
1692 NodeTypeEnum.Model, ModelData.class);
1693 return model.isLeft() ? model.left().value().getLeft().getName() : StringUtils.EMPTY;
1696 public Either<String, JanusGraphOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
1697 String propertyType = propDataDef.getType();
1698 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
1699 return getInnerType(type, propDataDef::getSchema);
1702 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType,
1703 Map<String, DataTypeDefinition> dataTypes) {
1704 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
1705 final ToscaPropertyType type = getType(propertyType);
1708 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
1709 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter
1710 .validateAndUpdate(value, dataTypeDefinition, dataTypes);
1711 if (Boolean.FALSE.equals(validateResult.right)) {
1712 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
1713 return Either.right(false);
1715 JsonElement jsonElement = validateResult.left;
1716 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
1717 return Either.left(valueFromJsonElement);
1719 log.trace("before validating property type {}", propertyType);
1720 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
1721 if (!isValidProperty) {
1722 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
1723 return Either.right(false);
1726 Object convertedValue = value;
1727 if (!isEmptyValue(value) && isValidate) {
1728 PropertyValueConverter converter = type.getConverter();
1729 convertedValue = converter.convert(value, innerType, dataTypes);
1731 return Either.left(convertedValue);
1734 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType,
1735 Map<String, DataTypeDefinition> dataTypes) {
1736 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
1739 public Either<Object, Boolean> validateAndUpdatePropertyValue(final Component containerComponent, final PropertyDataDefinition property,
1740 final Map<String, DataTypeDefinition> dataTypes) {
1741 if (property.isToscaFunction()) {
1742 toscaFunctionValidator.validate(property, containerComponent);
1743 property.setValue(property.getToscaFunction().getValue());
1744 return Either.left(property.getValue());
1746 Either<String, JanusGraphOperationStatus> checkInnerType = checkInnerType(property);
1747 if (checkInnerType.isRight()) {
1748 return Either.right(false);
1750 final String innerType = checkInnerType.left().value();
1751 return validateAndUpdatePropertyValue(property.getType(), property.getValue(), true, innerType, dataTypes);
1754 public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType,
1756 return this.findPropertiesOfNode(nodeType, uniqueId).right().bind(this::handleNotFoundProperties).left()
1757 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
1760 private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(
1761 JanusGraphOperationStatus janusGraphOperationStatus) {
1762 if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
1763 return Either.left(new HashMap<>());
1765 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1768 private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId,
1769 NodeTypeEnum nodeType,
1771 Collection<PropertyDefinition> nodeProps) {
1772 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
1773 String currentNodeUid = uniqueId;
1774 Either<T, StorageOperationStatus> derivedFrom;
1775 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
1776 currentNodeUid = derivedFrom.left().value().getUniqueId();
1777 JanusGraphOperationStatus janusGraphOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
1778 if (janusGraphOperationStatus != JanusGraphOperationStatus.OK) {
1779 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
1780 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1783 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
1784 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
1787 private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
1788 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
1791 public JanusGraphOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
1792 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
1793 if (findPropertiesRes.isRight()) {
1794 return findPropertiesRes.right().value();
1796 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
1797 if (properties != null) {
1798 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
1799 propertySetter.accept(propertiesAsList);
1801 return JanusGraphOperationStatus.OK;
1804 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType) {
1805 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
1806 if (findPropertiesOfNode.isRight()) {
1807 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
1808 if (findPropertiesOfNode.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
1809 return Either.left(Maps.newHashMap());
1811 return findPropertiesOfNode;
1813 return findPropertiesOfNode;
1817 * add properties to element type.
1819 * Per property, add a property node and associate it to the element type
1822 * @param propertiesMap
1825 protected Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType,
1826 Map<String, PropertyDefinition> propertiesMap) {
1827 Map<String, PropertyData> propertiesData = new HashMap<>();
1828 if (propertiesMap != null) {
1829 for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
1830 String propertyName = propertyDefinitionEntry.getKey();
1831 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1832 .addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
1833 if (addPropertyToNodeType.isRight()) {
1834 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1835 log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName,
1837 return Either.right(operationStatus);
1839 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1842 return Either.left(propertiesData);
1845 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType,
1846 List<PropertyDefinition> properties) {
1847 Map<String, PropertyDefinition> propMap;
1848 if (properties == null) {
1851 propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
1853 return addPropertiesToElementType(uniqueId, elementType, propMap);
1857 public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1858 DataTypeDefinition oldDataTypeDefinition) {
1859 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
1862 private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1863 DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
1864 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1866 List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
1867 List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
1868 String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
1869 String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
1870 String dataTypeName = newDataTypeDefinition.getName();
1871 List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
1872 if (isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, propertiesToAdd)
1873 || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
1874 log.debug("The new data type {} is invalid.", dataTypeName);
1875 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
1878 if (CollectionUtils.isEmpty(propertiesToAdd)) {
1879 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
1880 result = Either.right(StorageOperationStatus.OK);
1883 Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
1884 if (MapUtils.isNotEmpty(newDescriptions)) {
1885 JanusGraphOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(),
1887 if (updatePropertiesStatus != JanusGraphOperationStatus.OK) {
1888 log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}",
1889 oldDataTypeDefinition, updatePropertiesStatus);
1890 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1891 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatePropertiesStatus));
1895 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(
1896 oldDataTypeDefinition.getUniqueId(), oldDataTypeDefinition.getModel(), propertiesToAdd);
1897 if (addPropertiesToDataType.isRight()) {
1898 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition,
1899 addPropertiesToDataType.right().value().name());
1900 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1901 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToDataType.right().value()));
1904 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
1905 if (dataTypeByUid.isRight()) {
1906 JanusGraphOperationStatus status = addPropertiesToDataType.right().value();
1907 log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
1908 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
1909 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
1911 result = Either.left(dataTypeByUid.left().value());
1916 if (!inTransaction) {
1917 if (result == null || result.isRight()) {
1918 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1919 janusGraphGenericDao.rollback();
1921 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1922 janusGraphGenericDao.commit();
1928 private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties,
1929 List<PropertyDefinition> outputPropertiesToAdd) {
1930 if (newProperties != null && oldProperties != null) {
1931 Map<String, PropertyDefinition> newPropsMapper = newProperties.stream()
1932 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1933 Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream()
1934 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1935 for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
1936 String propName = newPropertyEntry.getKey();
1937 PropertyDefinition propDef = newPropertyEntry.getValue();
1938 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
1939 if (oldPropertyDefinition == null) {
1940 log.debug("New property {} received in the data type {}", propName, dataTypeName);
1941 outputPropertiesToAdd.add(propDef);
1944 String oldType = oldPropertyDefinition.getType();
1945 String oldEntryType = getEntryType(oldPropertyDefinition);
1946 String newType = propDef.getType();
1947 String newEntryType = getEntryType(propDef);
1948 if (!oldType.equals(newType)) {
1949 log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType,
1953 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
1954 log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName,
1955 oldEntryType, newEntryType);
1963 private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
1964 if (oldEntryType == null && newEntryType == null) {
1966 } else if (oldEntryType != null && newEntryType != null) {
1967 return oldEntryType.equals(newEntryType);
1973 private String getEntryType(PropertyDefinition oldPropertyDefinition) {
1974 String entryType = null;
1975 SchemaDefinition schema = oldPropertyDefinition.getSchema();
1976 if (schema != null) {
1977 PropertyDataDefinition schemaProperty = schema.getProperty();
1978 if (schemaProperty != null) {
1979 entryType = schemaProperty.getType();
1985 private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
1986 if (newDerivedFromName != null) {
1987 boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
1989 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1990 oldDerivedFromName);
1993 } else if (oldDerivedFromName == null) {
1995 } else {// new=null, old != null
1996 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1997 oldDerivedFromName);
2007 public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
2008 Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
2009 if (graphResult.isRight()) {
2010 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
2012 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
2013 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
2014 if (vertexService.isRight()) {
2015 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
2016 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
2018 Vertex vertex = vertexService.left().value();
2019 VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
2020 Integer counter = 0;
2021 if (vertexProperty.isPresent() && vertexProperty.value() != null) {
2022 counter = (Integer) vertexProperty.value();
2025 vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
2026 return Either.left(counter);
2029 public Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesUniqueness(
2030 Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
2031 Either<List<PropertyDefinition>, JanusGraphOperationStatus> result = Either.left(properties);
2032 for (PropertyDefinition property : properties) {
2033 JanusGraphOperationStatus status = validatePropertyUniqueness(inheritedProperties, property);
2034 if (status != JanusGraphOperationStatus.OK) {
2035 result = Either.right(status);
2043 * Validates uniqueness of examined property by comparing it with properties in propertiesOfType and updates if need type and inner type of the
2046 private JanusGraphOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2047 String propertyName = property.getName();
2048 String propertyType = property.getType();
2049 JanusGraphOperationStatus result = JanusGraphOperationStatus.OK;
2050 if (inheritedProperties.containsKey(propertyName)) {
2051 PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2052 if (typesMismatch(propertyType, defaultProperty.getType())) {
2053 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2054 result = JanusGraphOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2056 property.setType(defaultProperty.getType());
2057 String innerType = defaultProperty.getSchemaType();
2058 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2059 if (schemaProperty != null) {
2060 schemaProperty.setType(innerType);
2067 private boolean typesMismatch(String type1, String type2) {
2068 return type1 != null && type2 != null && !type2.equals(type1);
2071 public <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllTypePropertiesFromAllDerivedFrom(
2072 String nextParentUid, NodeTypeEnum nodeType, Class<T> clazz) {
2073 Map<String, PropertyDefinition> allProperies = new HashMap<>();
2074 return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2077 private <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getTypePropertiesFromDerivedFromRecursively(
2078 String nextParentUid, Map<String, PropertyDefinition> allProperies, NodeTypeEnum nodeType, Class<T> clazz) {
2079 JanusGraphOperationStatus error;
2080 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
2081 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2082 if (childrenNodes.isRight()) {
2083 if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
2084 error = childrenNodes.right().value();
2085 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid,
2087 return Either.right(error);
2089 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.",
2091 return Either.left(allProperies);
2094 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2095 if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
2096 error = allPropertiesOfTypeRes.right().value();
2098 "#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}",
2099 nextParentUid, error);
2100 return Either.right(error);
2101 } else if (allPropertiesOfTypeRes.isLeft()) {
2102 if (allProperies.isEmpty()) {
2103 allProperies.putAll(allPropertiesOfTypeRes.left().value());
2105 allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey()))
2106 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2109 return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType,
2114 private JanusGraphOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2115 if (MapUtils.isNotEmpty(newDescriptions)) {
2116 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getDataTypePropertiesRes = janusGraphGenericDao
2117 .getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2118 if (getDataTypePropertiesRes.isRight()) {
2119 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2120 return getDataTypePropertiesRes.right().value();
2122 getDataTypePropertiesRes.left().value().stream().filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2123 .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2125 return JanusGraphOperationStatus.OK;
2128 private JanusGraphVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<JanusGraphVertex, Edge> pair) {
2129 return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2132 private String getPropertyNameFromEdge(ImmutablePair<JanusGraphVertex, Edge> pair) {
2133 return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2136 private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2137 Map<String, PropertyDefinition> newPropertiesMap = newProperties.stream().collect(Collectors.toMap(PropertyDefinition::getName, p -> p));
2138 return oldProperties.stream()
2139 .filter(p -> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2140 .collect(Collectors.toMap(PropertyDefinition::getName, p -> newPropertiesMap.get(p.getName()).getDescription()));
2143 private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty) {
2144 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2147 if (StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2150 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())) {
2153 return property.getDescription().equals(otherProperty.getDescription());
2156 public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
2159 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
2160 JsonObject result = new JsonObject();
2161 JsonArray jsonArray = new JsonArray();
2162 if (src instanceof InRangeConstraint) {
2163 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
2164 jsonArray.add(JsonParser.parseString(String.valueOf(rangeConstraint.getInRange().get(0))));
2165 jsonArray.add(JsonParser.parseString(String.valueOf(rangeConstraint.getInRange().get(1))));
2166 result.add("inRange", jsonArray);
2167 } else if (src instanceof GreaterThanConstraint) {
2168 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
2169 jsonArray.add(JsonParser.parseString(String.valueOf(greaterThanConstraint.getGreaterThan())));
2170 result.add("greaterThan", jsonArray);
2171 } else if (src instanceof LessThanConstraint) {
2172 LessThanConstraint lessThanConstraint = (LessThanConstraint) src;
2173 jsonArray.add(JsonParser.parseString(String.valueOf(lessThanConstraint.getLessThan())));
2174 result.add("lessThan", jsonArray);
2175 } else if (src instanceof LessOrEqualConstraint) {
2176 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
2177 jsonArray.add(JsonParser.parseString(String.valueOf(lessOrEqualConstraint.getLessOrEqual())));
2178 result.add("lessOrEqual", jsonArray);
2180 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
2186 public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
2189 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
2190 PropertyConstraint propertyConstraint = null;
2191 final Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
2192 if (!set.isEmpty()) {
2193 final Entry<String, JsonElement> element = set.iterator().next();
2194 final String key = element.getKey();
2195 final ConstraintType constraintType = ConstraintType.findByType(key).orElse(null);
2196 if (constraintType == null) {
2197 log.warn("ConstraintType was not found for constraint name:{}", key);
2199 final JsonElement value = element.getValue();
2200 final Object typedValue = getTypedValue(value);
2201 switch (constraintType) {
2203 if (typedValue != null) {
2204 log.debug("Before adding value to EqualConstraint object. value = {}", typedValue);
2205 propertyConstraint = new EqualConstraint(typedValue);
2207 log.warn("The value of EqualConstraint is null");
2211 if (typedValue instanceof ArrayList) {
2212 List<Object> rangeArray = (ArrayList<Object>) typedValue;
2213 if (rangeArray.size() != 2 || rangeArray.contains("")) {
2214 log.error("The range constraint content is invalid. value = {}", typedValue);
2215 throw new JsonSyntaxException("The range constraint content is invalid");
2217 final Object minValue = rangeArray.get(0);
2218 final Object maxValue = rangeArray.get(1);
2220 final Comparable min = ConstraintUtil.convertToComparable(
2221 ToscaType.getToscaType(minValue.getClass().getSimpleName().toLowerCase()), String.valueOf(minValue));
2222 final Comparable max = ConstraintUtil.convertToComparable(
2223 ToscaType.getToscaType(maxValue.getClass().getSimpleName().toLowerCase()), String.valueOf(maxValue));
2225 propertyConstraint = new InRangeConstraint(Arrays.asList(min, max));
2228 log.warn("The value of InRangeConstraint is null");
2232 if (typedValue != null) {
2233 log.debug("Before adding value to GreaterThanConstraint object. value = {}", typedValue);
2234 propertyConstraint = new GreaterThanConstraint(typedValue);
2236 log.warn("The value of GreaterThanConstraint is null");
2240 if (typedValue != null) {
2241 log.debug("Before adding value to LessThanConstraint object. value = {}", typedValue);
2242 propertyConstraint = new LessThanConstraint(typedValue);
2244 log.warn("The value of LessThanConstraint is null");
2247 case GREATER_OR_EQUAL:
2248 if (typedValue != null) {
2249 log.debug("Before adding value to GreaterThanConstraint object. value = {}", typedValue);
2250 propertyConstraint = new GreaterOrEqualConstraint(typedValue);
2252 log.warn("The value of GreaterOrEqualConstraint is null");
2256 if (typedValue != null) {
2257 log.debug("Before adding value to LessOrEqualConstraint object. value = {}", typedValue);
2258 propertyConstraint = new LessOrEqualConstraint(typedValue);
2260 log.warn("The value of LessOrEqualConstraint is null");
2264 if (typedValue instanceof ArrayList) {
2265 List<Object> validValuesArray = (ArrayList<Object>) typedValue;
2266 if (validValuesArray.size() == 0 || validValuesArray.contains("")) {
2267 log.error("The valid values constraint content is invalid. value = {}", typedValue);
2268 throw new JsonSyntaxException("The valid values constraint content is invalid");
2270 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2271 vvConstraint.setValidValues(validValuesArray);
2272 propertyConstraint = vvConstraint;
2275 log.warn("The value of ValidValuesConstraint is null");
2279 if (value != null) {
2280 int asInt = value.getAsInt();
2281 log.debug("Before adding value to length constraint. value = {}", asInt);
2282 propertyConstraint = new LengthConstraint(asInt);
2284 log.warn("The value of LengthConstraint is null");
2288 if (value != null) {
2289 int asInt = value.getAsInt();
2290 log.debug("Before adding value to Min Length object. value = {}", asInt);
2291 propertyConstraint = new MinLengthConstraint(asInt);
2293 log.warn("The value of MinLengthConstraint is null");
2297 if (value != null) {
2298 int asInt = value.getAsInt();
2299 log.debug("Before adding value to max length constraint. value = {}", asInt);
2300 propertyConstraint = new MaxLengthConstraint(asInt);
2302 log.warn("The value of MaxLengthConstraint is null");
2306 if (value != null) {
2307 String asString = value.getAsString();
2308 log.debug("Before adding value to PatternConstraint object. value = {}", asString);
2309 propertyConstraint = new PatternConstraint(asString);
2311 log.warn("The value of PatternConstraint is null");
2315 log.warn("Key {} is not supported. Ignored.", key);
2319 return propertyConstraint;
2322 private Object getTypedValue(JsonElement je) {
2323 if (je == null || je.isJsonNull()) {
2326 if (je.isJsonPrimitive()) {
2327 return getJsonPrimitive(je.getAsJsonPrimitive());
2329 if (je.isJsonArray()) {
2330 ArrayList<Object> array = new ArrayList<>();
2331 for (JsonElement e : je.getAsJsonArray()) {
2332 array.add(getJsonPrimitive(e.getAsJsonPrimitive()));
2339 private Object getJsonPrimitive(JsonPrimitive je) {
2340 if (je.isBoolean()) {
2341 return je.getAsBoolean();
2343 if (je.isNumber()) {
2344 float number = je.getAsNumber().floatValue();
2345 if ((number % 1) == 0) {
2346 return je.getAsNumber().intValue();
2350 if (je.isString()) {
2351 return je.getAsString();
2357 public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
2360 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
2361 ObjectCodec oc = json.getCodec();
2362 JsonNode node = oc.readTree(json);
2363 PropertyConstraint propertyConstraint = null;
2365 Iterator<Entry<String, JsonNode>> fieldsIterator = node.fields();
2366 while (fieldsIterator.hasNext()) {
2367 Entry<String, JsonNode> field = fieldsIterator.next();
2368 ConstraintType constraintType = ConstraintType.findByType(field.getKey()).orElse(null);
2369 JsonNode value = field.getValue();
2371 if (constraintType == null) {
2372 log.warn("ConstraintType was not found for constraint name:{}", field.getKey());
2374 if (value == null) {
2375 log.warn("The value of {} constraint is null", constraintType);
2377 switch (constraintType) {
2379 propertyConstraint = deserializeConstraint(value, EqualConstraint.class);
2382 propertyConstraint = deserializeInRangeConstraint(value);
2385 propertyConstraint = deserializeConstraint(value, GreaterThanConstraint.class);
2388 propertyConstraint = deserializeConstraint(value, LessThanConstraint.class);
2390 case GREATER_OR_EQUAL:
2391 propertyConstraint = deserializeConstraint(value, GreaterOrEqualConstraint.class);
2394 propertyConstraint = deserializeConstraint(value, LessOrEqualConstraint.class);
2397 propertyConstraint = deserializeValidValuesConstraint(value);
2400 propertyConstraint = deserializeConstraintWithIntegerOperand(value, LengthConstraint.class);
2403 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MinLengthConstraint.class);
2406 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MaxLengthConstraint.class);
2409 propertyConstraint = deserializeConstraintWithStringPatternOperand(value, PatternConstraint.class);
2412 log.warn("Key {} is not supported. Ignored.", field.getKey());
2418 return propertyConstraint;
2421 private PropertyConstraint deserializeConstraint(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2422 return deserializeConstraintWithObjectOperand(convertToType(value), constraintClass);
2425 private PropertyConstraint deserializeConstraintWithObjectOperand(Object value, Class<? extends PropertyConstraint> constraintClass) {
2426 log.debug("Before adding value to {} object. value = {}", constraintClass, value);
2428 return constraintClass.getConstructor(Object.class).newInstance(value);
2429 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2430 | SecurityException exception) {
2431 log.error("Error deserializing constraint", exception);
2436 private PropertyConstraint deserializeConstraintWithStringPatternOperand(JsonNode value,
2437 Class<? extends PropertyConstraint> constraintClass) {
2438 String asString = value.asText();
2439 log.debug("Before adding value to {} object. value = {}", constraintClass, asString);
2441 return constraintClass.getConstructor(String.class).newInstance(asString);
2442 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2443 | SecurityException exception) {
2444 log.error("Error deserializing constraint", exception);
2449 private PropertyConstraint deserializeConstraintWithIntegerOperand(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2450 Integer asInt = value.asInt();
2451 log.debug("Before adding value to {} object. value = {}", constraintClass, asInt);
2453 return constraintClass.getConstructor(Integer.class).newInstance(asInt);
2454 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2455 | SecurityException exception) {
2456 log.error("Error deserializing constraint", exception);
2461 private PropertyConstraint deserializeInRangeConstraint(JsonNode value) {
2462 if (value instanceof ArrayNode) {
2463 ArrayNode rangeArray = (ArrayNode) value;
2464 if (rangeArray.size() != 2) {
2465 log.error("The range constraint content is invalid. value = {}", value);
2467 final Object minValue = convertToType(rangeArray.get(0));
2468 final Object maxValue = convertToType(rangeArray.get(1));
2469 final Comparable min = ConstraintUtil.convertToComparable(
2470 ToscaType.getToscaType(minValue.getClass().getSimpleName().toLowerCase()), String.valueOf(minValue));
2471 final Comparable max = ConstraintUtil.convertToComparable(
2472 ToscaType.getToscaType(maxValue.getClass().getSimpleName().toLowerCase()), String.valueOf(maxValue));
2474 return new InRangeConstraint(Arrays.asList(min, max));
2480 private PropertyConstraint deserializeValidValuesConstraint(JsonNode value) {
2481 ArrayNode rangeArray = (ArrayNode) value;
2482 if (rangeArray.size() == 0) {
2483 log.error("The valid values constraint content is invalid. value = {}", value);
2485 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2486 List<Object> validValues = new ArrayList<>();
2487 for (JsonNode jsonElement : rangeArray) {
2488 validValues.add(convertToType(jsonElement));
2490 vvConstraint.setValidValues(validValues);
2491 return vvConstraint;
2496 private Object convertToType(JsonNode jsonElement) {
2497 if (jsonElement.getNodeType().equals(JsonNodeType.NUMBER)) {
2498 float asFloat = (float) jsonElement.asDouble();
2499 if ((asFloat % 1) == 0) {
2500 return jsonElement.asInt();
2504 } else if (jsonElement.getNodeType().equals(JsonNodeType.BOOLEAN)) {
2505 return jsonElement.asBoolean();
2506 } else if (jsonElement.getNodeType().equals(JsonNodeType.ARRAY)) {
2507 List<Object> listValues = new ArrayList<>();
2508 for (JsonNode jsonArrayElement : jsonElement) {
2509 listValues.add(convertToType(jsonArrayElement));
2513 return jsonElement.asText();