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=========================================================
20 package org.openecomp.sdc.be.model.operations.impl;
22 import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR;
24 import com.fasterxml.jackson.core.ObjectCodec;
25 import com.fasterxml.jackson.databind.DeserializationContext;
26 import com.fasterxml.jackson.databind.JsonNode;
27 import com.google.common.collect.Maps;
28 import com.google.gson.JsonArray;
29 import com.google.gson.JsonDeserializationContext;
30 import com.google.gson.JsonDeserializer;
31 import com.google.gson.JsonElement;
32 import com.google.gson.JsonObject;
33 import com.google.gson.JsonParseException;
34 import com.google.gson.JsonParser;
35 import com.google.gson.JsonSerializationContext;
36 import com.google.gson.JsonSerializer;
37 import fj.data.Either;
38 import java.io.IOException;
39 import java.lang.reflect.Type;
40 import java.util.ArrayList;
41 import java.util.Collection;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.List;
46 import java.util.Map.Entry;
48 import java.util.StringJoiner;
49 import java.util.function.Consumer;
50 import java.util.regex.Matcher;
51 import java.util.regex.Pattern;
52 import java.util.stream.Collectors;
53 import org.apache.commons.collections.CollectionUtils;
54 import org.apache.commons.collections.MapUtils;
55 import org.apache.commons.lang3.StringUtils;
56 import org.apache.commons.lang3.tuple.ImmutablePair;
57 import org.apache.tinkerpop.gremlin.structure.Edge;
58 import org.apache.tinkerpop.gremlin.structure.Vertex;
59 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
60 import org.janusgraph.core.JanusGraph;
61 import org.janusgraph.core.JanusGraphVertex;
62 import org.janusgraph.core.JanusGraphVertexProperty;
63 import org.openecomp.sdc.be.config.BeEcompErrorManager;
64 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
65 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
66 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
67 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
68 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
69 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
70 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
71 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
72 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
73 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
74 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
75 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
76 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
77 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
78 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
79 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
80 import org.openecomp.sdc.be.model.DataTypeDefinition;
81 import org.openecomp.sdc.be.model.IComplexDefaultValue;
82 import org.openecomp.sdc.be.model.PropertyConstraint;
83 import org.openecomp.sdc.be.model.PropertyDefinition;
84 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
85 import org.openecomp.sdc.be.model.operations.api.IPropertyOperation;
86 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
87 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
88 import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType;
89 import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint;
90 import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
91 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
92 import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
93 import org.openecomp.sdc.be.model.tosca.constraints.LessThanConstraint;
94 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
95 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
96 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
97 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
98 import org.openecomp.sdc.be.resources.data.DataTypeData;
99 import org.openecomp.sdc.be.resources.data.ModelData;
100 import org.openecomp.sdc.be.resources.data.PropertyData;
101 import org.openecomp.sdc.be.resources.data.PropertyValueData;
102 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
103 import org.openecomp.sdc.be.resources.data.UniqueIdData;
104 import org.openecomp.sdc.common.log.wrappers.Logger;
105 import org.springframework.beans.factory.annotation.Autowired;
106 import org.springframework.stereotype.Component;
108 @Component("property-operation")
109 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
111 private static final String AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS = "After retrieving DERIVED_FROM node of {}. status is {}";
112 private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
113 private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
114 private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
115 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
116 private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS = "Failed to associate resource {} to property {} in graph. status is {}";
117 private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
118 private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
119 private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
120 private static final String PROPERTY = "Property";
121 private static final String UPDATE_DATA_TYPE = "UpdateDataType";
122 private static final Logger log = Logger.getLogger(PropertyOperation.class.getName());
123 private final DerivedFromOperation derivedFromOperation;
124 private DataTypeOperation dataTypeOperation;
127 public PropertyOperation(final HealingJanusGraphGenericDao janusGraphGenericDao, final DerivedFromOperation derivedFromOperation) {
128 this.janusGraphGenericDao = janusGraphGenericDao;
129 this.derivedFromOperation = derivedFromOperation;
132 //circular dependency DataTypeOperation->ModelOperation->ModelElementOperation->PropertyOperation
134 public void setDataTypeOperation(DataTypeOperation dataTypeOperation) {
135 this.dataTypeOperation = dataTypeOperation;
138 public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
139 log.debug("The object returned after create property is {}", propertyDataResult);
140 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
141 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
142 propertyDefResult.setName(propertyName);
143 return propertyDefResult;
146 public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
147 Either<PropertyData, JanusGraphOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
148 if (either.isRight()) {
149 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
150 return Either.right(storageStatus);
152 return Either.left(either.left().value());
156 * @param propertyDefinition
160 public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
161 log.trace("Going to validate property type and value. {}", propertyDefinition);
162 String propertyType = propertyDefinition.getType();
163 String value = propertyDefinition.getDefaultValue();
164 ToscaPropertyType type = getType(propertyType);
166 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
167 if (dataTypeDefinition == null) {
168 log.debug("The type {} of property cannot be found.", propertyType);
169 return StorageOperationStatus.INVALID_TYPE;
171 return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
173 String innerType = null;
174 Either<String, JanusGraphOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
175 if (checkInnerType.isRight()) {
176 return StorageOperationStatus.INVALID_TYPE;
178 innerType = checkInnerType.left().value();
179 log.trace("After validating property type {}", propertyType);
180 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
181 if (!isValidProperty) {
182 log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
183 return StorageOperationStatus.INVALID_VALUE;
185 PropertyValueConverter converter = type.getConverter();
186 if (isEmptyValue(value)) {
187 log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
188 propertyDefinition.setDefaultValue(EMPTY_VALUE);
189 } else if (!isEmptyValue(value)) {
190 String convertedValue = converter.convert(value, innerType, dataTypes);
191 propertyDefinition.setDefaultValue(convertedValue);
193 return StorageOperationStatus.OK;
196 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition,
198 ResourceMetadataData resourceData = new ResourceMetadataData();
199 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
200 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
201 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
202 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
203 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
204 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
205 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
206 if (createNodeResult.isRight()) {
207 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
208 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
209 return Either.right(operationStatus);
211 Map<String, Object> props = new HashMap<>();
212 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
213 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
214 .createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
215 if (createRelResult.isRight()) {
216 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
217 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
218 return Either.right(operationStatus);
220 return Either.left(createNodeResult.left().value());
223 public JanusGraphOperationStatus addPropertyToGraphByVertex(JanusGraphVertex metadataVertex, String propertyName,
224 PropertyDefinition propertyDefinition, String resourceId) {
225 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
226 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
227 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
228 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
229 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData);
230 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
231 if (createNodeResult.isRight()) {
232 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
233 log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
234 return operationStatus;
236 Map<String, Object> props = new HashMap<>();
237 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
238 JanusGraphVertex propertyVertex = createNodeResult.left().value();
239 JanusGraphOperationStatus createRelResult = janusGraphGenericDao.createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
240 if (!createRelResult.equals(JanusGraphOperationStatus.OK)) {
241 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
242 return createRelResult;
244 return createRelResult;
247 public JanusGraphGenericDao getJanusGraphGenericDao() {
248 return janusGraphGenericDao;
254 * @param janusGraphGenericDao
256 public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
257 this.janusGraphGenericDao = janusGraphGenericDao;
260 public Either<PropertyData, JanusGraphOperationStatus> deletePropertyFromGraph(String propertyId) {
261 log.debug("Before deleting property from graph {}", propertyId);
262 return janusGraphGenericDao.deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
265 public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition,
266 Map<String, DataTypeDefinition> dataTypes) {
267 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
268 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
269 return Either.right(validateAndUpdateProperty);
271 Either<PropertyData, JanusGraphOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
272 if (either.isRight()) {
273 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
274 return Either.right(storageStatus);
276 return Either.left(either.left().value());
279 public Either<PropertyData, JanusGraphOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
280 if (log.isDebugEnabled()) {
281 log.debug("Before updating property on graph {}", propertyId);
283 // get the original property data
284 Either<PropertyData, JanusGraphOperationStatus> statusProperty = janusGraphGenericDao
285 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
286 if (statusProperty.isRight()) {
287 log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
288 return Either.right(statusProperty.right().value());
290 PropertyData orgPropertyData = statusProperty.left().value();
291 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
292 // create new property data to update
293 PropertyData newPropertyData = new PropertyData();
294 newPropertyData.setPropertyDataDefinition(propertyDefinition);
295 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
296 // update the original property data with new values
297 if (orgPropertyDataDefinition.getDefaultValue() == null) {
298 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
300 if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
301 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
304 if (orgPropertyDataDefinition.getDescription() == null) {
305 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
307 if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
308 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
311 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
312 orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
314 if (newPropertyData.getConstraints() != null) {
315 orgPropertyData.setConstraints(newPropertyData.getConstraints());
317 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
318 return janusGraphGenericDao.updateNode(orgPropertyData, PropertyData.class);
321 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition,
322 NodeTypeEnum nodeType, String uniqueId) {
323 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
324 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
325 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
326 if (log.isDebugEnabled()) {
327 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
329 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
330 if (log.isDebugEnabled()) {
331 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
333 if (createNodeResult.isRight()) {
334 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
335 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
336 return Either.right(operationStatus);
338 Map<String, Object> props = new HashMap<>();
339 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
340 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
341 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
342 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
343 .createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
344 if (createRelResult.isRight()) {
345 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
346 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
347 return Either.right(operationStatus);
349 return Either.left(createNodeResult.left().value());
352 public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
353 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
354 Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
355 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
357 if (childrenNodes.isRight()) {
358 JanusGraphOperationStatus operationStatus = childrenNodes.right().value();
359 return Either.right(operationStatus);
361 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
362 if (values != null) {
363 for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
364 GraphEdge edge = immutablePair.getValue();
365 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
366 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
367 PropertyData propertyData = immutablePair.getKey();
368 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
369 resourceProps.put(propertyName, propertyDefinition);
372 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
373 return Either.left(resourceProps);
376 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
377 return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId).right()
378 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
381 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
382 Map<String, PropertyDefinition> newProperties) {
383 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
384 Map<String, PropertyDefinition> reallyNewProperties;
385 Map<String, PropertyData> unchangedPropsData;
386 if (oldPropertiesRes.isRight()) {
387 JanusGraphOperationStatus err = oldPropertiesRes.right().value();
388 if (err == JanusGraphOperationStatus.NOT_FOUND) {
389 reallyNewProperties = newProperties;
390 unchangedPropsData = Collections.emptyMap();
392 return Either.right(err);
395 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
396 reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
397 for (Entry<String, PropertyDefinition> oldEntry : oldProperties.entrySet()) {
398 String key = oldEntry.getKey();
399 PropertyDefinition newPropDef = newProperties != null ? newProperties.get(key) : null;
400 PropertyDefinition oldPropDef = oldEntry.getValue();
401 JanusGraphOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
402 if (status != JanusGraphOperationStatus.OK) {
403 return Either.right(status);
406 unchangedPropsData = oldProperties.entrySet().stream()
407 .collect(Collectors.toMap(Entry::getKey, e -> new PropertyData(e.getValue(), null)));
409 // add other properties
410 return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
414 * @param newProperties
415 * @param oldProperties
418 private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties,
419 Map<String, PropertyDefinition> oldProperties) {
420 return newProperties != null ? newProperties.entrySet().stream().filter(entry -> !oldProperties.containsKey(entry.getKey()))
421 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)) : null;
428 private JanusGraphOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
429 if (!isUpdateAllowed(newPropDef, oldPropDef)) {
430 return JanusGraphOperationStatus.MATCH_NOT_FOUND;
432 if (isUpdateRequired(newPropDef, oldPropDef)) {
433 modifyOldPropByNewOne(newPropDef, oldPropDef);
434 List<PropertyConstraint> constraints = oldPropDef.getConstraints();
435 PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
436 Either<PropertyData, JanusGraphOperationStatus> updateResult = janusGraphGenericDao.updateNode(node, PropertyData.class);
437 if (updateResult.isRight()) {
438 return updateResult.right().value();
441 return JanusGraphOperationStatus.OK;
448 private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
449 if (newPropDef == null) {
450 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
453 // If the property type is missing it's something that we could want to fix
454 if (oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
455 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
462 * Update only fields which modification is permitted.
467 private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
468 oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
469 oldPropDef.setDescription(newPropDef.getDescription());
470 oldPropDef.setRequired(newPropDef.isRequired());
471 // Type is updated to fix possible null type issue in janusGraph DB
472 oldPropDef.setType(newPropDef.getType());
475 private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
476 return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) || !StringUtils
477 .equals(oldPropDef.getDescription(), newPropDef.getDescription()) || oldPropDef.isRequired() != newPropDef.isRequired();
481 * Adds newProperties and returns in case of success (left part of Either) map of all properties i. e. added ones and contained in
486 * @param newProperties
487 * @param unchangedPropsData
490 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId,
491 Map<String, PropertyDefinition> newProperties,
492 Map<String, PropertyData> unchangedPropsData) {
493 return addPropertiesToElementType(uniqueId, nodeType, newProperties).left().map(m -> {
494 m.putAll(unchangedPropsData);
499 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType,
501 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
502 if (propertiesOfNodeRes.isRight()) {
503 JanusGraphOperationStatus status = propertiesOfNodeRes.right().value();
504 if (status == JanusGraphOperationStatus.NOT_FOUND) {
505 return Either.right(StorageOperationStatus.OK);
507 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
509 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
510 for (PropertyDefinition propertyDefinition : value.values()) {
511 String propertyUid = propertyDefinition.getUniqueId();
512 Either<PropertyData, JanusGraphOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
513 if (deletePropertyRes.isRight()) {
514 log.error("Failed to delete property with id {}", propertyUid);
515 JanusGraphOperationStatus status = deletePropertyRes.right().value();
516 if (status == JanusGraphOperationStatus.NOT_FOUND) {
517 status = JanusGraphOperationStatus.INVALID_ID;
519 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
522 log.debug("The properties deleted from node {} are {}", uniqueId, value);
523 return Either.left(value);
527 * 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
528 * (including derived from hierarchy)
532 * @param propertyName
533 * @param propertyType
536 public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
537 boolean result = false;
538 if (!CollectionUtils.isEmpty(properties)) {
539 for (PropertyDefinition propertyDefinition : properties) {
540 if (propertyDefinition.getName().equals(propertyName) && (propertyDefinition.getParentUniqueId().equals(resourceUid)
541 || !propertyDefinition.getType().equals(propertyType))) {
550 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType,
551 Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
552 if (rules == null || rules.isEmpty()) {
553 return new ImmutablePair<>(null, true);
555 for (PropertyRule rule : rules) {
556 String value = rule.getValue();
557 Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
558 if (updateResult.isRight()) {
559 Boolean status = updateResult.right().value();
561 return new ImmutablePair<>(value, status);
564 String newValue = null;
565 Object object = updateResult.left().value();
566 if (object != null) {
567 newValue = object.toString();
569 rule.setValue(newValue);
572 return new ImmutablePair<>(null, true);
575 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
576 String resourceInstanceId) {
577 List<PropertyRule> rules = resourceInstanceProperty.getRules();
579 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
580 rules = new ArrayList<>();
581 rules.add(propertyRule);
583 rules = sortRules(rules);
585 propertyValueData.setRules(rules);
588 private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
589 String resourceInstanceId) {
590 List<String> path = resourceInstanceProperty.getPath();
591 // FOR BC. Since old Property values on VFC/VF does not have rules on
595 // Update could be done on one level only, thus we can use this
597 // operation to avoid migration.
598 if (path == null || path.isEmpty()) {
599 path = new ArrayList<>();
600 path.add(resourceInstanceId);
602 PropertyRule propertyRule = new PropertyRule();
603 propertyRule.setRule(path);
604 propertyRule.setValue(propertyValueData.getValue());
608 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
609 // TODO: sort the rules by size and binary representation.
611 // (x, y, .+) --> 110 6 priority 1
613 // (x, .+, z) --> 101 5 priority 2
617 public ImmutablePair<JanusGraphOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
618 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
619 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllRes = this
620 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
621 if (getAllRes.isRight()) {
622 JanusGraphOperationStatus status = getAllRes.right().value();
623 log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
624 return new ImmutablePair<>(status, null);
626 List<ComponentInstanceProperty> list = getAllRes.left().value();
628 for (ComponentInstanceProperty instanceProperty : list) {
629 String propertyUniqueId = instanceProperty.getUniqueId();
630 String valueUniqueUid = instanceProperty.getValueUniqueUid();
631 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
632 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
633 log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
634 return new ImmutablePair<>(JanusGraphOperationStatus.ALREADY_EXIST, valueUniqueUid);
638 return new ImmutablePair<>(JanusGraphOperationStatus.NOT_FOUND, null);
641 public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
642 String resourceInstanceId) {
643 List<PropertyRule> currentRules = propertyValueData.getRules();
644 List<PropertyRule> rules = resourceInstanceProperty.getRules();
645 // if rules are not supported.
647 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
648 rules = new ArrayList<>();
649 rules.add(propertyRule);
650 if (currentRules != null) {
651 rules = mergeRules(currentRules, rules);
654 // Full mode. all rules are sent in update operation.
655 rules = sortRules(rules);
657 propertyValueData.setRules(rules);
660 private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
661 List<PropertyRule> mergedRules = new ArrayList<>();
662 if (newRules == null || newRules.isEmpty()) {
665 for (PropertyRule rule : currentRules) {
666 PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
667 mergedRules.add(propertyRule);
669 for (PropertyRule rule : newRules) {
670 PropertyRule foundRule = findRuleInList(rule, mergedRules);
671 if (foundRule != null) {
672 foundRule.setValue(rule.getValue());
674 mergedRules.add(rule);
680 private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
681 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
684 PropertyRule foundRule = null;
685 for (PropertyRule propertyRule : rules) {
686 if (rule.getRuleSize() != propertyRule.getRuleSize()) {
689 boolean equals = propertyRule.compareRule(rule);
691 foundRule = propertyRule;
699 * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
701 * @param resourceInstanceUid
704 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
705 String resourceInstanceUid) {
706 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
709 public Either<PropertyValueData, JanusGraphOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
710 Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
711 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
712 if (findResInstanceRes.isRight()) {
713 JanusGraphOperationStatus status = findResInstanceRes.right().value();
714 if (status == JanusGraphOperationStatus.NOT_FOUND) {
715 status = JanusGraphOperationStatus.INVALID_ID;
717 return Either.right(status);
719 Either<PropertyValueData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
720 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
721 if (findPropertyDefRes.isRight()) {
722 JanusGraphOperationStatus status = findPropertyDefRes.right().value();
723 if (status == JanusGraphOperationStatus.NOT_FOUND) {
724 status = JanusGraphOperationStatus.INVALID_ID;
726 return Either.right(status);
728 Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
729 .getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
730 if (relation.isRight()) {
731 // TODO: add error in case of error
732 JanusGraphOperationStatus status = relation.right().value();
733 if (status == JanusGraphOperationStatus.NOT_FOUND) {
734 status = JanusGraphOperationStatus.INVALID_ID;
736 return Either.right(status);
738 Either<PropertyValueData, JanusGraphOperationStatus> deleteNode = janusGraphGenericDao
739 .deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
740 if (deleteNode.isRight()) {
741 return Either.right(deleteNode.right().value());
743 PropertyValueData value = deleteNode.left().value();
744 return Either.left(value);
747 public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid,
748 String resourceInstanceId,
749 boolean inTransaction) {
750 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
752 Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = this
753 .removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
754 if (eitherStatus.isRight()) {
755 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId,
756 eitherStatus.right().value().name());
757 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
760 PropertyValueData propertyValueData = eitherStatus.left().value();
761 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
762 propertyValueResult.setUniqueId(resourceInstanceId);
763 propertyValueResult.setValue(propertyValueData.getValue());
764 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
765 result = Either.left(propertyValueResult);
769 if (!inTransaction) {
770 if (result == null || result.isRight()) {
771 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
772 janusGraphGenericDao.rollback();
774 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
775 janusGraphGenericDao.commit();
781 public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData,
782 ComponentInstanceProperty resourceInstanceProperty) {
783 String value = propertyValueData.getValue();
784 String uid = propertyValueData.getUniqueId();
785 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
786 instanceProperty.setPath(resourceInstanceProperty.getPath());
787 return instanceProperty;
791 public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
792 if (propertyDefinition == null) {
795 String innerType = null;
796 String propertyType = propertyDefinition.getType();
797 ToscaPropertyType type = getType(propertyType);
798 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
799 SchemaDefinition def = propertyDefinition.getSchema();
803 PropertyDataDefinition propDef = def.getProperty();
804 if (propDef == null) {
807 innerType = propDef.getType();
809 String value = propertyDefinition.getDefaultValue();
811 return isValidValue(type, value, innerType, dataTypes);
813 log.trace("The given type {} is not a pre defined one.", propertyType);
814 DataTypeDefinition foundDt = dataTypes.get(propertyType);
815 if (foundDt != null) {
816 return isValidComplexValue(foundDt, value, dataTypes);
823 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final String model) {
824 if (property == null) {
827 if (ToscaPropertyType.isValidType(property.getType()) == null) {
828 Either<Boolean, JanusGraphOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType(), model);
829 if (definedInDataTypes.isRight()) {
832 Boolean isExist = definedInDataTypes.left().value();
833 return isExist.booleanValue();
839 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final Map<String, DataTypeDefinition> dataTypes) {
840 if (property == null) {
843 return ToscaPropertyType.isValidType(property.getType()) != null || dataTypes.containsKey(property.getType());
847 public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
848 if (property == null) {
849 return new ImmutablePair<>(null, false);
851 SchemaDefinition schema;
852 PropertyDataDefinition innerProp;
853 String innerType = null;
854 if ((schema = property.getSchema()) != null) {
855 if ((innerProp = schema.getProperty()) != null) {
856 innerType = innerProp.getType();
859 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
860 if (innerToscaType == null) {
861 DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
862 if (dataTypeDefinition == null) {
863 log.debug("The inner type {} is not a data type.", innerType);
864 return new ImmutablePair<>(innerType, false);
866 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
869 return new ImmutablePair<>(innerType, true);
872 private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
873 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
874 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
875 return validateAndUpdate.right.booleanValue();
878 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
879 String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
880 Either<JanusGraphVertex, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
881 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
882 if (findResInstanceRes.isRight()) {
883 JanusGraphOperationStatus status = findResInstanceRes.right().value();
884 if (status == JanusGraphOperationStatus.NOT_FOUND) {
885 status = JanusGraphOperationStatus.INVALID_ID;
887 return Either.right(status);
889 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> propertyImplNodes = janusGraphGenericDao
890 .getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
891 if (propertyImplNodes.isRight()) {
892 JanusGraphOperationStatus status = propertyImplNodes.right().value();
893 return Either.right(status);
895 List<ImmutablePair<JanusGraphVertex, Edge>> list = propertyImplNodes.left().value();
896 if (list == null || list.isEmpty()) {
897 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
899 List<ComponentInstanceProperty> result = new ArrayList<>();
900 for (ImmutablePair<JanusGraphVertex, Edge> propertyValue : list) {
901 JanusGraphVertex propertyValueDataVertex = propertyValue.getLeft();
902 String propertyValueUid = (String) janusGraphGenericDao
903 .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
904 String value = (String) janusGraphGenericDao.getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
905 ImmutablePair<JanusGraphVertex, Edge> propertyDefPair = janusGraphGenericDao
906 .getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
907 if (propertyDefPair == null) {
908 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
910 Map<String, Object> properties = janusGraphGenericDao.getProperties(propertyValueDataVertex);
911 PropertyValueData propertyValueData = GraphElementFactory
912 .createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
913 String propertyUniqueId = (String) janusGraphGenericDao
914 .getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
915 ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
916 // set property original unique id
917 resourceInstanceProperty.setUniqueId(propertyUniqueId);
920 // TODO: esofer add resource id
921 resourceInstanceProperty.setParentUniqueId(null);
923 resourceInstanceProperty.setValue(value);
924 // set property value unique id
925 resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
927 resourceInstanceProperty.setRules(propertyValueData.getRules());
928 result.add(resourceInstanceProperty);
930 return Either.left(result);
934 * Find the default value from the list of component instances. Start the search from the second component instance
936 * @param pathOfComponentInstances
937 * @param propertyUniqueId
938 * @param defaultValue
941 public Either<String, JanusGraphOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances,
942 String propertyUniqueId, String defaultValue) {
943 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
944 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
945 return Either.left(defaultValue);
947 String result = defaultValue;
948 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
949 String compInstanceId = pathOfComponentInstances.get(i);
950 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> propertyValuesResult = this
951 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
952 log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
953 if (propertyValuesResult.isRight()) {
954 JanusGraphOperationStatus status = propertyValuesResult.right().value();
955 if (status != JanusGraphOperationStatus.NOT_FOUND) {
956 return Either.right(status);
961 ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
962 log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
963 if (foundCompInstanceProperty == null) {
966 List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i),
967 foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
968 log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
969 PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
970 log.trace("Match rule is {}", matchedRule);
971 if (matchedRule != null) {
972 result = matchedRule.getValue();
976 return Either.left(result);
979 private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
980 ComponentInstanceProperty result = null;
984 for (ComponentInstanceProperty instProperty : list) {
985 if (instProperty.getUniqueId().equals(propertyUniqueId)) {
986 result = instProperty;
993 private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
997 rules = buildDefaultRule(compInstanceId, ruleSize, value);
1001 private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
1002 List<PropertyRule> rules = componentInstanceProperty.getRules();
1003 if (rules == null) {
1004 rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
1009 private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
1010 List<PropertyRule> rules = new ArrayList<>();
1011 List<String> rule = new ArrayList<>();
1012 rule.add(componentInstanceId);
1013 for (int i = 0; i < size - 1; i++) {
1014 rule.add(PropertyRule.getRuleAnyMatch());
1016 PropertyRule propertyRule = new PropertyRule(rule, value);
1017 rules.add(propertyRule);
1021 private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1022 PropertyRule propertyRule = null;
1023 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1024 String firstCompInstance = pathOfInstances.get(level);
1025 if (rules != null) {
1026 for (PropertyRule rule : rules) {
1027 int ruleSize = rule.getRule().size();
1028 // check the length of the rule equals to the length of the
1031 if (ruleSize != pathOfInstances.size() - level) {
1034 // check that the rule starts with correct component instance id
1035 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1038 String secondToken = rule.getToken(2);
1039 if (secondToken != null && (secondToken.equals(PropertyRule.getForceAll()) || secondToken.equals(PropertyRule.getALL()))) {
1040 propertyRule = rule;
1043 String patternStr = buildStringForMatch(rule.getRule(), 0);
1044 Pattern pattern = Pattern.compile(patternStr);
1045 Matcher matcher = pattern.matcher(stringForMatch);
1046 if (matcher.matches()) {
1047 if (log.isTraceEnabled()) {
1048 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1050 propertyRule = rule;
1055 return propertyRule;
1058 private boolean checkFirstItem(String left, String right) {
1059 if (left != null && left.equals(right)) {
1065 private String buildStringForMatch(List<String> pathOfInstances, int level) {
1066 StringBuilder builder = new StringBuilder();
1067 for (int i = level; i < pathOfInstances.size(); i++) {
1068 builder.append(pathOfInstances.get(i));
1069 if (i < pathOfInstances.size() - 1) {
1070 builder.append("#");
1073 return builder.toString();
1076 public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty,
1077 Map<String, ComponentInstanceProperty> instanceIdToValue) {
1078 List<String> pathOfInstances = instanceProperty.getPath();
1080 int size = pathOfInstances.size();
1081 int numberOfMatches = 0;
1082 for (String instanceId : pathOfInstances) {
1083 ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1084 if (componentInstanceProperty != null) {
1085 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1086 // If it is the first level instance, then update valueUniuqeId
1088 // parameter in order to know on update that
1090 // we should update and not create new node on graph.
1092 instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1093 instanceProperty.setRules(rules);
1095 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1098 String value = rule.getValue();
1099 if (numberOfMatches == 1) {
1100 instanceProperty.setValue(value);
1101 if (log.isDebugEnabled()) {
1102 log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1103 pathOfInstances, value);
1105 } else if (numberOfMatches == 2) {
1106 // In case of another property value match, then use the
1108 // value to be the default value of the property.
1109 instanceProperty.setDefaultValue(value);
1110 if (log.isDebugEnabled()) {
1111 log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1112 pathOfInstances, value);
1123 * Add data type to graph.
1125 * 1. Add data type node
1127 * 2. Add edge between the former node to its parent(if exists)
1129 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1131 * @param dataTypeDefinition
1134 private Either<DataTypeData, JanusGraphOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1135 log.debug("Got data type {}", dataTypeDefinition);
1136 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getModel(), dataTypeDefinition.getName());
1137 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1138 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1139 Either<DataTypeData, JanusGraphOperationStatus> createDataTypeResult = janusGraphGenericDao.createNode(dataTypeData, DataTypeData.class);
1140 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1141 if (createDataTypeResult.isRight()) {
1142 JanusGraphOperationStatus operationStatus = createDataTypeResult.right().value();
1143 log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1144 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1145 return Either.right(operationStatus);
1147 DataTypeData resultCTD = createDataTypeResult.left().value();
1148 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1149 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(), dataTypeDefinition.getModel(),
1151 if (addPropertiesToDataType.isRight()) {
1152 log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1153 return Either.right(addPropertiesToDataType.right().value());
1156 final Either<GraphRelation, JanusGraphOperationStatus> modelRelationship = addDataTypeToModel(dataTypeDefinition);
1157 if (modelRelationship.isRight()) {
1158 return Either.right(modelRelationship.right().value());
1161 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1162 if (derivedFrom != null) {
1163 final Either<DataTypeDefinition, JanusGraphOperationStatus> derivedFromDataType = getDataTypeByNameValidForModel(derivedFrom, dataTypeDefinition.getModel());
1164 if (derivedFromDataType.isRight()) {
1165 return Either.right(derivedFromDataType.right().value());
1168 log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1169 UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1170 final String deriveFromUid = derivedFromDataType.left().value().getUniqueId();
1171 UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1172 Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
1173 .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1174 log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1175 if (createRelation.isRight()) {
1176 return Either.right(createRelation.right().value());
1179 return Either.left(createDataTypeResult.left().value());
1182 private Either<GraphRelation, JanusGraphOperationStatus> addDataTypeToModel(final DataTypeDefinition dataTypeDefinition) {
1183 final String model = dataTypeDefinition.getModel();
1184 if (model == null) {
1185 return Either.left(null);
1187 final GraphNode from = new UniqueIdData(NodeTypeEnum.Model, UniqueIdBuilder.buildModelUid(model));
1188 final GraphNode to = new UniqueIdData(NodeTypeEnum.DataType, dataTypeDefinition.getUniqueId());
1189 log.info("Connecting model {} to type {}", from, to);
1190 return janusGraphGenericDao.createRelation(from , to, GraphEdgeLabels.MODEL_ELEMENT, Collections.emptyMap());
1193 private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1194 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1195 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1196 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1197 if (creationDate == null) {
1198 creationDate = System.currentTimeMillis();
1200 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1201 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1202 return dataTypeData;
1206 * add properties to capability type.
1208 * Per property, add a property node and associate it to the capability type
1214 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType(final String uniqueId, final String modelName,
1215 final List<PropertyDefinition> properties) {
1216 Map<String, PropertyData> propertiesData = new HashMap<>();
1217 if (properties != null && !properties.isEmpty()) {
1218 for (PropertyDefinition propertyDefinition : properties) {
1219 String propertyName = propertyDefinition.getName();
1220 String propertyType = propertyDefinition.getType();
1221 Either<Boolean, JanusGraphOperationStatus> validPropertyType = isValidPropertyType(propertyType, modelName);
1222 if (validPropertyType.isRight()) {
1223 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1224 return Either.right(validPropertyType.right().value());
1226 Boolean isValid = validPropertyType.left().value();
1227 if (isValid == null || !isValid.booleanValue()) {
1228 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1229 return Either.right(JanusGraphOperationStatus.INVALID_TYPE);
1231 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1232 .addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1233 if (addPropertyToNodeType.isRight()) {
1234 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1235 log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1236 BeEcompErrorManager.getInstance()
1237 .logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus,
1238 ErrorSeverity.ERROR);
1239 return Either.right(operationStatus);
1241 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1243 DataTypeData dataTypeData = new DataTypeData();
1244 dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1245 long modificationTime = System.currentTimeMillis();
1246 dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1247 Either<DataTypeData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao.updateNode(dataTypeData, DataTypeData.class);
1248 if (updateNode.isRight()) {
1249 JanusGraphOperationStatus operationStatus = updateNode.right().value();
1250 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1251 BeEcompErrorManager.getInstance()
1252 .logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1253 return Either.right(operationStatus);
1255 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1258 return Either.left(propertiesData);
1261 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByNameValidForModel(final String name, final String modelName) {
1262 final Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1263 .getNode(GraphPropertiesDictionary.NAME.getProperty(), name, DataTypeData.class, modelName);
1264 if (dataTypesRes.isRight()) {
1265 final JanusGraphOperationStatus status = dataTypesRes.right().value();
1266 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, name, status);
1267 return Either.right(status);
1269 final DataTypeData dataType = dataTypesRes.left().value();
1270 final DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(dataType.getDataTypeDataDefinition());
1271 final JanusGraphOperationStatus propertiesStatus = fillProperties(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1272 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1273 log.error(BUSINESS_PROCESS_ERROR, FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, dataTypeDefinition.getUniqueId());
1274 return Either.right(propertiesStatus);
1276 final Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1277 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeDefinition.getUniqueId(), GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1278 DataTypeData.class);
1279 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, dataTypeDefinition.getUniqueId(), parentNode);
1280 if (parentNode.isRight()) {
1281 final JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1282 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1283 log.error(BUSINESS_PROCESS_ERROR, "Failed to find the parent data type of data type {}. status is {}", dataTypeDefinition.getUniqueId(), janusGraphOperationStatus);
1284 return Either.right(janusGraphOperationStatus);
1287 // derived from node was found
1288 final ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1289 final DataTypeData parentDataType = immutablePair.getKey();
1290 final Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentDataType.getUniqueId());
1291 if (dataTypeByUid.isRight()) {
1292 return Either.right(dataTypeByUid.right().value());
1294 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1295 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1297 return Either.left(dataTypeDefinition);
1301 * Build Data type object from graph by unique id
1306 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUid(String uniqueId) {
1307 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1308 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1309 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1310 if (dataTypesRes.isRight()) {
1311 JanusGraphOperationStatus status = dataTypesRes.right().value();
1312 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1313 return Either.right(status);
1315 DataTypeData ctData = dataTypesRes.left().value();
1316 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1317 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1318 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1319 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1320 return Either.right(propertiesStatus);
1322 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1323 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1324 DataTypeData.class);
1325 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1326 if (parentNode.isRight()) {
1327 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1328 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1329 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1330 result = Either.right(janusGraphOperationStatus);
1334 // derived from node was found
1335 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1336 DataTypeData parentCT = immutablePair.getKey();
1337 String parentUniqueId = parentCT.getUniqueId();
1338 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1339 if (dataTypeByUid.isRight()) {
1340 return Either.right(dataTypeByUid.right().value());
1342 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1343 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1345 result = Either.left(dataTypeDefinition);
1349 private JanusGraphOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1350 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this
1351 .findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1352 if (findPropertiesOfNode.isRight()) {
1353 JanusGraphOperationStatus janusGraphOperationStatus = findPropertiesOfNode.right().value();
1354 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, janusGraphOperationStatus);
1355 if (JanusGraphOperationStatus.NOT_FOUND.equals(janusGraphOperationStatus)) {
1356 return JanusGraphOperationStatus.OK;
1358 return janusGraphOperationStatus;
1361 Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1362 if (properties != null && !properties.isEmpty()) {
1363 List<PropertyDefinition> listOfProps = new ArrayList<>();
1364 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1365 String propName = entry.getKey();
1366 PropertyDefinition propertyDefinition = entry.getValue();
1367 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1368 newPropertyDefinition.setName(propName);
1369 listOfProps.add(newPropertyDefinition);
1371 dataTypeDefinition.setProperties(listOfProps);
1373 return JanusGraphOperationStatus.OK;
1377 private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1378 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1380 Either<DataTypeData, JanusGraphOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1381 if (eitherStatus.isRight()) {
1382 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1383 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1384 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1387 DataTypeData capabilityTypeData = eitherStatus.left().value();
1388 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1389 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1390 result = Either.left(dataTypeDefResult);
1394 if (!inTransaction) {
1395 if (result == null || result.isRight()) {
1396 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1397 janusGraphGenericDao.rollback();
1399 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1400 janusGraphGenericDao.commit();
1407 public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1408 return addDataType(dataTypeDefinition, true);
1412 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel, final boolean inTransaction) {
1413 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1415 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByNameValidForModel(name, validForModel);
1416 if (ctResult.isRight()) {
1417 JanusGraphOperationStatus status = ctResult.right().value();
1418 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1419 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1421 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1424 result = Either.left(ctResult.left().value());
1427 if (!inTransaction) {
1428 if (result == null || result.isRight()) {
1429 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1430 janusGraphGenericDao.rollback();
1432 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1433 janusGraphGenericDao.commit();
1440 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel) {
1441 return getDataTypeByName(name, validForModel, true);
1444 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByUidWithoutDerived(String uid, boolean inTransaction) {
1445 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1447 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1448 if (ctResult.isRight()) {
1449 JanusGraphOperationStatus status = ctResult.right().value();
1450 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1451 log.error(BUSINESS_PROCESS_ERROR, "Failed to retrieve information on data type {} status is {}", uid, status);
1453 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1456 result = Either.left(ctResult.left().value());
1459 if (!inTransaction) {
1460 if (result == null || result.isRight()) {
1461 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1462 janusGraphGenericDao.rollback();
1464 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1465 janusGraphGenericDao.commit();
1471 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1472 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1473 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1474 if (dataTypesRes.isRight()) {
1475 JanusGraphOperationStatus status = dataTypesRes.right().value();
1476 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1477 return Either.right(status);
1479 DataTypeData ctData = dataTypesRes.left().value();
1480 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1481 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1482 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1483 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1484 return Either.right(propertiesStatus);
1486 return Either.left(dataTypeDefinition);
1490 * convert between graph Node object to Java object
1492 * @param dataTypeData
1495 protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1496 log.debug("The object returned after create data type is {}", dataTypeData);
1497 return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1500 private Either<Boolean, JanusGraphOperationStatus> isValidPropertyType(String propertyType, final String modelName) {
1501 if (propertyType == null || propertyType.isEmpty()) {
1502 return Either.left(false);
1504 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1505 if (toscaPropertyType == null) {
1506 return isDefinedInDataTypes(propertyType, modelName);
1508 return Either.left(true);
1512 public Either<Boolean, JanusGraphOperationStatus> isDefinedInDataTypes(final String propertyType, final String modelName) {
1513 Either<DataTypeDefinition, JanusGraphOperationStatus> dataType = getDataTypeByNameValidForModel(propertyType, modelName);
1514 if (dataType.isRight()) {
1515 JanusGraphOperationStatus status = dataType.right().value();
1516 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1517 return Either.left(false);
1519 return Either.right(status);
1521 return Either.left(true);
1524 public Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> getAllDataTypes() {
1525 final Map<String, Map<String, DataTypeDefinition>> dataTypes = new HashMap<>();
1526 Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> result = Either.left(dataTypes);
1527 final Map<String, DataTypeDefinition> allDataTypesFound = new HashMap<>();
1529 final Map<String, List<String>> dataTypeUidstoModels = dataTypeOperation.getAllDataTypeUidsToModels();
1531 if (dataTypeUidstoModels != null) {
1532 log.trace("Number of data types to load is {}", dataTypeUidstoModels.size());
1533 for (Map.Entry<String, List<String>> entry : dataTypeUidstoModels.entrySet()) {
1534 log.trace("Going to fetch data type with uid {}", entry.getKey());
1535 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this
1536 .getAndAddDataTypeByUid(entry.getKey(), allDataTypesFound);
1537 if (dataTypeByUid.isRight()) {
1538 JanusGraphOperationStatus status = dataTypeByUid.right().value();
1539 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1540 status = JanusGraphOperationStatus.INVALID_ID;
1542 return Either.right(status);
1544 for (final String model: entry.getValue()) {
1545 if (!dataTypes.containsKey(model)) {
1546 dataTypes.put(model, new HashMap<String, DataTypeDefinition>());
1548 DataTypeDefinition dataTypeDefinition = allDataTypesFound.get(entry.getKey());
1549 dataTypes.get(model).put(dataTypeDefinition.getName(), dataTypeDefinition);
1554 if (log.isTraceEnabled()) {
1555 if (result.isRight()) {
1556 log.trace("After fetching all data types {}", result);
1558 Map<String, Map<String, DataTypeDefinition>> map = result.left().value();
1560 String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1561 log.trace("After fetching all data types {} ", types);
1569 * Build Data type object from graph by unique id
1574 private Either<DataTypeDefinition, JanusGraphOperationStatus> getAndAddDataTypeByUid(String uniqueId,
1575 Map<String, DataTypeDefinition> allDataTypes) {
1576 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1577 if (allDataTypes.containsKey(uniqueId)) {
1578 return Either.left(allDataTypes.get(uniqueId));
1580 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1581 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1582 if (dataTypesRes.isRight()) {
1583 JanusGraphOperationStatus status = dataTypesRes.right().value();
1584 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1585 return Either.right(status);
1587 DataTypeData ctData = dataTypesRes.left().value();
1588 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1589 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1590 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1591 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1592 return Either.right(propertiesStatus);
1594 allDataTypes.put(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1595 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1596 if (allDataTypes.containsKey(derivedFrom)) {
1597 DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1598 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1599 return Either.left(dataTypeDefinition);
1601 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1602 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1603 DataTypeData.class);
1604 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1605 if (parentNode.isRight()) {
1606 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1607 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1608 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1609 result = Either.right(janusGraphOperationStatus);
1613 // derived from node was found
1614 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1615 DataTypeData parentCT = immutablePair.getKey();
1616 String parentUniqueId = parentCT.getUniqueId();
1617 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1618 if (dataTypeByUid.isRight()) {
1619 return Either.right(dataTypeByUid.right().value());
1621 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1622 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1623 final var model = getModel(uniqueId);
1624 if (StringUtils.isNotEmpty(model)) {
1625 dataTypeDefinition.setModel(model);
1628 result = Either.left(dataTypeDefinition);
1632 private String getModel(final String uniqueId) {
1633 final Either<ImmutablePair<ModelData, GraphEdge>, JanusGraphOperationStatus> model = janusGraphGenericDao.getParentNode(
1634 UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.MODEL_ELEMENT,
1635 NodeTypeEnum.Model, ModelData.class);
1636 return model.isLeft() ? model.left().value().getLeft().getName() : StringUtils.EMPTY;
1639 public Either<String, JanusGraphOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
1640 String propertyType = propDataDef.getType();
1641 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
1642 return getInnerType(type, propDataDef::getSchema);
1645 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType,
1646 Map<String, DataTypeDefinition> dataTypes) {
1647 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
1648 ToscaPropertyType type = getType(propertyType);
1651 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
1652 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter
1653 .validateAndUpdate(value, dataTypeDefinition, dataTypes);
1654 if (Boolean.FALSE.equals(validateResult.right)) {
1655 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
1656 return Either.right(false);
1658 JsonElement jsonElement = validateResult.left;
1659 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
1660 return Either.left(valueFromJsonElement);
1662 log.trace("before validating property type {}", propertyType);
1663 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
1664 if (!isValidProperty) {
1665 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
1666 return Either.right(false);
1669 Object convertedValue = value;
1670 if (!isEmptyValue(value) && isValidate) {
1671 PropertyValueConverter converter = type.getConverter();
1672 convertedValue = converter.convert(value, innerType, dataTypes);
1674 return Either.left(convertedValue);
1677 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType,
1678 Map<String, DataTypeDefinition> dataTypes) {
1679 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
1682 public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType,
1684 return this.findPropertiesOfNode(nodeType, uniqueId).right().bind(this::handleNotFoundProperties).left()
1685 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
1688 private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(
1689 JanusGraphOperationStatus janusGraphOperationStatus) {
1690 if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
1691 return Either.left(new HashMap<>());
1693 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1696 private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId,
1697 NodeTypeEnum nodeType,
1699 Collection<PropertyDefinition> nodeProps) {
1700 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
1701 String currentNodeUid = uniqueId;
1702 Either<T, StorageOperationStatus> derivedFrom;
1703 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
1704 currentNodeUid = derivedFrom.left().value().getUniqueId();
1705 JanusGraphOperationStatus janusGraphOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
1706 if (janusGraphOperationStatus != JanusGraphOperationStatus.OK) {
1707 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
1708 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1711 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
1712 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
1715 private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
1716 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
1720 * @Override public PropertyOperation getPropertyOperation() { return this; }
1722 public JanusGraphOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
1723 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
1724 if (findPropertiesRes.isRight()) {
1725 return findPropertiesRes.right().value();
1727 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
1728 if (properties != null) {
1729 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
1730 propertySetter.accept(propertiesAsList);
1732 return JanusGraphOperationStatus.OK;
1735 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType) {
1736 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
1737 if (findPropertiesOfNode.isRight()) {
1738 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
1739 if (findPropertiesOfNode.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
1740 return Either.left(Maps.newHashMap());
1742 return findPropertiesOfNode;
1744 return findPropertiesOfNode;
1748 * add properties to element type.
1750 * Per property, add a property node and associate it to the element type
1753 * @param propertiesMap
1756 protected Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType,
1757 Map<String, PropertyDefinition> propertiesMap) {
1758 Map<String, PropertyData> propertiesData = new HashMap<>();
1759 if (propertiesMap != null) {
1760 for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
1761 String propertyName = propertyDefinitionEntry.getKey();
1762 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1763 .addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
1764 if (addPropertyToNodeType.isRight()) {
1765 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1766 log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName,
1768 return Either.right(operationStatus);
1770 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1773 return Either.left(propertiesData);
1776 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType,
1777 List<PropertyDefinition> properties) {
1778 Map<String, PropertyDefinition> propMap;
1779 if (properties == null) {
1782 propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
1784 return addPropertiesToElementType(uniqueId, elementType, propMap);
1788 public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1789 DataTypeDefinition oldDataTypeDefinition) {
1790 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
1793 private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1794 DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
1795 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1797 List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
1798 List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
1799 String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
1800 String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
1801 String dataTypeName = newDataTypeDefinition.getName();
1802 List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
1803 if (isPropertyOmitted(newProperties, oldProperties, dataTypeName) || isPropertyTypeChanged(dataTypeName, newProperties, oldProperties,
1804 propertiesToAdd) || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
1805 log.debug("The new data type {} is invalid.", dataTypeName);
1806 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
1809 if (propertiesToAdd == null || propertiesToAdd.isEmpty()) {
1810 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
1811 result = Either.right(StorageOperationStatus.OK);
1814 Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
1815 if (MapUtils.isNotEmpty(newDescriptions)) {
1816 JanusGraphOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(),
1818 if (updatePropertiesStatus != JanusGraphOperationStatus.OK) {
1819 log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}",
1820 oldDataTypeDefinition, updatePropertiesStatus);
1821 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1822 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatePropertiesStatus));
1826 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(
1827 oldDataTypeDefinition.getUniqueId(), oldDataTypeDefinition.getModel(), propertiesToAdd);
1828 if (addPropertiesToDataType.isRight()) {
1829 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition,
1830 addPropertiesToDataType.right().value().name());
1831 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1832 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToDataType.right().value()));
1835 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
1836 if (dataTypeByUid.isRight()) {
1837 JanusGraphOperationStatus status = addPropertiesToDataType.right().value();
1838 log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
1839 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
1840 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
1842 result = Either.left(dataTypeByUid.left().value());
1847 if (!inTransaction) {
1848 if (result == null || result.isRight()) {
1849 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1850 janusGraphGenericDao.rollback();
1852 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1853 janusGraphGenericDao.commit();
1859 private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties,
1860 List<PropertyDefinition> outputPropertiesToAdd) {
1861 if (newProperties != null && oldProperties != null) {
1862 Map<String, PropertyDefinition> newPropsMapper = newProperties.stream()
1863 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1864 Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream()
1865 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1866 for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
1867 String propName = newPropertyEntry.getKey();
1868 PropertyDefinition propDef = newPropertyEntry.getValue();
1869 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
1870 if (oldPropertyDefinition == null) {
1871 log.debug("New property {} received in the data type {}", propName, dataTypeName);
1872 outputPropertiesToAdd.add(propDef);
1875 String oldType = oldPropertyDefinition.getType();
1876 String oldEntryType = getEntryType(oldPropertyDefinition);
1877 String newType = propDef.getType();
1878 String newEntryType = getEntryType(propDef);
1879 if (!oldType.equals(newType)) {
1880 log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType,
1884 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
1885 log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName,
1886 oldEntryType, newEntryType);
1894 private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
1895 if (oldEntryType == null && newEntryType == null) {
1897 } else if (oldEntryType != null && newEntryType != null) {
1898 return oldEntryType.equals(newEntryType);
1904 private String getEntryType(PropertyDefinition oldPropertyDefinition) {
1905 String entryType = null;
1906 SchemaDefinition schema = oldPropertyDefinition.getSchema();
1907 if (schema != null) {
1908 PropertyDataDefinition schemaProperty = schema.getProperty();
1909 if (schemaProperty != null) {
1910 entryType = schemaProperty.getType();
1916 private boolean isPropertyOmitted(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, String dataTypeName) {
1917 boolean isValid = validateChangeInCaseOfEmptyProperties(newProperties, oldProperties, dataTypeName);
1919 log.debug("At least one property is missing in the new data type {}", dataTypeName);
1922 if (newProperties != null && oldProperties != null) {
1923 List<String> newProps = newProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
1924 List<String> oldProps = oldProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
1925 if (!newProps.containsAll(oldProps)) {
1926 StringJoiner joiner = new StringJoiner(",", "[", "]");
1927 newProps.forEach(joiner::add);
1928 log.debug("Properties {} in data type {} are missing, but they already defined in the existing data type", joiner.toString(),
1936 private boolean validateChangeInCaseOfEmptyProperties(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties,
1937 String dataTypeName) {
1938 if (newProperties != null) {
1939 if (newProperties.isEmpty()) {
1940 newProperties = null;
1943 if (oldProperties != null) {
1944 if (oldProperties.isEmpty()) {
1945 oldProperties = null;
1948 if ((newProperties == null && oldProperties == null) || (newProperties != null && oldProperties != null)) {
1954 private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
1955 if (newDerivedFromName != null) {
1956 boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
1958 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1959 oldDerivedFromName);
1962 } else if (oldDerivedFromName == null) {
1964 } else {// new=null, old != null
1965 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1966 oldDerivedFromName);
1976 public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
1977 Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
1978 if (graphResult.isRight()) {
1979 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
1981 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
1982 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
1983 if (vertexService.isRight()) {
1984 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
1985 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
1987 Vertex vertex = vertexService.left().value();
1988 VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
1989 Integer counter = 0;
1990 if (vertexProperty.isPresent() && vertexProperty.value() != null) {
1991 counter = (Integer) vertexProperty.value();
1994 vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
1995 return Either.left(counter);
1998 public Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesUniqueness(
1999 Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
2000 Either<List<PropertyDefinition>, JanusGraphOperationStatus> result = Either.left(properties);
2001 for (PropertyDefinition property : properties) {
2002 JanusGraphOperationStatus status = validatePropertyUniqueness(inheritedProperties, property);
2003 if (status != JanusGraphOperationStatus.OK) {
2004 result = Either.right(status);
2012 * Validates uniqueness of examined property by comparing it with properties in propertiesOfType and updates if need type and inner type of the
2015 private JanusGraphOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2016 String propertyName = property.getName();
2017 String propertyType = property.getType();
2018 JanusGraphOperationStatus result = JanusGraphOperationStatus.OK;
2019 if (inheritedProperties.containsKey(propertyName)) {
2020 PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2021 if (typesMismatch(propertyType, defaultProperty.getType())) {
2022 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2023 result = JanusGraphOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2025 property.setType(defaultProperty.getType());
2026 String innerType = defaultProperty.getSchemaType();
2027 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2028 if (schemaProperty != null) {
2029 schemaProperty.setType(innerType);
2036 private boolean typesMismatch(String type1, String type2) {
2037 return type1 != null && type2 != null && !type2.equals(type1);
2040 public <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllTypePropertiesFromAllDerivedFrom(
2041 String nextParentUid, NodeTypeEnum nodeType, Class<T> clazz) {
2042 Map<String, PropertyDefinition> allProperies = new HashMap<>();
2043 return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2046 private <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getTypePropertiesFromDerivedFromRecursively(
2047 String nextParentUid, Map<String, PropertyDefinition> allProperies, NodeTypeEnum nodeType, Class<T> clazz) {
2048 JanusGraphOperationStatus error;
2049 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
2050 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2051 if (childrenNodes.isRight()) {
2052 if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
2053 error = childrenNodes.right().value();
2054 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid,
2056 return Either.right(error);
2058 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.",
2060 return Either.left(allProperies);
2063 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2064 if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
2065 error = allPropertiesOfTypeRes.right().value();
2067 "#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}",
2068 nextParentUid, error);
2069 return Either.right(error);
2070 } else if (allPropertiesOfTypeRes.isLeft()) {
2071 if (allProperies.isEmpty()) {
2072 allProperies.putAll(allPropertiesOfTypeRes.left().value());
2074 allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey()))
2075 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2078 return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType,
2083 private JanusGraphOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2084 if (MapUtils.isNotEmpty(newDescriptions)) {
2085 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getDataTypePropertiesRes = janusGraphGenericDao
2086 .getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2087 if (getDataTypePropertiesRes.isRight()) {
2088 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2089 return getDataTypePropertiesRes.right().value();
2091 getDataTypePropertiesRes.left().value().stream().filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2092 .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2094 return JanusGraphOperationStatus.OK;
2097 private JanusGraphVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<JanusGraphVertex, Edge> pair) {
2098 return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2101 private String getPropertyNameFromEdge(ImmutablePair<JanusGraphVertex, Edge> pair) {
2102 return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2105 private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2106 Map<String, PropertyDefinition> newPropertiesMap = newProperties.stream().collect(Collectors.toMap(PropertyDefinition::getName, p -> p));
2107 return oldProperties.stream()
2108 .filter(p -> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2109 .collect(Collectors.toMap(PropertyDefinition::getName, p -> newPropertiesMap.get(p.getName()).getDescription()));
2112 private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty) {
2113 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2116 if (StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2119 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())) {
2122 return property.getDescription().equals(otherProperty.getDescription());
2125 public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
2128 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
2129 JsonParser parser = new JsonParser();
2130 JsonObject result = new JsonObject();
2131 JsonArray jsonArray = new JsonArray();
2132 if (src instanceof InRangeConstraint) {
2133 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
2134 jsonArray.add(parser.parse(rangeConstraint.getRangeMinValue()));
2135 jsonArray.add(parser.parse(rangeConstraint.getRangeMaxValue()));
2136 result.add("inRange", jsonArray);
2137 } else if (src instanceof GreaterThanConstraint) {
2138 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
2139 jsonArray.add(parser.parse(greaterThanConstraint.getGreaterThan()));
2140 result.add("greaterThan", jsonArray);
2141 } else if (src instanceof LessOrEqualConstraint) {
2142 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
2143 jsonArray.add(parser.parse(lessOrEqualConstraint.getLessOrEqual()));
2144 result.add("lessOrEqual", jsonArray);
2146 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
2152 public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
2154 private static final String THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL = "The value of GreaterThanConstraint is null";
2157 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
2158 PropertyConstraint propertyConstraint = null;
2159 Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
2160 if (set.size() == 1) {
2161 Entry<String, JsonElement> element = set.iterator().next();
2162 String key = element.getKey();
2163 JsonElement value = element.getValue();
2164 ConstraintType constraintType = ConstraintType.getByType(key);
2165 if (constraintType == null) {
2166 log.warn("ConstraintType was not found for constraint name:{}", key);
2168 switch (constraintType) {
2170 if (value != null) {
2171 if (value instanceof JsonArray) {
2172 JsonArray rangeArray = (JsonArray) value;
2173 if (rangeArray.size() != 2) {
2174 log.error("The range constraint content is invalid. value = {}", value);
2176 InRangeConstraint rangeConstraint = new InRangeConstraint();
2177 String minValue = rangeArray.get(0).getAsString();
2179 JsonElement maxElement = rangeArray.get(1);
2180 if (maxElement.isJsonNull()) {
2181 maxValue = String.valueOf(maxElement.getAsJsonNull());
2183 maxValue = maxElement.getAsString();
2185 rangeConstraint.setRangeMinValue(minValue);
2186 rangeConstraint.setRangeMaxValue(maxValue);
2187 propertyConstraint = rangeConstraint;
2191 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2195 if (value != null) {
2196 String asString = value.getAsString();
2197 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
2198 propertyConstraint = new GreaterThanConstraint(asString);
2201 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2205 if (value != null) {
2206 String asString = value.getAsString();
2207 log.debug("Before adding value to LessThanConstraint object. value = {}", asString);
2208 propertyConstraint = new LessThanConstraint(asString);
2211 log.warn("The value of LessThanConstraint is null");
2214 case GREATER_OR_EQUAL:
2215 if (value != null) {
2216 String asString = value.getAsString();
2217 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
2218 propertyConstraint = new GreaterOrEqualConstraint(asString);
2221 log.warn("The value of GreaterOrEqualConstraint is null");
2225 if (value != null) {
2226 String asString = value.getAsString();
2227 log.debug("Before adding value to LessOrEqualConstraint object. value = {}", asString);
2228 propertyConstraint = new LessOrEqualConstraint(asString);
2230 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2234 if (value != null) {
2235 JsonArray rangeArray = (JsonArray) value;
2236 if (rangeArray.size() == 0) {
2237 log.error("The valid values constraint content is invalid. value = {}", value);
2239 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2240 List<String> validValues = new ArrayList<>();
2241 for (JsonElement jsonElement : rangeArray) {
2242 String item = jsonElement.getAsString();
2243 validValues.add(item);
2245 vvConstraint.setValidValues(validValues);
2246 propertyConstraint = vvConstraint;
2251 if (value != null) {
2252 int asInt = value.getAsInt();
2253 log.debug("Before adding value to Min Length object. value = {}", asInt);
2254 propertyConstraint = new MinLengthConstraint(asInt);
2257 log.warn("The value of MinLengthConstraint is null");
2261 log.warn("Key {} is not supported. Ignored.", key);
2265 return propertyConstraint;
2269 public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
2272 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
2273 ObjectCodec oc = json.getCodec();
2274 JsonNode node = oc.readTree(json);