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.StringEscapeUtils;
63 import org.apache.commons.lang3.StringUtils;
64 import org.apache.commons.lang3.tuple.ImmutablePair;
65 import org.apache.tinkerpop.gremlin.structure.Edge;
66 import org.apache.tinkerpop.gremlin.structure.Vertex;
67 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
68 import org.janusgraph.core.JanusGraph;
69 import org.janusgraph.core.JanusGraphVertex;
70 import org.janusgraph.core.JanusGraphVertexProperty;
71 import org.openecomp.sdc.be.config.BeEcompErrorManager;
72 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
73 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
74 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
75 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
76 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
77 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
78 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
79 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
80 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
81 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
82 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
83 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
84 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
85 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
86 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
87 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
88 import org.openecomp.sdc.be.model.Component;
89 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
90 import org.openecomp.sdc.be.model.DataTypeDefinition;
91 import org.openecomp.sdc.be.model.IComplexDefaultValue;
92 import org.openecomp.sdc.be.model.PropertyConstraint;
93 import org.openecomp.sdc.be.model.PropertyDefinition;
94 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
95 import org.openecomp.sdc.be.model.operations.api.IPropertyOperation;
96 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
97 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
98 import org.openecomp.sdc.be.model.tosca.ToscaType;
99 import org.openecomp.sdc.be.model.tosca.constraints.ConstraintUtil;
100 import org.openecomp.sdc.be.model.tosca.constraints.EqualConstraint;
101 import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint;
102 import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
103 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
104 import org.openecomp.sdc.be.model.tosca.constraints.LengthConstraint;
105 import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
106 import org.openecomp.sdc.be.model.tosca.constraints.LessThanConstraint;
107 import org.openecomp.sdc.be.model.tosca.constraints.MaxLengthConstraint;
108 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
109 import org.openecomp.sdc.be.model.tosca.constraints.PatternConstraint;
110 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
111 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
112 import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator;
113 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
114 import org.openecomp.sdc.be.resources.data.DataTypeData;
115 import org.openecomp.sdc.be.resources.data.ModelData;
116 import org.openecomp.sdc.be.resources.data.PropertyData;
117 import org.openecomp.sdc.be.resources.data.PropertyValueData;
118 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
119 import org.openecomp.sdc.be.resources.data.UniqueIdData;
120 import org.openecomp.sdc.common.log.wrappers.Logger;
121 import org.springframework.beans.factory.annotation.Autowired;
123 @org.springframework.stereotype.Component("property-operation")
124 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
126 private static final String AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS = "After retrieving DERIVED_FROM node of {}. status is {}";
127 private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
128 private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
129 private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
130 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
131 private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS =
132 "Failed to associate resource {} to property {} in graph. status is {}";
133 private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
134 private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
135 private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
136 private static final String PROPERTY = "Property";
137 private static final String UPDATE_DATA_TYPE = "UpdateDataType";
138 private static final Logger log = Logger.getLogger(PropertyOperation.class.getName());
139 private final DerivedFromOperation derivedFromOperation;
140 private ToscaFunctionValidator toscaFunctionValidator;
141 private DataTypeOperation dataTypeOperation;
144 public PropertyOperation(final HealingJanusGraphGenericDao janusGraphGenericDao, final DerivedFromOperation derivedFromOperation) {
145 this.janusGraphGenericDao = janusGraphGenericDao;
146 this.derivedFromOperation = derivedFromOperation;
150 public void setToscaFunctionValidator(final ToscaFunctionValidator toscaFunctionValidator) {
151 this.toscaFunctionValidator = toscaFunctionValidator;
154 //circular dependency DataTypeOperation->ModelOperation->ModelElementOperation->PropertyOperation
156 public void setDataTypeOperation(DataTypeOperation dataTypeOperation) {
157 this.dataTypeOperation = dataTypeOperation;
160 public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
161 log.debug("The object returned after create property is {}", propertyDataResult);
162 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
163 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
164 propertyDefResult.setName(propertyName);
165 return propertyDefResult;
168 public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
169 Either<PropertyData, JanusGraphOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
170 if (either.isRight()) {
171 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
172 return Either.right(storageStatus);
174 return Either.left(either.left().value());
178 * @param propertyDefinition
182 public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
183 log.trace("Going to validate property type and value. {}", propertyDefinition);
184 String propertyType = propertyDefinition.getType();
185 String value = propertyDefinition.getDefaultValue();
186 ToscaPropertyType type = getType(propertyType);
188 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
189 if (dataTypeDefinition == null) {
190 log.debug("The type {} of property cannot be found.", propertyType);
191 return StorageOperationStatus.INVALID_TYPE;
193 return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
195 String innerType = null;
196 Either<String, JanusGraphOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
197 if (checkInnerType.isRight()) {
198 return StorageOperationStatus.INVALID_TYPE;
200 innerType = checkInnerType.left().value();
201 log.trace("After validating property type {}", propertyType);
202 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
203 if (!isValidProperty) {
204 log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
205 return StorageOperationStatus.INVALID_VALUE;
207 PropertyValueConverter converter = type.getConverter();
208 if (isEmptyValue(value)) {
209 log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
210 propertyDefinition.setDefaultValue(EMPTY_VALUE);
211 } else if (!isEmptyValue(value)) {
212 String convertedValue = converter.convert(value, innerType, dataTypes);
213 propertyDefinition.setDefaultValue(convertedValue);
215 return StorageOperationStatus.OK;
218 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition,
220 ResourceMetadataData resourceData = new ResourceMetadataData();
221 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
222 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
223 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
224 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
225 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
226 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
227 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
228 if (createNodeResult.isRight()) {
229 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
230 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
231 return Either.right(operationStatus);
233 Map<String, Object> props = new HashMap<>();
234 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
235 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
236 .createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
237 if (createRelResult.isRight()) {
238 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
239 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
240 return Either.right(operationStatus);
242 return Either.left(createNodeResult.left().value());
245 public JanusGraphOperationStatus addPropertyToGraphByVertex(JanusGraphVertex metadataVertex, String propertyName,
246 PropertyDefinition propertyDefinition, String resourceId) {
247 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
248 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
249 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
250 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
251 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData);
252 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
253 if (createNodeResult.isRight()) {
254 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
255 log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
256 return operationStatus;
258 Map<String, Object> props = new HashMap<>();
259 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
260 JanusGraphVertex propertyVertex = createNodeResult.left().value();
261 JanusGraphOperationStatus createRelResult = janusGraphGenericDao.createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
262 if (!createRelResult.equals(JanusGraphOperationStatus.OK)) {
263 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
264 return createRelResult;
266 return createRelResult;
269 public JanusGraphGenericDao getJanusGraphGenericDao() {
270 return janusGraphGenericDao;
276 * @param janusGraphGenericDao
278 public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
279 this.janusGraphGenericDao = janusGraphGenericDao;
282 public Either<PropertyData, JanusGraphOperationStatus> deletePropertyFromGraph(String propertyId) {
283 log.debug("Before deleting property from graph {}", propertyId);
284 return janusGraphGenericDao.deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
287 public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition,
288 Map<String, DataTypeDefinition> dataTypes) {
289 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
290 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
291 return Either.right(validateAndUpdateProperty);
293 Either<PropertyData, JanusGraphOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
294 if (either.isRight()) {
295 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
296 return Either.right(storageStatus);
298 return Either.left(either.left().value());
301 public Either<PropertyData, JanusGraphOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
302 if (log.isDebugEnabled()) {
303 log.debug("Before updating property on graph {}", propertyId);
305 // get the original property data
306 Either<PropertyData, JanusGraphOperationStatus> statusProperty = janusGraphGenericDao
307 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
308 if (statusProperty.isRight()) {
309 log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
310 return Either.right(statusProperty.right().value());
312 PropertyData orgPropertyData = statusProperty.left().value();
313 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
314 // create new property data to update
315 PropertyData newPropertyData = new PropertyData();
316 newPropertyData.setPropertyDataDefinition(propertyDefinition);
317 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
318 // update the original property data with new values
319 if (orgPropertyDataDefinition.getDefaultValue() == null) {
320 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
322 if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
323 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
326 if (orgPropertyDataDefinition.getDescription() == null) {
327 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
329 if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
330 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
333 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
334 orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
336 if (newPropertyData.getConstraints() != null) {
337 orgPropertyData.setConstraints(newPropertyData.getConstraints());
339 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
340 return janusGraphGenericDao.updateNode(orgPropertyData, PropertyData.class);
343 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition,
344 NodeTypeEnum nodeType, String uniqueId) {
345 return addPropertyToNodeType(propertyName, propertyDefinition, nodeType, uniqueId, true);
348 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(final String propertyName,
349 final PropertyDefinition propertyDefinition,
350 final NodeTypeEnum nodeType, final String uniqueId,
351 final boolean inTransaction) {
352 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
353 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
354 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
355 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
356 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
357 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
358 if (createNodeResult.isRight()) {
359 if (!inTransaction) {
360 janusGraphGenericDao.rollback();
362 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
363 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
364 return Either.right(operationStatus);
366 Map<String, Object> props = new HashMap<>();
367 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
368 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
369 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
370 Either<GraphRelation, JanusGraphOperationStatus> createRelResult =
371 janusGraphGenericDao.createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
372 if (createRelResult.isRight()) {
373 if (!inTransaction) {
374 janusGraphGenericDao.rollback();
376 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
377 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
378 return Either.right(operationStatus);
380 if (!inTransaction) {
381 janusGraphGenericDao.commit();
383 return Either.left(createNodeResult.left().value());
386 public Either<PropertyDefinition, JanusGraphOperationStatus> updatePropertyAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
387 PropertyDefinition newProperty) {
388 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
390 if (oldPropertiesRes.isRight()) {
391 return Either.right(oldPropertiesRes.right().value());
393 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
394 PropertyDefinition oldPropDef = oldProperties.get(newProperty.getName());
395 JanusGraphOperationStatus status = updateOldProperty(newProperty, oldPropDef);
396 if (status != JanusGraphOperationStatus.OK) {
397 return Either.right(status);
400 return Either.left(newProperty);
403 public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
404 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
405 Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
406 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
408 if (childrenNodes.isRight()) {
409 JanusGraphOperationStatus operationStatus = childrenNodes.right().value();
410 return Either.right(operationStatus);
412 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
413 if (values != null) {
414 for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
415 GraphEdge edge = immutablePair.getValue();
416 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
417 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
418 PropertyData propertyData = immutablePair.getKey();
419 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
420 resourceProps.put(propertyName, propertyDefinition);
423 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
424 return Either.left(resourceProps);
427 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
428 return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId).right()
429 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
432 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
433 Map<String, PropertyDefinition> newProperties) {
434 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
435 Map<String, PropertyDefinition> reallyNewProperties;
436 Map<String, PropertyData> unchangedPropsData;
437 if (oldPropertiesRes.isRight()) {
438 JanusGraphOperationStatus err = oldPropertiesRes.right().value();
439 if (err == JanusGraphOperationStatus.NOT_FOUND) {
440 reallyNewProperties = newProperties;
441 unchangedPropsData = Collections.emptyMap();
443 return Either.right(err);
446 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
447 reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
448 for (Entry<String, PropertyDefinition> oldEntry : oldProperties.entrySet()) {
449 String key = oldEntry.getKey();
450 PropertyDefinition newPropDef = newProperties != null ? newProperties.get(key) : null;
451 PropertyDefinition oldPropDef = oldEntry.getValue();
452 JanusGraphOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
453 if (status != JanusGraphOperationStatus.OK) {
454 return Either.right(status);
457 unchangedPropsData = oldProperties.entrySet().stream()
458 .collect(Collectors.toMap(Entry::getKey, e -> new PropertyData(e.getValue(), null)));
460 // add other properties
461 return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
465 * @param newProperties
466 * @param oldProperties
469 private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties,
470 Map<String, PropertyDefinition> oldProperties) {
471 return newProperties != null ? newProperties.entrySet().stream().filter(entry -> !oldProperties.containsKey(entry.getKey()))
472 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)) : null;
479 private JanusGraphOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
480 if (!isUpdateAllowed(newPropDef, oldPropDef)) {
481 return JanusGraphOperationStatus.MATCH_NOT_FOUND;
483 if (isUpdateRequired(newPropDef, oldPropDef)) {
484 modifyOldPropByNewOne(newPropDef, oldPropDef);
485 List<PropertyConstraint> constraints = oldPropDef.getConstraints();
486 PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
487 Either<PropertyData, JanusGraphOperationStatus> updateResult = janusGraphGenericDao.updateNode(node, PropertyData.class);
488 if (updateResult.isRight()) {
489 return updateResult.right().value();
492 return JanusGraphOperationStatus.OK;
499 private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
500 if (newPropDef == null) {
501 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
504 // If the property type is missing it's something that we could want to fix
505 if (oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
506 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
513 * Update only fields which modification is permitted.
518 private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
519 oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
520 oldPropDef.setDescription(newPropDef.getDescription());
521 oldPropDef.setRequired(newPropDef.isRequired());
522 oldPropDef.setConstraints(newPropDef.getConstraints());
523 // Type is updated to fix possible null type issue in janusGraph DB
524 oldPropDef.setType(newPropDef.getType());
527 private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
528 return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) || !StringUtils
529 .equals(oldPropDef.getDescription(), newPropDef.getDescription()) || oldPropDef.isRequired() != newPropDef.isRequired();
533 * Adds newProperties and returns in case of success (left part of Either) map of all properties i. e. added ones and contained in
538 * @param newProperties
539 * @param unchangedPropsData
542 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId,
543 Map<String, PropertyDefinition> newProperties,
544 Map<String, PropertyData> unchangedPropsData) {
545 return addPropertiesToElementType(uniqueId, nodeType, newProperties).left().map(m -> {
546 m.putAll(unchangedPropsData);
551 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType,
553 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
554 if (propertiesOfNodeRes.isRight()) {
555 JanusGraphOperationStatus status = propertiesOfNodeRes.right().value();
556 if (status == JanusGraphOperationStatus.NOT_FOUND) {
557 return Either.right(StorageOperationStatus.OK);
559 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
561 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
562 for (PropertyDefinition propertyDefinition : value.values()) {
563 String propertyUid = propertyDefinition.getUniqueId();
564 Either<PropertyData, JanusGraphOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
565 if (deletePropertyRes.isRight()) {
566 log.error("Failed to delete property with id {}", propertyUid);
567 JanusGraphOperationStatus status = deletePropertyRes.right().value();
568 if (status == JanusGraphOperationStatus.NOT_FOUND) {
569 status = JanusGraphOperationStatus.INVALID_ID;
571 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
574 log.debug("The properties deleted from node {} are {}", uniqueId, value);
575 return Either.left(value);
579 * 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
580 * (including derived from hierarchy)
584 * @param propertyName
585 * @param propertyType
588 public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
589 boolean result = false;
590 if (!CollectionUtils.isEmpty(properties)) {
591 for (PropertyDefinition propertyDefinition : properties) {
592 if (propertyDefinition.getName().equals(propertyName) && (propertyDefinition.getParentUniqueId().equals(resourceUid)
593 || !propertyDefinition.getType().equals(propertyType))) {
602 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType,
603 Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
604 if (rules == null || rules.isEmpty()) {
605 return new ImmutablePair<>(null, true);
607 for (PropertyRule rule : rules) {
608 String value = rule.getValue();
609 Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
610 if (updateResult.isRight()) {
611 Boolean status = updateResult.right().value();
613 return new ImmutablePair<>(value, status);
616 String newValue = null;
617 Object object = updateResult.left().value();
618 if (object != null) {
619 newValue = object.toString();
621 rule.setValue(newValue);
624 return new ImmutablePair<>(null, true);
627 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
628 String resourceInstanceId) {
629 List<PropertyRule> rules = resourceInstanceProperty.getRules();
631 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
632 rules = new ArrayList<>();
633 rules.add(propertyRule);
635 rules = sortRules(rules);
637 propertyValueData.setRules(rules);
640 private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
641 String resourceInstanceId) {
642 List<String> path = resourceInstanceProperty.getPath();
643 // FOR BC. Since old Property values on VFC/VF does not have rules on
647 // Update could be done on one level only, thus we can use this
649 // operation to avoid migration.
650 if (path == null || path.isEmpty()) {
651 path = new ArrayList<>();
652 path.add(resourceInstanceId);
654 PropertyRule propertyRule = new PropertyRule();
655 propertyRule.setRule(path);
656 propertyRule.setValue(propertyValueData.getValue());
660 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
661 // TODO: sort the rules by size and binary representation.
663 // (x, y, .+) --> 110 6 priority 1
665 // (x, .+, z) --> 101 5 priority 2
669 public ImmutablePair<JanusGraphOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
670 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
671 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllRes = this
672 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
673 if (getAllRes.isRight()) {
674 JanusGraphOperationStatus status = getAllRes.right().value();
675 log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
676 return new ImmutablePair<>(status, null);
678 List<ComponentInstanceProperty> list = getAllRes.left().value();
680 for (ComponentInstanceProperty instanceProperty : list) {
681 String propertyUniqueId = instanceProperty.getUniqueId();
682 String valueUniqueUid = instanceProperty.getValueUniqueUid();
683 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
684 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
685 log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
686 return new ImmutablePair<>(JanusGraphOperationStatus.ALREADY_EXIST, valueUniqueUid);
690 return new ImmutablePair<>(JanusGraphOperationStatus.NOT_FOUND, null);
693 public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
694 String resourceInstanceId) {
695 List<PropertyRule> currentRules = propertyValueData.getRules();
696 List<PropertyRule> rules = resourceInstanceProperty.getRules();
697 // if rules are not supported.
699 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
700 rules = new ArrayList<>();
701 rules.add(propertyRule);
702 if (currentRules != null) {
703 rules = mergeRules(currentRules, rules);
706 // Full mode. all rules are sent in update operation.
707 rules = sortRules(rules);
709 propertyValueData.setRules(rules);
712 private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
713 List<PropertyRule> mergedRules = new ArrayList<>();
714 if (newRules == null || newRules.isEmpty()) {
717 for (PropertyRule rule : currentRules) {
718 PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
719 mergedRules.add(propertyRule);
721 for (PropertyRule rule : newRules) {
722 PropertyRule foundRule = findRuleInList(rule, mergedRules);
723 if (foundRule != null) {
724 foundRule.setValue(rule.getValue());
726 mergedRules.add(rule);
732 private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
733 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
736 PropertyRule foundRule = null;
737 for (PropertyRule propertyRule : rules) {
738 if (rule.getRuleSize() != propertyRule.getRuleSize()) {
741 boolean equals = propertyRule.compareRule(rule);
743 foundRule = propertyRule;
751 * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
753 * @param resourceInstanceUid
756 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
757 String resourceInstanceUid) {
758 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
761 public Either<PropertyValueData, JanusGraphOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
762 Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
763 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
764 if (findResInstanceRes.isRight()) {
765 JanusGraphOperationStatus status = findResInstanceRes.right().value();
766 if (status == JanusGraphOperationStatus.NOT_FOUND) {
767 status = JanusGraphOperationStatus.INVALID_ID;
769 return Either.right(status);
771 Either<PropertyValueData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
772 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
773 if (findPropertyDefRes.isRight()) {
774 JanusGraphOperationStatus status = findPropertyDefRes.right().value();
775 if (status == JanusGraphOperationStatus.NOT_FOUND) {
776 status = JanusGraphOperationStatus.INVALID_ID;
778 return Either.right(status);
780 Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
781 .getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
782 if (relation.isRight()) {
783 // TODO: add error in case of error
784 JanusGraphOperationStatus status = relation.right().value();
785 if (status == JanusGraphOperationStatus.NOT_FOUND) {
786 status = JanusGraphOperationStatus.INVALID_ID;
788 return Either.right(status);
790 Either<PropertyValueData, JanusGraphOperationStatus> deleteNode = janusGraphGenericDao
791 .deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
792 if (deleteNode.isRight()) {
793 return Either.right(deleteNode.right().value());
795 PropertyValueData value = deleteNode.left().value();
796 return Either.left(value);
799 public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid,
800 String resourceInstanceId,
801 boolean inTransaction) {
802 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
804 Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = this
805 .removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
806 if (eitherStatus.isRight()) {
807 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId,
808 eitherStatus.right().value().name());
809 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
812 PropertyValueData propertyValueData = eitherStatus.left().value();
813 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
814 propertyValueResult.setUniqueId(resourceInstanceId);
815 propertyValueResult.setValue(propertyValueData.getValue());
816 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
817 result = Either.left(propertyValueResult);
821 if (!inTransaction) {
822 if (result == null || result.isRight()) {
823 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
824 janusGraphGenericDao.rollback();
826 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
827 janusGraphGenericDao.commit();
833 public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData,
834 ComponentInstanceProperty resourceInstanceProperty) {
835 String value = propertyValueData.getValue();
836 String uid = propertyValueData.getUniqueId();
837 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
838 instanceProperty.setPath(resourceInstanceProperty.getPath());
839 return instanceProperty;
843 public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
844 if (propertyDefinition == null) {
847 String innerType = null;
848 String propertyType = propertyDefinition.getType();
849 ToscaPropertyType type = getType(propertyType);
850 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
851 SchemaDefinition def = propertyDefinition.getSchema();
855 PropertyDataDefinition propDef = def.getProperty();
856 if (propDef == null) {
859 innerType = propDef.getType();
861 String value = propertyDefinition.getDefaultValue();
863 return isValidValue(type, value, innerType, dataTypes);
865 log.trace("The given type {} is not a pre defined one.", propertyType);
866 DataTypeDefinition foundDt = dataTypes.get(propertyType);
867 if (foundDt != null) {
868 return isValidComplexValue(foundDt, value, dataTypes);
875 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final String model) {
876 if (property == null) {
879 if (ToscaPropertyType.isValidType(property.getType()) == null) {
880 Either<Boolean, JanusGraphOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType(), model);
881 if (definedInDataTypes.isRight()) {
884 Boolean isExist = definedInDataTypes.left().value();
885 return isExist.booleanValue();
891 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final Map<String, DataTypeDefinition> dataTypes) {
892 if (property == null) {
895 return ToscaPropertyType.isValidType(property.getType()) != null || dataTypes.containsKey(property.getType());
899 public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
900 if (property == null) {
901 return new ImmutablePair<>(null, false);
903 SchemaDefinition schema;
904 PropertyDataDefinition innerProp;
905 String innerType = null;
906 if ((schema = property.getSchema()) != null) {
907 if ((innerProp = schema.getProperty()) != null) {
908 innerType = innerProp.getType();
911 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
912 if (innerToscaType == null) {
913 DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
914 if (dataTypeDefinition == null) {
915 log.debug("The inner type {} is not a data type.", innerType);
916 return new ImmutablePair<>(innerType, false);
918 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
921 return new ImmutablePair<>(innerType, true);
924 private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
925 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
926 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
927 return validateAndUpdate.right.booleanValue();
930 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
931 String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
932 Either<JanusGraphVertex, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
933 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
934 if (findResInstanceRes.isRight()) {
935 JanusGraphOperationStatus status = findResInstanceRes.right().value();
936 if (status == JanusGraphOperationStatus.NOT_FOUND) {
937 status = JanusGraphOperationStatus.INVALID_ID;
939 return Either.right(status);
941 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> propertyImplNodes = janusGraphGenericDao
942 .getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
943 if (propertyImplNodes.isRight()) {
944 JanusGraphOperationStatus status = propertyImplNodes.right().value();
945 return Either.right(status);
947 List<ImmutablePair<JanusGraphVertex, Edge>> list = propertyImplNodes.left().value();
948 if (list == null || list.isEmpty()) {
949 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
951 List<ComponentInstanceProperty> result = new ArrayList<>();
952 for (ImmutablePair<JanusGraphVertex, Edge> propertyValue : list) {
953 JanusGraphVertex propertyValueDataVertex = propertyValue.getLeft();
954 String propertyValueUid = (String) janusGraphGenericDao
955 .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
956 String value = (String) janusGraphGenericDao.getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
957 ImmutablePair<JanusGraphVertex, Edge> propertyDefPair = janusGraphGenericDao
958 .getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
959 if (propertyDefPair == null) {
960 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
962 Map<String, Object> properties = janusGraphGenericDao.getProperties(propertyValueDataVertex);
963 PropertyValueData propertyValueData = GraphElementFactory
964 .createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
965 String propertyUniqueId = (String) janusGraphGenericDao
966 .getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
967 ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
968 // set property original unique id
969 resourceInstanceProperty.setUniqueId(propertyUniqueId);
972 // TODO: esofer add resource id
973 resourceInstanceProperty.setParentUniqueId(null);
975 resourceInstanceProperty.setValue(value);
976 // set property value unique id
977 resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
979 resourceInstanceProperty.setRules(propertyValueData.getRules());
980 result.add(resourceInstanceProperty);
982 return Either.left(result);
986 * Find the default value from the list of component instances. Start the search from the second component instance
988 * @param pathOfComponentInstances
989 * @param propertyUniqueId
990 * @param defaultValue
993 public Either<String, JanusGraphOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances,
994 String propertyUniqueId, String defaultValue) {
995 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
996 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
997 return Either.left(defaultValue);
999 String result = defaultValue;
1000 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
1001 String compInstanceId = pathOfComponentInstances.get(i);
1002 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> propertyValuesResult = this
1003 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
1004 log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
1005 if (propertyValuesResult.isRight()) {
1006 JanusGraphOperationStatus status = propertyValuesResult.right().value();
1007 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1008 return Either.right(status);
1013 ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
1014 log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
1015 if (foundCompInstanceProperty == null) {
1018 List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i),
1019 foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
1020 log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
1021 PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
1022 log.trace("Match rule is {}", matchedRule);
1023 if (matchedRule != null) {
1024 result = matchedRule.getValue();
1028 return Either.left(result);
1031 private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
1032 ComponentInstanceProperty result = null;
1036 for (ComponentInstanceProperty instProperty : list) {
1037 if (instProperty.getUniqueId().equals(propertyUniqueId)) {
1038 result = instProperty;
1045 private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
1046 if (rules != null) {
1049 rules = buildDefaultRule(compInstanceId, ruleSize, value);
1053 private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
1054 List<PropertyRule> rules = componentInstanceProperty.getRules();
1055 if (rules == null) {
1056 rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
1061 private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
1062 List<PropertyRule> rules = new ArrayList<>();
1063 List<String> rule = new ArrayList<>();
1064 rule.add(componentInstanceId);
1065 for (int i = 0; i < size - 1; i++) {
1066 rule.add(PropertyRule.getRuleAnyMatch());
1068 PropertyRule propertyRule = new PropertyRule(rule, value);
1069 rules.add(propertyRule);
1073 private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1074 PropertyRule propertyRule = null;
1075 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1076 String firstCompInstance = pathOfInstances.get(level);
1077 if (rules != null) {
1078 for (PropertyRule rule : rules) {
1079 int ruleSize = rule.getRule().size();
1080 // check the length of the rule equals to the length of the
1083 if (ruleSize != pathOfInstances.size() - level) {
1086 // check that the rule starts with correct component instance id
1087 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1090 String secondToken = rule.getToken(2);
1091 if (secondToken != null && (secondToken.equals(PropertyRule.getForceAll()) || secondToken.equals(PropertyRule.getALL()))) {
1092 propertyRule = rule;
1095 String patternStr = buildStringForMatch(rule.getRule(), 0);
1096 Pattern pattern = Pattern.compile(patternStr);
1097 Matcher matcher = pattern.matcher(stringForMatch);
1098 if (matcher.matches()) {
1099 if (log.isTraceEnabled()) {
1100 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1102 propertyRule = rule;
1107 return propertyRule;
1110 private boolean checkFirstItem(String left, String right) {
1111 return left != null && left.equals(right);
1114 private String buildStringForMatch(List<String> pathOfInstances, int level) {
1115 StringBuilder builder = new StringBuilder();
1116 for (int i = level; i < pathOfInstances.size(); i++) {
1117 builder.append(pathOfInstances.get(i));
1118 if (i < pathOfInstances.size() - 1) {
1119 builder.append("#");
1122 return builder.toString();
1125 public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty,
1126 Map<String, ComponentInstanceProperty> instanceIdToValue) {
1127 List<String> pathOfInstances = instanceProperty.getPath();
1129 int size = pathOfInstances.size();
1130 int numberOfMatches = 0;
1131 for (String instanceId : pathOfInstances) {
1132 ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1133 if (componentInstanceProperty != null) {
1134 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1135 // If it is the first level instance, then update valueUniuqeId
1137 // parameter in order to know on update that
1139 // we should update and not create new node on graph.
1141 instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1142 instanceProperty.setRules(rules);
1144 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1147 String value = rule.getValue();
1148 if (numberOfMatches == 1) {
1149 instanceProperty.setValue(value);
1150 if (log.isDebugEnabled()) {
1151 log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1152 pathOfInstances, value);
1154 } else if (numberOfMatches == 2) {
1155 // In case of another property value match, then use the
1157 // value to be the default value of the property.
1158 instanceProperty.setDefaultValue(value);
1159 if (log.isDebugEnabled()) {
1160 log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1161 pathOfInstances, value);
1172 * Add data type to graph.
1174 * 1. Add data type node
1176 * 2. Add edge between the former node to its parent(if exists)
1178 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1180 * @param dataTypeDefinition
1183 private Either<DataTypeData, JanusGraphOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1184 log.debug("Got data type {}", dataTypeDefinition);
1185 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getModel(), dataTypeDefinition.getName());
1186 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1187 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1188 Either<DataTypeData, JanusGraphOperationStatus> createDataTypeResult = janusGraphGenericDao.createNode(dataTypeData, DataTypeData.class);
1189 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1190 if (createDataTypeResult.isRight()) {
1191 JanusGraphOperationStatus operationStatus = createDataTypeResult.right().value();
1192 log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1193 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1194 return Either.right(operationStatus);
1196 DataTypeData resultCTD = createDataTypeResult.left().value();
1197 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1198 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(),
1199 dataTypeDefinition.getModel(),
1201 if (addPropertiesToDataType.isRight()) {
1202 log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1203 return Either.right(addPropertiesToDataType.right().value());
1206 final Either<GraphRelation, JanusGraphOperationStatus> modelRelationship = addDataTypeToModel(dataTypeDefinition);
1207 if (modelRelationship.isRight()) {
1208 return Either.right(modelRelationship.right().value());
1211 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1212 if (derivedFrom != null) {
1213 final Either<DataTypeDefinition, JanusGraphOperationStatus> derivedFromDataType = getDataTypeByNameValidForModel(derivedFrom,
1214 dataTypeDefinition.getModel());
1215 if (derivedFromDataType.isRight()) {
1216 return Either.right(derivedFromDataType.right().value());
1219 log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1220 UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1221 final String deriveFromUid = derivedFromDataType.left().value().getUniqueId();
1222 UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1223 Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
1224 .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1225 log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1226 if (createRelation.isRight()) {
1227 return Either.right(createRelation.right().value());
1230 return Either.left(createDataTypeResult.left().value());
1233 private Either<GraphRelation, JanusGraphOperationStatus> addDataTypeToModel(final DataTypeDefinition dataTypeDefinition) {
1234 final String model = dataTypeDefinition.getModel();
1235 if (model == null) {
1236 return Either.left(null);
1238 final GraphNode from = new UniqueIdData(NodeTypeEnum.Model, UniqueIdBuilder.buildModelUid(model));
1239 final GraphNode to = new UniqueIdData(NodeTypeEnum.DataType, dataTypeDefinition.getUniqueId());
1240 log.info("Connecting model {} to type {}", from, to);
1241 return janusGraphGenericDao.createRelation(from, to, GraphEdgeLabels.MODEL_ELEMENT, Collections.emptyMap());
1244 private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1245 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1246 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1247 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1248 if (creationDate == null) {
1249 creationDate = System.currentTimeMillis();
1251 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1252 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1253 return dataTypeData;
1257 * add properties to capability type.
1259 * Per property, add a property node and associate it to the capability type
1265 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType(final String uniqueId, final String modelName,
1266 final List<PropertyDefinition> properties) {
1267 Map<String, PropertyData> propertiesData = new HashMap<>();
1268 if (properties != null && !properties.isEmpty()) {
1269 for (PropertyDefinition propertyDefinition : properties) {
1270 String propertyName = propertyDefinition.getName();
1271 String propertyType = propertyDefinition.getType();
1272 Either<Boolean, JanusGraphOperationStatus> validPropertyType = isValidPropertyType(propertyType, modelName);
1273 if (validPropertyType.isRight()) {
1274 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1275 return Either.right(validPropertyType.right().value());
1277 Boolean isValid = validPropertyType.left().value();
1278 if (isValid == null || !isValid.booleanValue()) {
1279 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1280 return Either.right(JanusGraphOperationStatus.INVALID_TYPE);
1282 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1283 .addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1284 if (addPropertyToNodeType.isRight()) {
1285 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1286 log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1287 BeEcompErrorManager.getInstance()
1288 .logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus,
1289 ErrorSeverity.ERROR);
1290 return Either.right(operationStatus);
1292 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1294 DataTypeData dataTypeData = new DataTypeData();
1295 Either<DataTypeDefinition, StorageOperationStatus> existingNode = getDataTypeByUidWithoutDerived(uniqueId, true);
1296 if (existingNode.isLeft()) {
1297 dataTypeData.getDataTypeDataDefinition().setNormative(existingNode.left().value().isNormative());
1299 dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1301 long modificationTime = System.currentTimeMillis();
1302 dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1303 Either<DataTypeData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao.updateNode(dataTypeData, DataTypeData.class);
1304 if (updateNode.isRight()) {
1305 JanusGraphOperationStatus operationStatus = updateNode.right().value();
1306 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1307 BeEcompErrorManager.getInstance()
1308 .logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1309 return Either.right(operationStatus);
1311 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1314 return Either.left(propertiesData);
1317 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByNameValidForModel(final String name, final String modelName) {
1318 final Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1319 .getNode(GraphPropertiesDictionary.NAME.getProperty(), name, DataTypeData.class, modelName);
1320 if (dataTypesRes.isRight()) {
1321 final JanusGraphOperationStatus status = dataTypesRes.right().value();
1322 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, name, status);
1323 return Either.right(status);
1325 final DataTypeData dataType = dataTypesRes.left().value();
1326 final DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(dataType.getDataTypeDataDefinition());
1327 final JanusGraphOperationStatus propertiesStatus = fillProperties(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1328 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1329 log.error(BUSINESS_PROCESS_ERROR, FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, dataTypeDefinition.getUniqueId());
1330 return Either.right(propertiesStatus);
1332 final Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1333 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeDefinition.getUniqueId(), GraphEdgeLabels.DERIVED_FROM,
1334 NodeTypeEnum.DataType,
1335 DataTypeData.class);
1336 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, dataTypeDefinition.getUniqueId(), parentNode);
1337 if (parentNode.isRight()) {
1338 final JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1339 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1340 log.error(BUSINESS_PROCESS_ERROR, "Failed to find the parent data type of data type {}. status is {}",
1341 dataTypeDefinition.getUniqueId(), janusGraphOperationStatus);
1342 return Either.right(janusGraphOperationStatus);
1345 // derived from node was found
1346 final ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1347 final DataTypeData parentDataType = immutablePair.getKey();
1348 final Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentDataType.getUniqueId());
1349 if (dataTypeByUid.isRight()) {
1350 return Either.right(dataTypeByUid.right().value());
1352 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1353 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1355 return Either.left(dataTypeDefinition);
1359 * Build Data type object from graph by unique id
1364 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUid(String uniqueId) {
1365 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1366 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1367 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1368 if (dataTypesRes.isRight()) {
1369 JanusGraphOperationStatus status = dataTypesRes.right().value();
1370 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1371 return Either.right(status);
1373 DataTypeData ctData = dataTypesRes.left().value();
1374 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1375 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1376 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1377 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1378 return Either.right(propertiesStatus);
1380 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1381 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1382 DataTypeData.class);
1383 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1384 if (parentNode.isRight()) {
1385 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1386 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1387 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1388 result = Either.right(janusGraphOperationStatus);
1392 // derived from node was found
1393 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1394 DataTypeData parentCT = immutablePair.getKey();
1395 String parentUniqueId = parentCT.getUniqueId();
1396 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1397 if (dataTypeByUid.isRight()) {
1398 return Either.right(dataTypeByUid.right().value());
1400 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1401 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1403 result = Either.left(dataTypeDefinition);
1407 private JanusGraphOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1408 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this
1409 .findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1410 if (findPropertiesOfNode.isRight()) {
1411 JanusGraphOperationStatus janusGraphOperationStatus = findPropertiesOfNode.right().value();
1412 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, janusGraphOperationStatus);
1413 if (JanusGraphOperationStatus.NOT_FOUND.equals(janusGraphOperationStatus)) {
1414 return JanusGraphOperationStatus.OK;
1416 return janusGraphOperationStatus;
1419 Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1420 if (properties != null && !properties.isEmpty()) {
1421 List<PropertyDefinition> listOfProps = new ArrayList<>();
1422 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1423 String propName = entry.getKey();
1424 PropertyDefinition propertyDefinition = entry.getValue();
1425 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1426 newPropertyDefinition.setName(propName);
1427 listOfProps.add(newPropertyDefinition);
1429 dataTypeDefinition.setProperties(listOfProps);
1431 return JanusGraphOperationStatus.OK;
1435 private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1436 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1438 Either<DataTypeData, JanusGraphOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1439 if (eitherStatus.isRight()) {
1440 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1441 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1442 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1445 DataTypeData capabilityTypeData = eitherStatus.left().value();
1446 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1447 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1448 result = Either.left(dataTypeDefResult);
1452 if (!inTransaction) {
1453 if (result == null || result.isRight()) {
1454 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1455 janusGraphGenericDao.rollback();
1457 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1458 janusGraphGenericDao.commit();
1465 public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1466 return addDataType(dataTypeDefinition, true);
1470 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel,
1471 final boolean inTransaction) {
1472 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1474 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByNameValidForModel(name, validForModel);
1475 if (ctResult.isRight()) {
1476 JanusGraphOperationStatus status = ctResult.right().value();
1477 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1478 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1480 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1483 result = Either.left(ctResult.left().value());
1486 if (!inTransaction) {
1487 if (result == null || result.isRight()) {
1488 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1489 janusGraphGenericDao.rollback();
1491 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1492 janusGraphGenericDao.commit();
1499 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel) {
1500 return getDataTypeByName(name, validForModel, true);
1503 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByUidWithoutDerived(String uid, boolean inTransaction) {
1504 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1506 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1507 if (ctResult.isRight()) {
1508 JanusGraphOperationStatus status = ctResult.right().value();
1509 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1510 log.error(BUSINESS_PROCESS_ERROR, "Failed to retrieve information on data type {} status is {}", uid, status);
1512 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1515 result = Either.left(ctResult.left().value());
1518 if (!inTransaction) {
1519 if (result == null || result.isRight()) {
1520 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1521 janusGraphGenericDao.rollback();
1523 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1524 janusGraphGenericDao.commit();
1530 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1531 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1532 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1533 if (dataTypesRes.isRight()) {
1534 JanusGraphOperationStatus status = dataTypesRes.right().value();
1535 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1536 return Either.right(status);
1538 DataTypeData ctData = dataTypesRes.left().value();
1539 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1540 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1541 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1542 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1543 return Either.right(propertiesStatus);
1545 return Either.left(dataTypeDefinition);
1549 * convert between graph Node object to Java object
1551 * @param dataTypeData
1554 protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1555 log.debug("The object returned after create data type is {}", dataTypeData);
1556 return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1559 private Either<Boolean, JanusGraphOperationStatus> isValidPropertyType(String propertyType, final String modelName) {
1560 if (propertyType == null || propertyType.isEmpty()) {
1561 return Either.left(false);
1563 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1564 if (toscaPropertyType == null) {
1565 return isDefinedInDataTypes(propertyType, modelName);
1567 return Either.left(true);
1571 public Either<Boolean, JanusGraphOperationStatus> isDefinedInDataTypes(final String propertyType, final String modelName) {
1572 Either<DataTypeDefinition, JanusGraphOperationStatus> dataType = getDataTypeByNameValidForModel(propertyType, modelName);
1573 if (dataType.isRight()) {
1574 JanusGraphOperationStatus status = dataType.right().value();
1575 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1576 return Either.left(false);
1578 return Either.right(status);
1580 return Either.left(true);
1583 public Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> getAllDataTypes() {
1584 final Map<String, Map<String, DataTypeDefinition>> dataTypes = new HashMap<>();
1585 Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> result = Either.left(dataTypes);
1586 final Map<String, DataTypeDefinition> allDataTypesFound = new HashMap<>();
1588 final Map<String, List<String>> dataTypeUidstoModels = dataTypeOperation.getAllDataTypeUidsToModels();
1590 if (dataTypeUidstoModels != null) {
1591 log.trace("Number of data types to load is {}", dataTypeUidstoModels.size());
1592 for (final Map.Entry<String, List<String>> entry : dataTypeUidstoModels.entrySet()) {
1593 final String key = entry.getKey();
1594 log.trace("Going to fetch data type with uid {}", key);
1595 final Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getAndAddDataTypeByUid(key, allDataTypesFound);
1596 if (dataTypeByUid.isRight()) {
1597 JanusGraphOperationStatus status = dataTypeByUid.right().value();
1598 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1599 status = JanusGraphOperationStatus.INVALID_ID;
1601 return Either.right(status);
1603 for (final String model : entry.getValue()) {
1604 if (!dataTypes.containsKey(model)) {
1605 dataTypes.put(model, new HashMap<>());
1607 DataTypeDefinition dataTypeDefinition = allDataTypesFound.get(entry.getKey());
1608 dataTypes.get(model).put(dataTypeDefinition.getName(), dataTypeDefinition);
1612 if (log.isTraceEnabled()) {
1613 if (result.isRight()) {
1614 log.trace("After fetching all data types {}", result);
1616 Map<String, Map<String, DataTypeDefinition>> map = result.left().value();
1618 String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1619 log.trace("After fetching all data types {} ", types);
1627 * Build Data type object from graph by unique id
1632 private Either<DataTypeDefinition, JanusGraphOperationStatus> getAndAddDataTypeByUid(String uniqueId,
1633 Map<String, DataTypeDefinition> allDataTypes) {
1634 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1635 if (allDataTypes.containsKey(uniqueId)) {
1636 return Either.left(allDataTypes.get(uniqueId));
1638 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1639 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1640 if (dataTypesRes.isRight()) {
1641 JanusGraphOperationStatus status = dataTypesRes.right().value();
1642 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1643 return Either.right(status);
1645 DataTypeData ctData = dataTypesRes.left().value();
1646 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1647 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1648 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1649 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1650 return Either.right(propertiesStatus);
1652 allDataTypes.put(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1653 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1654 if (allDataTypes.containsKey(derivedFrom)) {
1655 DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1656 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1657 return Either.left(dataTypeDefinition);
1659 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1660 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1661 DataTypeData.class);
1662 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1663 if (parentNode.isRight()) {
1664 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1665 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1666 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1667 result = Either.right(janusGraphOperationStatus);
1671 // derived from node was found
1672 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1673 DataTypeData parentCT = immutablePair.getKey();
1674 String parentUniqueId = parentCT.getUniqueId();
1675 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1676 if (dataTypeByUid.isRight()) {
1677 return Either.right(dataTypeByUid.right().value());
1679 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1680 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1681 final var model = getModel(uniqueId);
1682 if (StringUtils.isNotEmpty(model)) {
1683 dataTypeDefinition.setModel(model);
1686 result = Either.left(dataTypeDefinition);
1690 private String getModel(final String uniqueId) {
1691 final Either<ImmutablePair<ModelData, GraphEdge>, JanusGraphOperationStatus> model = janusGraphGenericDao.getParentNode(
1692 UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.MODEL_ELEMENT,
1693 NodeTypeEnum.Model, ModelData.class);
1694 return model.isLeft() ? model.left().value().getLeft().getName() : StringUtils.EMPTY;
1697 public Either<String, JanusGraphOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
1698 String propertyType = propDataDef.getType();
1699 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
1700 return getInnerType(type, propDataDef::getSchema);
1703 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType,
1704 Map<String, DataTypeDefinition> dataTypes) {
1705 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
1706 final ToscaPropertyType type = getType(propertyType);
1709 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
1710 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter
1711 .validateAndUpdate(value, dataTypeDefinition, dataTypes);
1712 if (Boolean.FALSE.equals(validateResult.right)) {
1713 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
1714 return Either.right(false);
1716 JsonElement jsonElement = validateResult.left;
1717 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
1718 return Either.left(valueFromJsonElement);
1720 log.trace("before validating property type {}", propertyType);
1721 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
1722 if (!isValidProperty) {
1723 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
1724 return Either.right(false);
1727 Object convertedValue = value;
1728 if (!isEmptyValue(value) && isValidate) {
1729 PropertyValueConverter converter = type.getConverter();
1730 convertedValue = converter.convert(value, innerType, dataTypes);
1732 return Either.left(convertedValue);
1735 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType,
1736 Map<String, DataTypeDefinition> dataTypes) {
1737 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
1740 public Either<Object, Boolean> validateAndUpdatePropertyValue(final Component containerComponent, final PropertyDataDefinition property,
1741 final Map<String, DataTypeDefinition> dataTypes) {
1742 if (property.isToscaFunction()) {
1743 toscaFunctionValidator.validate(property, containerComponent);
1744 property.setValue(StringEscapeUtils.unescapeJava(property.getToscaFunction().getValue()));
1745 return Either.left(property.getValue());
1747 Either<String, JanusGraphOperationStatus> checkInnerType = checkInnerType(property);
1748 if (checkInnerType.isRight()) {
1749 return Either.right(false);
1751 final String innerType = checkInnerType.left().value();
1752 return validateAndUpdatePropertyValue(property.getType(), property.getValue(), true, innerType, dataTypes);
1755 public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType,
1757 return this.findPropertiesOfNode(nodeType, uniqueId).right().bind(this::handleNotFoundProperties).left()
1758 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
1761 private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(
1762 JanusGraphOperationStatus janusGraphOperationStatus) {
1763 if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
1764 return Either.left(new HashMap<>());
1766 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1769 private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId,
1770 NodeTypeEnum nodeType,
1772 Collection<PropertyDefinition> nodeProps) {
1773 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
1774 String currentNodeUid = uniqueId;
1775 Either<T, StorageOperationStatus> derivedFrom;
1776 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
1777 currentNodeUid = derivedFrom.left().value().getUniqueId();
1778 JanusGraphOperationStatus janusGraphOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
1779 if (janusGraphOperationStatus != JanusGraphOperationStatus.OK) {
1780 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
1781 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1784 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
1785 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
1788 private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
1789 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
1792 public JanusGraphOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
1793 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
1794 if (findPropertiesRes.isRight()) {
1795 return findPropertiesRes.right().value();
1797 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
1798 if (properties != null) {
1799 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
1800 propertySetter.accept(propertiesAsList);
1802 return JanusGraphOperationStatus.OK;
1805 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType) {
1806 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
1807 if (findPropertiesOfNode.isRight()) {
1808 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
1809 if (findPropertiesOfNode.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
1810 return Either.left(Maps.newHashMap());
1812 return findPropertiesOfNode;
1814 return findPropertiesOfNode;
1818 * add properties to element type.
1820 * Per property, add a property node and associate it to the element type
1823 * @param propertiesMap
1826 protected Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType,
1827 Map<String, PropertyDefinition> propertiesMap) {
1828 Map<String, PropertyData> propertiesData = new HashMap<>();
1829 if (propertiesMap != null) {
1830 for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
1831 String propertyName = propertyDefinitionEntry.getKey();
1832 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1833 .addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
1834 if (addPropertyToNodeType.isRight()) {
1835 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1836 log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName,
1838 return Either.right(operationStatus);
1840 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1843 return Either.left(propertiesData);
1846 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType,
1847 List<PropertyDefinition> properties) {
1848 Map<String, PropertyDefinition> propMap;
1849 if (properties == null) {
1852 propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
1854 return addPropertiesToElementType(uniqueId, elementType, propMap);
1858 public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1859 DataTypeDefinition oldDataTypeDefinition) {
1860 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
1863 private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1864 DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
1865 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1867 List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
1868 List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
1869 String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
1870 String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
1871 String dataTypeName = newDataTypeDefinition.getName();
1872 List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
1873 if (isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, propertiesToAdd)
1874 || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
1875 log.debug("The new data type {} is invalid.", dataTypeName);
1876 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
1879 if (CollectionUtils.isEmpty(propertiesToAdd)) {
1880 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
1881 result = Either.right(StorageOperationStatus.OK);
1884 Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
1885 if (MapUtils.isNotEmpty(newDescriptions)) {
1886 JanusGraphOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(),
1888 if (updatePropertiesStatus != JanusGraphOperationStatus.OK) {
1889 log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}",
1890 oldDataTypeDefinition, updatePropertiesStatus);
1891 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1892 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatePropertiesStatus));
1896 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(
1897 oldDataTypeDefinition.getUniqueId(), oldDataTypeDefinition.getModel(), propertiesToAdd);
1898 if (addPropertiesToDataType.isRight()) {
1899 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition,
1900 addPropertiesToDataType.right().value().name());
1901 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1902 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToDataType.right().value()));
1905 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
1906 if (dataTypeByUid.isRight()) {
1907 JanusGraphOperationStatus status = addPropertiesToDataType.right().value();
1908 log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
1909 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
1910 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
1912 result = Either.left(dataTypeByUid.left().value());
1917 if (!inTransaction) {
1918 if (result == null || result.isRight()) {
1919 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1920 janusGraphGenericDao.rollback();
1922 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1923 janusGraphGenericDao.commit();
1929 private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties,
1930 List<PropertyDefinition> outputPropertiesToAdd) {
1931 if (newProperties != null && oldProperties != null) {
1932 Map<String, PropertyDefinition> newPropsMapper = newProperties.stream()
1933 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1934 Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream()
1935 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1936 for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
1937 String propName = newPropertyEntry.getKey();
1938 PropertyDefinition propDef = newPropertyEntry.getValue();
1939 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
1940 if (oldPropertyDefinition == null) {
1941 log.debug("New property {} received in the data type {}", propName, dataTypeName);
1942 outputPropertiesToAdd.add(propDef);
1945 String oldType = oldPropertyDefinition.getType();
1946 String oldEntryType = getEntryType(oldPropertyDefinition);
1947 String newType = propDef.getType();
1948 String newEntryType = getEntryType(propDef);
1949 if (!oldType.equals(newType)) {
1950 log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType,
1954 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
1955 log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName,
1956 oldEntryType, newEntryType);
1964 private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
1965 if (oldEntryType == null && newEntryType == null) {
1967 } else if (oldEntryType != null && newEntryType != null) {
1968 return oldEntryType.equals(newEntryType);
1974 private String getEntryType(PropertyDefinition oldPropertyDefinition) {
1975 String entryType = null;
1976 SchemaDefinition schema = oldPropertyDefinition.getSchema();
1977 if (schema != null) {
1978 PropertyDataDefinition schemaProperty = schema.getProperty();
1979 if (schemaProperty != null) {
1980 entryType = schemaProperty.getType();
1986 private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
1987 if (newDerivedFromName != null) {
1988 boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
1990 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1991 oldDerivedFromName);
1994 } else if (oldDerivedFromName == null) {
1996 } else {// new=null, old != null
1997 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1998 oldDerivedFromName);
2008 public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
2009 Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
2010 if (graphResult.isRight()) {
2011 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
2013 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
2014 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
2015 if (vertexService.isRight()) {
2016 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
2017 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
2019 Vertex vertex = vertexService.left().value();
2020 VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
2021 Integer counter = 0;
2022 if (vertexProperty.isPresent() && vertexProperty.value() != null) {
2023 counter = (Integer) vertexProperty.value();
2026 vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
2027 return Either.left(counter);
2030 public Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesUniqueness(
2031 Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
2032 Either<List<PropertyDefinition>, JanusGraphOperationStatus> result = Either.left(properties);
2033 for (PropertyDefinition property : properties) {
2034 JanusGraphOperationStatus status = validatePropertyUniqueness(inheritedProperties, property);
2035 if (status != JanusGraphOperationStatus.OK) {
2036 result = Either.right(status);
2044 * Validates uniqueness of examined property by comparing it with properties in propertiesOfType and updates if need type and inner type of the
2047 private JanusGraphOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2048 String propertyName = property.getName();
2049 String propertyType = property.getType();
2050 JanusGraphOperationStatus result = JanusGraphOperationStatus.OK;
2051 if (inheritedProperties.containsKey(propertyName)) {
2052 PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2053 if (typesMismatch(propertyType, defaultProperty.getType())) {
2054 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2055 result = JanusGraphOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2057 property.setType(defaultProperty.getType());
2058 String innerType = defaultProperty.getSchemaType();
2059 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2060 if (schemaProperty != null) {
2061 schemaProperty.setType(innerType);
2068 private boolean typesMismatch(String type1, String type2) {
2069 return type1 != null && type2 != null && !type2.equals(type1);
2072 public <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllTypePropertiesFromAllDerivedFrom(
2073 String nextParentUid, NodeTypeEnum nodeType, Class<T> clazz) {
2074 Map<String, PropertyDefinition> allProperies = new HashMap<>();
2075 return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2078 private <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getTypePropertiesFromDerivedFromRecursively(
2079 String nextParentUid, Map<String, PropertyDefinition> allProperies, NodeTypeEnum nodeType, Class<T> clazz) {
2080 JanusGraphOperationStatus error;
2081 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
2082 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2083 if (childrenNodes.isRight()) {
2084 if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
2085 error = childrenNodes.right().value();
2086 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid,
2088 return Either.right(error);
2090 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.",
2092 return Either.left(allProperies);
2095 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2096 if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
2097 error = allPropertiesOfTypeRes.right().value();
2099 "#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}",
2100 nextParentUid, error);
2101 return Either.right(error);
2102 } else if (allPropertiesOfTypeRes.isLeft()) {
2103 if (allProperies.isEmpty()) {
2104 allProperies.putAll(allPropertiesOfTypeRes.left().value());
2106 allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey()))
2107 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2110 return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType,
2115 private JanusGraphOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2116 if (MapUtils.isNotEmpty(newDescriptions)) {
2117 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getDataTypePropertiesRes = janusGraphGenericDao
2118 .getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2119 if (getDataTypePropertiesRes.isRight()) {
2120 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2121 return getDataTypePropertiesRes.right().value();
2123 getDataTypePropertiesRes.left().value().stream().filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2124 .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2126 return JanusGraphOperationStatus.OK;
2129 private JanusGraphVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<JanusGraphVertex, Edge> pair) {
2130 return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2133 private String getPropertyNameFromEdge(ImmutablePair<JanusGraphVertex, Edge> pair) {
2134 return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2137 private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2138 Map<String, PropertyDefinition> newPropertiesMap = newProperties.stream().collect(Collectors.toMap(PropertyDefinition::getName, p -> p));
2139 return oldProperties.stream()
2140 .filter(p -> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2141 .collect(Collectors.toMap(PropertyDefinition::getName, p -> newPropertiesMap.get(p.getName()).getDescription()));
2144 private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty) {
2145 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2148 if (StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2151 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())) {
2154 return property.getDescription().equals(otherProperty.getDescription());
2157 public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
2160 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
2161 JsonObject result = new JsonObject();
2162 JsonArray jsonArray = new JsonArray();
2163 if (src instanceof InRangeConstraint) {
2164 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
2165 jsonArray.add(JsonParser.parseString(String.valueOf(rangeConstraint.getInRange().get(0))));
2166 jsonArray.add(JsonParser.parseString(String.valueOf(rangeConstraint.getInRange().get(1))));
2167 result.add("inRange", jsonArray);
2168 } else if (src instanceof GreaterThanConstraint) {
2169 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
2170 jsonArray.add(JsonParser.parseString(String.valueOf(greaterThanConstraint.getGreaterThan())));
2171 result.add("greaterThan", jsonArray);
2172 } else if (src instanceof LessThanConstraint) {
2173 LessThanConstraint lessThanConstraint = (LessThanConstraint) src;
2174 jsonArray.add(JsonParser.parseString(String.valueOf(lessThanConstraint.getLessThan())));
2175 result.add("lessThan", jsonArray);
2176 } else if (src instanceof LessOrEqualConstraint) {
2177 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
2178 jsonArray.add(JsonParser.parseString(String.valueOf(lessOrEqualConstraint.getLessOrEqual())));
2179 result.add("lessOrEqual", jsonArray);
2181 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
2187 public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
2190 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
2191 PropertyConstraint propertyConstraint = null;
2192 final Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
2193 if (!set.isEmpty()) {
2194 final Entry<String, JsonElement> element = set.iterator().next();
2195 final String key = element.getKey();
2196 final ConstraintType constraintType = ConstraintType.findByType(key).orElse(null);
2197 if (constraintType == null) {
2198 log.warn("ConstraintType was not found for constraint name:{}", key);
2200 final JsonElement value = element.getValue();
2201 final Object typedValue = getTypedValue(value);
2202 switch (constraintType) {
2204 if (typedValue != null) {
2205 log.debug("Before adding value to EqualConstraint object. value = {}", typedValue);
2206 propertyConstraint = new EqualConstraint(typedValue);
2208 log.warn("The value of EqualConstraint is null");
2212 if (typedValue instanceof ArrayList) {
2213 List<Object> rangeArray = (ArrayList<Object>) typedValue;
2214 if (rangeArray.size() != 2 || rangeArray.contains("")) {
2215 log.error("The range constraint content is invalid. value = {}", typedValue);
2216 throw new JsonSyntaxException("The range constraint content is invalid");
2218 final Object minValue = rangeArray.get(0);
2219 final Object maxValue = rangeArray.get(1);
2221 final Comparable min = ConstraintUtil.convertToComparable(
2222 ToscaType.getToscaType(minValue.getClass().getSimpleName().toLowerCase()), String.valueOf(minValue));
2223 final Comparable max = ConstraintUtil.convertToComparable(
2224 ToscaType.getToscaType(maxValue.getClass().getSimpleName().toLowerCase()), String.valueOf(maxValue));
2226 propertyConstraint = new InRangeConstraint(Arrays.asList(min, max));
2229 log.warn("The value of InRangeConstraint is null");
2233 if (typedValue != null) {
2234 log.debug("Before adding value to GreaterThanConstraint object. value = {}", typedValue);
2235 propertyConstraint = new GreaterThanConstraint(typedValue);
2237 log.warn("The value of GreaterThanConstraint is null");
2241 if (typedValue != null) {
2242 log.debug("Before adding value to LessThanConstraint object. value = {}", typedValue);
2243 propertyConstraint = new LessThanConstraint(typedValue);
2245 log.warn("The value of LessThanConstraint is null");
2248 case GREATER_OR_EQUAL:
2249 if (typedValue != null) {
2250 log.debug("Before adding value to GreaterThanConstraint object. value = {}", typedValue);
2251 propertyConstraint = new GreaterOrEqualConstraint(typedValue);
2253 log.warn("The value of GreaterOrEqualConstraint is null");
2257 if (typedValue != null) {
2258 log.debug("Before adding value to LessOrEqualConstraint object. value = {}", typedValue);
2259 propertyConstraint = new LessOrEqualConstraint(typedValue);
2261 log.warn("The value of LessOrEqualConstraint is null");
2265 if (typedValue instanceof ArrayList) {
2266 List<Object> validValuesArray = (ArrayList<Object>) typedValue;
2267 if (validValuesArray.size() == 0 || validValuesArray.contains("")) {
2268 log.error("The valid values constraint content is invalid. value = {}", typedValue);
2269 throw new JsonSyntaxException("The valid values constraint content is invalid");
2271 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2272 vvConstraint.setValidValues(validValuesArray);
2273 propertyConstraint = vvConstraint;
2276 log.warn("The value of ValidValuesConstraint is null");
2280 if (value != null) {
2281 int asInt = value.getAsInt();
2282 log.debug("Before adding value to length constraint. value = {}", asInt);
2283 propertyConstraint = new LengthConstraint(asInt);
2285 log.warn("The value of LengthConstraint is null");
2289 if (value != null) {
2290 int asInt = value.getAsInt();
2291 log.debug("Before adding value to Min Length object. value = {}", asInt);
2292 propertyConstraint = new MinLengthConstraint(asInt);
2294 log.warn("The value of MinLengthConstraint is null");
2298 if (value != null) {
2299 int asInt = value.getAsInt();
2300 log.debug("Before adding value to max length constraint. value = {}", asInt);
2301 propertyConstraint = new MaxLengthConstraint(asInt);
2303 log.warn("The value of MaxLengthConstraint is null");
2307 if (value != null) {
2308 String asString = value.getAsString();
2309 log.debug("Before adding value to PatternConstraint object. value = {}", asString);
2310 propertyConstraint = new PatternConstraint(asString);
2312 log.warn("The value of PatternConstraint is null");
2316 log.warn("Key {} is not supported. Ignored.", key);
2320 return propertyConstraint;
2323 private Object getTypedValue(JsonElement je) {
2324 if (je == null || je.isJsonNull()) {
2327 if (je.isJsonPrimitive()) {
2328 return getJsonPrimitive(je.getAsJsonPrimitive());
2330 if (je.isJsonArray()) {
2331 ArrayList<Object> array = new ArrayList<>();
2332 for (JsonElement e : je.getAsJsonArray()) {
2333 array.add(getJsonPrimitive(e.getAsJsonPrimitive()));
2340 private Object getJsonPrimitive(JsonPrimitive je) {
2341 if (je.isBoolean()) {
2342 return je.getAsBoolean();
2344 if (je.isNumber()) {
2345 float number = je.getAsNumber().floatValue();
2346 if ((number % 1) == 0) {
2347 return je.getAsNumber().intValue();
2351 if (je.isString()) {
2352 return je.getAsString();
2358 public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
2361 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
2362 ObjectCodec oc = json.getCodec();
2363 JsonNode node = oc.readTree(json);
2364 PropertyConstraint propertyConstraint = null;
2366 Iterator<Entry<String, JsonNode>> fieldsIterator = node.fields();
2367 while (fieldsIterator.hasNext()) {
2368 Entry<String, JsonNode> field = fieldsIterator.next();
2369 ConstraintType constraintType = ConstraintType.findByType(field.getKey()).orElse(null);
2370 JsonNode value = field.getValue();
2372 if (constraintType == null) {
2373 log.warn("ConstraintType was not found for constraint name:{}", field.getKey());
2375 if (value == null) {
2376 log.warn("The value of {} constraint is null", constraintType);
2378 switch (constraintType) {
2380 propertyConstraint = deserializeConstraint(value, EqualConstraint.class);
2383 propertyConstraint = deserializeInRangeConstraint(value);
2386 propertyConstraint = deserializeConstraint(value, GreaterThanConstraint.class);
2389 propertyConstraint = deserializeConstraint(value, LessThanConstraint.class);
2391 case GREATER_OR_EQUAL:
2392 propertyConstraint = deserializeConstraint(value, GreaterOrEqualConstraint.class);
2395 propertyConstraint = deserializeConstraint(value, LessOrEqualConstraint.class);
2398 propertyConstraint = deserializeValidValuesConstraint(value);
2401 propertyConstraint = deserializeConstraintWithIntegerOperand(value, LengthConstraint.class);
2404 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MinLengthConstraint.class);
2407 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MaxLengthConstraint.class);
2410 propertyConstraint = deserializeConstraintWithStringPatternOperand(value, PatternConstraint.class);
2413 log.warn("Key {} is not supported. Ignored.", field.getKey());
2419 return propertyConstraint;
2422 private PropertyConstraint deserializeConstraint(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2423 return deserializeConstraintWithObjectOperand(convertToType(value), constraintClass);
2426 private PropertyConstraint deserializeConstraintWithObjectOperand(Object value, Class<? extends PropertyConstraint> constraintClass) {
2427 log.debug("Before adding value to {} object. value = {}", constraintClass, value);
2429 return constraintClass.getConstructor(Object.class).newInstance(value);
2430 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2431 | SecurityException exception) {
2432 log.error("Error deserializing constraint", exception);
2437 private PropertyConstraint deserializeConstraintWithStringPatternOperand(JsonNode value,
2438 Class<? extends PropertyConstraint> constraintClass) {
2439 String asString = value.asText();
2440 log.debug("Before adding value to {} object. value = {}", constraintClass, asString);
2442 return constraintClass.getConstructor(String.class).newInstance(asString);
2443 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2444 | SecurityException exception) {
2445 log.error("Error deserializing constraint", exception);
2450 private PropertyConstraint deserializeConstraintWithIntegerOperand(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2451 Integer asInt = value.asInt();
2452 log.debug("Before adding value to {} object. value = {}", constraintClass, asInt);
2454 return constraintClass.getConstructor(Integer.class).newInstance(asInt);
2455 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2456 | SecurityException exception) {
2457 log.error("Error deserializing constraint", exception);
2462 private PropertyConstraint deserializeInRangeConstraint(JsonNode value) {
2463 if (value instanceof ArrayNode) {
2464 ArrayNode rangeArray = (ArrayNode) value;
2465 if (rangeArray.size() != 2) {
2466 log.error("The range constraint content is invalid. value = {}", value);
2468 final Object minValue = convertToType(rangeArray.get(0));
2469 final Object maxValue = convertToType(rangeArray.get(1));
2470 final Comparable min = ConstraintUtil.convertToComparable(
2471 ToscaType.getToscaType(minValue.getClass().getSimpleName().toLowerCase()), String.valueOf(minValue));
2472 final Comparable max = ConstraintUtil.convertToComparable(
2473 ToscaType.getToscaType(maxValue.getClass().getSimpleName().toLowerCase()), String.valueOf(maxValue));
2475 return new InRangeConstraint(Arrays.asList(min, max));
2481 private PropertyConstraint deserializeValidValuesConstraint(JsonNode value) {
2482 ArrayNode rangeArray = (ArrayNode) value;
2483 if (rangeArray.size() == 0) {
2484 log.error("The valid values constraint content is invalid. value = {}", value);
2486 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2487 List<Object> validValues = new ArrayList<>();
2488 for (JsonNode jsonElement : rangeArray) {
2489 validValues.add(convertToType(jsonElement));
2491 vvConstraint.setValidValues(validValues);
2492 return vvConstraint;
2497 private Object convertToType(JsonNode jsonElement) {
2498 if (jsonElement.getNodeType().equals(JsonNodeType.NUMBER)) {
2499 float asFloat = (float) jsonElement.asDouble();
2500 if ((asFloat % 1) == 0) {
2501 return jsonElement.asInt();
2505 } else if (jsonElement.getNodeType().equals(JsonNodeType.BOOLEAN)) {
2506 return jsonElement.asBoolean();
2507 } else if (jsonElement.getNodeType().equals(JsonNodeType.ARRAY)) {
2508 List<Object> listValues = new ArrayList<>();
2509 for (JsonNode jsonArrayElement : jsonElement) {
2510 listValues.add(convertToType(jsonArrayElement));
2514 return jsonElement.asText();