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.fasterxml.jackson.databind.node.ArrayNode;
28 import com.google.common.collect.Maps;
29 import com.google.gson.JsonArray;
30 import com.google.gson.JsonDeserializationContext;
31 import com.google.gson.JsonDeserializer;
32 import com.google.gson.JsonElement;
33 import com.google.gson.JsonObject;
34 import com.google.gson.JsonParseException;
35 import com.google.gson.JsonParser;
36 import com.google.gson.JsonPrimitive;
37 import com.google.gson.JsonSerializationContext;
38 import com.google.gson.JsonSerializer;
39 import com.google.gson.JsonSyntaxException;
40 import fj.data.Either;
41 import java.io.IOException;
42 import java.lang.reflect.InvocationTargetException;
43 import java.lang.reflect.Type;
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.Iterator;
49 import java.util.List;
51 import java.util.Map.Entry;
53 import java.util.function.Consumer;
54 import java.util.regex.Matcher;
55 import java.util.regex.Pattern;
56 import java.util.stream.Collectors;
57 import org.apache.commons.collections.CollectionUtils;
58 import org.apache.commons.collections.MapUtils;
59 import org.apache.commons.lang3.StringUtils;
60 import org.apache.commons.lang3.tuple.ImmutablePair;
61 import org.apache.tinkerpop.gremlin.structure.Edge;
62 import org.apache.tinkerpop.gremlin.structure.Vertex;
63 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
64 import org.janusgraph.core.JanusGraph;
65 import org.janusgraph.core.JanusGraphVertex;
66 import org.janusgraph.core.JanusGraphVertexProperty;
67 import org.openecomp.sdc.be.config.BeEcompErrorManager;
68 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
69 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
70 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
71 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
72 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
73 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
74 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
75 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
76 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
77 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
78 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
79 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
80 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
81 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
82 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
83 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
84 import org.openecomp.sdc.be.model.Component;
85 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
86 import org.openecomp.sdc.be.model.DataTypeDefinition;
87 import org.openecomp.sdc.be.model.IComplexDefaultValue;
88 import org.openecomp.sdc.be.model.PropertyConstraint;
89 import org.openecomp.sdc.be.model.PropertyDefinition;
90 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
91 import org.openecomp.sdc.be.model.operations.api.IPropertyOperation;
92 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
93 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
94 import org.openecomp.sdc.be.model.tosca.constraints.EqualConstraint;
95 import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint;
96 import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
97 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
98 import org.openecomp.sdc.be.model.tosca.constraints.LengthConstraint;
99 import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
100 import org.openecomp.sdc.be.model.tosca.constraints.LessThanConstraint;
101 import org.openecomp.sdc.be.model.tosca.constraints.MaxLengthConstraint;
102 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
103 import org.openecomp.sdc.be.model.tosca.constraints.PatternConstraint;
104 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
105 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
106 import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator;
107 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
108 import org.openecomp.sdc.be.resources.data.DataTypeData;
109 import org.openecomp.sdc.be.resources.data.ModelData;
110 import org.openecomp.sdc.be.resources.data.PropertyData;
111 import org.openecomp.sdc.be.resources.data.PropertyValueData;
112 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
113 import org.openecomp.sdc.be.resources.data.UniqueIdData;
114 import org.openecomp.sdc.common.log.wrappers.Logger;
115 import org.springframework.beans.factory.annotation.Autowired;
117 @org.springframework.stereotype.Component("property-operation")
118 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
120 private static final String AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS = "After retrieving DERIVED_FROM node of {}. status is {}";
121 private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
122 private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
123 private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
124 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
125 private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS = "Failed to associate resource {} to property {} in graph. status is {}";
126 private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
127 private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
128 private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
129 private static final String PROPERTY = "Property";
130 private static final String UPDATE_DATA_TYPE = "UpdateDataType";
131 private static final Logger log = Logger.getLogger(PropertyOperation.class.getName());
132 private final DerivedFromOperation derivedFromOperation;
133 private ToscaFunctionValidator toscaFunctionValidator;
134 private DataTypeOperation dataTypeOperation;
137 public PropertyOperation(final HealingJanusGraphGenericDao janusGraphGenericDao, final DerivedFromOperation derivedFromOperation) {
138 this.janusGraphGenericDao = janusGraphGenericDao;
139 this.derivedFromOperation = derivedFromOperation;
143 public void setToscaFunctionValidator(final ToscaFunctionValidator toscaFunctionValidator) {
144 this.toscaFunctionValidator = toscaFunctionValidator;
147 //circular dependency DataTypeOperation->ModelOperation->ModelElementOperation->PropertyOperation
149 public void setDataTypeOperation(DataTypeOperation dataTypeOperation) {
150 this.dataTypeOperation = dataTypeOperation;
153 public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
154 log.debug("The object returned after create property is {}", propertyDataResult);
155 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
156 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
157 propertyDefResult.setName(propertyName);
158 return propertyDefResult;
161 public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
162 Either<PropertyData, JanusGraphOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
163 if (either.isRight()) {
164 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
165 return Either.right(storageStatus);
167 return Either.left(either.left().value());
171 * @param propertyDefinition
175 public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
176 log.trace("Going to validate property type and value. {}", propertyDefinition);
177 String propertyType = propertyDefinition.getType();
178 String value = propertyDefinition.getDefaultValue();
179 ToscaPropertyType type = getType(propertyType);
181 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
182 if (dataTypeDefinition == null) {
183 log.debug("The type {} of property cannot be found.", propertyType);
184 return StorageOperationStatus.INVALID_TYPE;
186 return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
188 String innerType = null;
189 Either<String, JanusGraphOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
190 if (checkInnerType.isRight()) {
191 return StorageOperationStatus.INVALID_TYPE;
193 innerType = checkInnerType.left().value();
194 log.trace("After validating property type {}", propertyType);
195 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
196 if (!isValidProperty) {
197 log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
198 return StorageOperationStatus.INVALID_VALUE;
200 PropertyValueConverter converter = type.getConverter();
201 if (isEmptyValue(value)) {
202 log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
203 propertyDefinition.setDefaultValue(EMPTY_VALUE);
204 } else if (!isEmptyValue(value)) {
205 String convertedValue = converter.convert(value, innerType, dataTypes);
206 propertyDefinition.setDefaultValue(convertedValue);
208 return StorageOperationStatus.OK;
211 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition,
213 ResourceMetadataData resourceData = new ResourceMetadataData();
214 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
215 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
216 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
217 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
218 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
219 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
220 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
221 if (createNodeResult.isRight()) {
222 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
223 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
224 return Either.right(operationStatus);
226 Map<String, Object> props = new HashMap<>();
227 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
228 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
229 .createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
230 if (createRelResult.isRight()) {
231 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
232 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
233 return Either.right(operationStatus);
235 return Either.left(createNodeResult.left().value());
238 public JanusGraphOperationStatus addPropertyToGraphByVertex(JanusGraphVertex metadataVertex, String propertyName,
239 PropertyDefinition propertyDefinition, String resourceId) {
240 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
241 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
242 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
243 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
244 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData);
245 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
246 if (createNodeResult.isRight()) {
247 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
248 log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
249 return operationStatus;
251 Map<String, Object> props = new HashMap<>();
252 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
253 JanusGraphVertex propertyVertex = createNodeResult.left().value();
254 JanusGraphOperationStatus createRelResult = janusGraphGenericDao.createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
255 if (!createRelResult.equals(JanusGraphOperationStatus.OK)) {
256 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
257 return createRelResult;
259 return createRelResult;
262 public JanusGraphGenericDao getJanusGraphGenericDao() {
263 return janusGraphGenericDao;
269 * @param janusGraphGenericDao
271 public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
272 this.janusGraphGenericDao = janusGraphGenericDao;
275 public Either<PropertyData, JanusGraphOperationStatus> deletePropertyFromGraph(String propertyId) {
276 log.debug("Before deleting property from graph {}", propertyId);
277 return janusGraphGenericDao.deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
280 public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition,
281 Map<String, DataTypeDefinition> dataTypes) {
282 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
283 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
284 return Either.right(validateAndUpdateProperty);
286 Either<PropertyData, JanusGraphOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
287 if (either.isRight()) {
288 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
289 return Either.right(storageStatus);
291 return Either.left(either.left().value());
294 public Either<PropertyData, JanusGraphOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
295 if (log.isDebugEnabled()) {
296 log.debug("Before updating property on graph {}", propertyId);
298 // get the original property data
299 Either<PropertyData, JanusGraphOperationStatus> statusProperty = janusGraphGenericDao
300 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
301 if (statusProperty.isRight()) {
302 log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
303 return Either.right(statusProperty.right().value());
305 PropertyData orgPropertyData = statusProperty.left().value();
306 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
307 // create new property data to update
308 PropertyData newPropertyData = new PropertyData();
309 newPropertyData.setPropertyDataDefinition(propertyDefinition);
310 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
311 // update the original property data with new values
312 if (orgPropertyDataDefinition.getDefaultValue() == null) {
313 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
315 if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
316 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
319 if (orgPropertyDataDefinition.getDescription() == null) {
320 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
322 if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
323 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
326 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
327 orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
329 if (newPropertyData.getConstraints() != null) {
330 orgPropertyData.setConstraints(newPropertyData.getConstraints());
332 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
333 return janusGraphGenericDao.updateNode(orgPropertyData, PropertyData.class);
336 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition,
337 NodeTypeEnum nodeType, String uniqueId) {
338 return addPropertyToNodeType(propertyName, propertyDefinition, nodeType, uniqueId, true);
341 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(final String propertyName,
342 final PropertyDefinition propertyDefinition,
343 final NodeTypeEnum nodeType, final String uniqueId,
344 final boolean inTransaction) {
345 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
346 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
347 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
348 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
349 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
350 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
351 if (createNodeResult.isRight()) {
352 if (!inTransaction) {
353 janusGraphGenericDao.rollback();
355 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
356 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
357 return Either.right(operationStatus);
359 Map<String, Object> props = new HashMap<>();
360 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
361 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
362 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
363 Either<GraphRelation, JanusGraphOperationStatus> createRelResult =
364 janusGraphGenericDao.createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
365 if (createRelResult.isRight()) {
366 if (!inTransaction) {
367 janusGraphGenericDao.rollback();
369 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
370 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
371 return Either.right(operationStatus);
373 if (!inTransaction) {
374 janusGraphGenericDao.commit();
376 return Either.left(createNodeResult.left().value());
379 public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
380 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
381 Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
382 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
384 if (childrenNodes.isRight()) {
385 JanusGraphOperationStatus operationStatus = childrenNodes.right().value();
386 return Either.right(operationStatus);
388 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
389 if (values != null) {
390 for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
391 GraphEdge edge = immutablePair.getValue();
392 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
393 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
394 PropertyData propertyData = immutablePair.getKey();
395 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
396 resourceProps.put(propertyName, propertyDefinition);
399 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
400 return Either.left(resourceProps);
403 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
404 return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId).right()
405 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
408 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
409 Map<String, PropertyDefinition> newProperties) {
410 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
411 Map<String, PropertyDefinition> reallyNewProperties;
412 Map<String, PropertyData> unchangedPropsData;
413 if (oldPropertiesRes.isRight()) {
414 JanusGraphOperationStatus err = oldPropertiesRes.right().value();
415 if (err == JanusGraphOperationStatus.NOT_FOUND) {
416 reallyNewProperties = newProperties;
417 unchangedPropsData = Collections.emptyMap();
419 return Either.right(err);
422 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
423 reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
424 for (Entry<String, PropertyDefinition> oldEntry : oldProperties.entrySet()) {
425 String key = oldEntry.getKey();
426 PropertyDefinition newPropDef = newProperties != null ? newProperties.get(key) : null;
427 PropertyDefinition oldPropDef = oldEntry.getValue();
428 JanusGraphOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
429 if (status != JanusGraphOperationStatus.OK) {
430 return Either.right(status);
433 unchangedPropsData = oldProperties.entrySet().stream()
434 .collect(Collectors.toMap(Entry::getKey, e -> new PropertyData(e.getValue(), null)));
436 // add other properties
437 return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
441 * @param newProperties
442 * @param oldProperties
445 private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties,
446 Map<String, PropertyDefinition> oldProperties) {
447 return newProperties != null ? newProperties.entrySet().stream().filter(entry -> !oldProperties.containsKey(entry.getKey()))
448 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)) : null;
455 private JanusGraphOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
456 if (!isUpdateAllowed(newPropDef, oldPropDef)) {
457 return JanusGraphOperationStatus.MATCH_NOT_FOUND;
459 if (isUpdateRequired(newPropDef, oldPropDef)) {
460 modifyOldPropByNewOne(newPropDef, oldPropDef);
461 List<PropertyConstraint> constraints = oldPropDef.getConstraints();
462 PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
463 Either<PropertyData, JanusGraphOperationStatus> updateResult = janusGraphGenericDao.updateNode(node, PropertyData.class);
464 if (updateResult.isRight()) {
465 return updateResult.right().value();
468 return JanusGraphOperationStatus.OK;
475 private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
476 if (newPropDef == null) {
477 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
480 // If the property type is missing it's something that we could want to fix
481 if (oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
482 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
489 * Update only fields which modification is permitted.
494 private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
495 oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
496 oldPropDef.setDescription(newPropDef.getDescription());
497 oldPropDef.setRequired(newPropDef.isRequired());
498 // Type is updated to fix possible null type issue in janusGraph DB
499 oldPropDef.setType(newPropDef.getType());
502 private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
503 return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) || !StringUtils
504 .equals(oldPropDef.getDescription(), newPropDef.getDescription()) || oldPropDef.isRequired() != newPropDef.isRequired();
508 * Adds newProperties and returns in case of success (left part of Either) map of all properties i. e. added ones and contained in
513 * @param newProperties
514 * @param unchangedPropsData
517 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId,
518 Map<String, PropertyDefinition> newProperties,
519 Map<String, PropertyData> unchangedPropsData) {
520 return addPropertiesToElementType(uniqueId, nodeType, newProperties).left().map(m -> {
521 m.putAll(unchangedPropsData);
526 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType,
528 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
529 if (propertiesOfNodeRes.isRight()) {
530 JanusGraphOperationStatus status = propertiesOfNodeRes.right().value();
531 if (status == JanusGraphOperationStatus.NOT_FOUND) {
532 return Either.right(StorageOperationStatus.OK);
534 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
536 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
537 for (PropertyDefinition propertyDefinition : value.values()) {
538 String propertyUid = propertyDefinition.getUniqueId();
539 Either<PropertyData, JanusGraphOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
540 if (deletePropertyRes.isRight()) {
541 log.error("Failed to delete property with id {}", propertyUid);
542 JanusGraphOperationStatus status = deletePropertyRes.right().value();
543 if (status == JanusGraphOperationStatus.NOT_FOUND) {
544 status = JanusGraphOperationStatus.INVALID_ID;
546 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
549 log.debug("The properties deleted from node {} are {}", uniqueId, value);
550 return Either.left(value);
554 * 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
555 * (including derived from hierarchy)
559 * @param propertyName
560 * @param propertyType
563 public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
564 boolean result = false;
565 if (!CollectionUtils.isEmpty(properties)) {
566 for (PropertyDefinition propertyDefinition : properties) {
567 if (propertyDefinition.getName().equals(propertyName) && (propertyDefinition.getParentUniqueId().equals(resourceUid)
568 || !propertyDefinition.getType().equals(propertyType))) {
577 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType,
578 Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
579 if (rules == null || rules.isEmpty()) {
580 return new ImmutablePair<>(null, true);
582 for (PropertyRule rule : rules) {
583 String value = rule.getValue();
584 Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
585 if (updateResult.isRight()) {
586 Boolean status = updateResult.right().value();
588 return new ImmutablePair<>(value, status);
591 String newValue = null;
592 Object object = updateResult.left().value();
593 if (object != null) {
594 newValue = object.toString();
596 rule.setValue(newValue);
599 return new ImmutablePair<>(null, true);
602 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
603 String resourceInstanceId) {
604 List<PropertyRule> rules = resourceInstanceProperty.getRules();
606 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
607 rules = new ArrayList<>();
608 rules.add(propertyRule);
610 rules = sortRules(rules);
612 propertyValueData.setRules(rules);
615 private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
616 String resourceInstanceId) {
617 List<String> path = resourceInstanceProperty.getPath();
618 // FOR BC. Since old Property values on VFC/VF does not have rules on
622 // Update could be done on one level only, thus we can use this
624 // operation to avoid migration.
625 if (path == null || path.isEmpty()) {
626 path = new ArrayList<>();
627 path.add(resourceInstanceId);
629 PropertyRule propertyRule = new PropertyRule();
630 propertyRule.setRule(path);
631 propertyRule.setValue(propertyValueData.getValue());
635 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
636 // TODO: sort the rules by size and binary representation.
638 // (x, y, .+) --> 110 6 priority 1
640 // (x, .+, z) --> 101 5 priority 2
644 public ImmutablePair<JanusGraphOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
645 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
646 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllRes = this
647 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
648 if (getAllRes.isRight()) {
649 JanusGraphOperationStatus status = getAllRes.right().value();
650 log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
651 return new ImmutablePair<>(status, null);
653 List<ComponentInstanceProperty> list = getAllRes.left().value();
655 for (ComponentInstanceProperty instanceProperty : list) {
656 String propertyUniqueId = instanceProperty.getUniqueId();
657 String valueUniqueUid = instanceProperty.getValueUniqueUid();
658 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
659 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
660 log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
661 return new ImmutablePair<>(JanusGraphOperationStatus.ALREADY_EXIST, valueUniqueUid);
665 return new ImmutablePair<>(JanusGraphOperationStatus.NOT_FOUND, null);
668 public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
669 String resourceInstanceId) {
670 List<PropertyRule> currentRules = propertyValueData.getRules();
671 List<PropertyRule> rules = resourceInstanceProperty.getRules();
672 // if rules are not supported.
674 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
675 rules = new ArrayList<>();
676 rules.add(propertyRule);
677 if (currentRules != null) {
678 rules = mergeRules(currentRules, rules);
681 // Full mode. all rules are sent in update operation.
682 rules = sortRules(rules);
684 propertyValueData.setRules(rules);
687 private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
688 List<PropertyRule> mergedRules = new ArrayList<>();
689 if (newRules == null || newRules.isEmpty()) {
692 for (PropertyRule rule : currentRules) {
693 PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
694 mergedRules.add(propertyRule);
696 for (PropertyRule rule : newRules) {
697 PropertyRule foundRule = findRuleInList(rule, mergedRules);
698 if (foundRule != null) {
699 foundRule.setValue(rule.getValue());
701 mergedRules.add(rule);
707 private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
708 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
711 PropertyRule foundRule = null;
712 for (PropertyRule propertyRule : rules) {
713 if (rule.getRuleSize() != propertyRule.getRuleSize()) {
716 boolean equals = propertyRule.compareRule(rule);
718 foundRule = propertyRule;
726 * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
728 * @param resourceInstanceUid
731 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
732 String resourceInstanceUid) {
733 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
736 public Either<PropertyValueData, JanusGraphOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
737 Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
738 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
739 if (findResInstanceRes.isRight()) {
740 JanusGraphOperationStatus status = findResInstanceRes.right().value();
741 if (status == JanusGraphOperationStatus.NOT_FOUND) {
742 status = JanusGraphOperationStatus.INVALID_ID;
744 return Either.right(status);
746 Either<PropertyValueData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
747 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
748 if (findPropertyDefRes.isRight()) {
749 JanusGraphOperationStatus status = findPropertyDefRes.right().value();
750 if (status == JanusGraphOperationStatus.NOT_FOUND) {
751 status = JanusGraphOperationStatus.INVALID_ID;
753 return Either.right(status);
755 Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
756 .getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
757 if (relation.isRight()) {
758 // TODO: add error in case of error
759 JanusGraphOperationStatus status = relation.right().value();
760 if (status == JanusGraphOperationStatus.NOT_FOUND) {
761 status = JanusGraphOperationStatus.INVALID_ID;
763 return Either.right(status);
765 Either<PropertyValueData, JanusGraphOperationStatus> deleteNode = janusGraphGenericDao
766 .deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
767 if (deleteNode.isRight()) {
768 return Either.right(deleteNode.right().value());
770 PropertyValueData value = deleteNode.left().value();
771 return Either.left(value);
774 public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid,
775 String resourceInstanceId,
776 boolean inTransaction) {
777 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
779 Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = this
780 .removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
781 if (eitherStatus.isRight()) {
782 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId,
783 eitherStatus.right().value().name());
784 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
787 PropertyValueData propertyValueData = eitherStatus.left().value();
788 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
789 propertyValueResult.setUniqueId(resourceInstanceId);
790 propertyValueResult.setValue(propertyValueData.getValue());
791 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
792 result = Either.left(propertyValueResult);
796 if (!inTransaction) {
797 if (result == null || result.isRight()) {
798 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
799 janusGraphGenericDao.rollback();
801 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
802 janusGraphGenericDao.commit();
808 public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData,
809 ComponentInstanceProperty resourceInstanceProperty) {
810 String value = propertyValueData.getValue();
811 String uid = propertyValueData.getUniqueId();
812 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
813 instanceProperty.setPath(resourceInstanceProperty.getPath());
814 return instanceProperty;
818 public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
819 if (propertyDefinition == null) {
822 String innerType = null;
823 String propertyType = propertyDefinition.getType();
824 ToscaPropertyType type = getType(propertyType);
825 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
826 SchemaDefinition def = propertyDefinition.getSchema();
830 PropertyDataDefinition propDef = def.getProperty();
831 if (propDef == null) {
834 innerType = propDef.getType();
836 String value = propertyDefinition.getDefaultValue();
838 return isValidValue(type, value, innerType, dataTypes);
840 log.trace("The given type {} is not a pre defined one.", propertyType);
841 DataTypeDefinition foundDt = dataTypes.get(propertyType);
842 if (foundDt != null) {
843 return isValidComplexValue(foundDt, value, dataTypes);
850 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final String model) {
851 if (property == null) {
854 if (ToscaPropertyType.isValidType(property.getType()) == null) {
855 Either<Boolean, JanusGraphOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType(), model);
856 if (definedInDataTypes.isRight()) {
859 Boolean isExist = definedInDataTypes.left().value();
860 return isExist.booleanValue();
866 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final Map<String, DataTypeDefinition> dataTypes) {
867 if (property == null) {
870 return ToscaPropertyType.isValidType(property.getType()) != null || dataTypes.containsKey(property.getType());
874 public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
875 if (property == null) {
876 return new ImmutablePair<>(null, false);
878 SchemaDefinition schema;
879 PropertyDataDefinition innerProp;
880 String innerType = null;
881 if ((schema = property.getSchema()) != null) {
882 if ((innerProp = schema.getProperty()) != null) {
883 innerType = innerProp.getType();
886 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
887 if (innerToscaType == null) {
888 DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
889 if (dataTypeDefinition == null) {
890 log.debug("The inner type {} is not a data type.", innerType);
891 return new ImmutablePair<>(innerType, false);
893 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
896 return new ImmutablePair<>(innerType, true);
899 private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
900 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
901 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
902 return validateAndUpdate.right.booleanValue();
905 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
906 String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
907 Either<JanusGraphVertex, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
908 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
909 if (findResInstanceRes.isRight()) {
910 JanusGraphOperationStatus status = findResInstanceRes.right().value();
911 if (status == JanusGraphOperationStatus.NOT_FOUND) {
912 status = JanusGraphOperationStatus.INVALID_ID;
914 return Either.right(status);
916 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> propertyImplNodes = janusGraphGenericDao
917 .getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
918 if (propertyImplNodes.isRight()) {
919 JanusGraphOperationStatus status = propertyImplNodes.right().value();
920 return Either.right(status);
922 List<ImmutablePair<JanusGraphVertex, Edge>> list = propertyImplNodes.left().value();
923 if (list == null || list.isEmpty()) {
924 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
926 List<ComponentInstanceProperty> result = new ArrayList<>();
927 for (ImmutablePair<JanusGraphVertex, Edge> propertyValue : list) {
928 JanusGraphVertex propertyValueDataVertex = propertyValue.getLeft();
929 String propertyValueUid = (String) janusGraphGenericDao
930 .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
931 String value = (String) janusGraphGenericDao.getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
932 ImmutablePair<JanusGraphVertex, Edge> propertyDefPair = janusGraphGenericDao
933 .getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
934 if (propertyDefPair == null) {
935 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
937 Map<String, Object> properties = janusGraphGenericDao.getProperties(propertyValueDataVertex);
938 PropertyValueData propertyValueData = GraphElementFactory
939 .createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
940 String propertyUniqueId = (String) janusGraphGenericDao
941 .getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
942 ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
943 // set property original unique id
944 resourceInstanceProperty.setUniqueId(propertyUniqueId);
947 // TODO: esofer add resource id
948 resourceInstanceProperty.setParentUniqueId(null);
950 resourceInstanceProperty.setValue(value);
951 // set property value unique id
952 resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
954 resourceInstanceProperty.setRules(propertyValueData.getRules());
955 result.add(resourceInstanceProperty);
957 return Either.left(result);
961 * Find the default value from the list of component instances. Start the search from the second component instance
963 * @param pathOfComponentInstances
964 * @param propertyUniqueId
965 * @param defaultValue
968 public Either<String, JanusGraphOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances,
969 String propertyUniqueId, String defaultValue) {
970 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
971 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
972 return Either.left(defaultValue);
974 String result = defaultValue;
975 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
976 String compInstanceId = pathOfComponentInstances.get(i);
977 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> propertyValuesResult = this
978 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
979 log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
980 if (propertyValuesResult.isRight()) {
981 JanusGraphOperationStatus status = propertyValuesResult.right().value();
982 if (status != JanusGraphOperationStatus.NOT_FOUND) {
983 return Either.right(status);
988 ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
989 log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
990 if (foundCompInstanceProperty == null) {
993 List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i),
994 foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
995 log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
996 PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
997 log.trace("Match rule is {}", matchedRule);
998 if (matchedRule != null) {
999 result = matchedRule.getValue();
1003 return Either.left(result);
1006 private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
1007 ComponentInstanceProperty result = null;
1011 for (ComponentInstanceProperty instProperty : list) {
1012 if (instProperty.getUniqueId().equals(propertyUniqueId)) {
1013 result = instProperty;
1020 private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
1021 if (rules != null) {
1024 rules = buildDefaultRule(compInstanceId, ruleSize, value);
1028 private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
1029 List<PropertyRule> rules = componentInstanceProperty.getRules();
1030 if (rules == null) {
1031 rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
1036 private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
1037 List<PropertyRule> rules = new ArrayList<>();
1038 List<String> rule = new ArrayList<>();
1039 rule.add(componentInstanceId);
1040 for (int i = 0; i < size - 1; i++) {
1041 rule.add(PropertyRule.getRuleAnyMatch());
1043 PropertyRule propertyRule = new PropertyRule(rule, value);
1044 rules.add(propertyRule);
1048 private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1049 PropertyRule propertyRule = null;
1050 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1051 String firstCompInstance = pathOfInstances.get(level);
1052 if (rules != null) {
1053 for (PropertyRule rule : rules) {
1054 int ruleSize = rule.getRule().size();
1055 // check the length of the rule equals to the length of the
1058 if (ruleSize != pathOfInstances.size() - level) {
1061 // check that the rule starts with correct component instance id
1062 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1065 String secondToken = rule.getToken(2);
1066 if (secondToken != null && (secondToken.equals(PropertyRule.getForceAll()) || secondToken.equals(PropertyRule.getALL()))) {
1067 propertyRule = rule;
1070 String patternStr = buildStringForMatch(rule.getRule(), 0);
1071 Pattern pattern = Pattern.compile(patternStr);
1072 Matcher matcher = pattern.matcher(stringForMatch);
1073 if (matcher.matches()) {
1074 if (log.isTraceEnabled()) {
1075 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1077 propertyRule = rule;
1082 return propertyRule;
1085 private boolean checkFirstItem(String left, String right) {
1086 if (left != null && left.equals(right)) {
1092 private String buildStringForMatch(List<String> pathOfInstances, int level) {
1093 StringBuilder builder = new StringBuilder();
1094 for (int i = level; i < pathOfInstances.size(); i++) {
1095 builder.append(pathOfInstances.get(i));
1096 if (i < pathOfInstances.size() - 1) {
1097 builder.append("#");
1100 return builder.toString();
1103 public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty,
1104 Map<String, ComponentInstanceProperty> instanceIdToValue) {
1105 List<String> pathOfInstances = instanceProperty.getPath();
1107 int size = pathOfInstances.size();
1108 int numberOfMatches = 0;
1109 for (String instanceId : pathOfInstances) {
1110 ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1111 if (componentInstanceProperty != null) {
1112 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1113 // If it is the first level instance, then update valueUniuqeId
1115 // parameter in order to know on update that
1117 // we should update and not create new node on graph.
1119 instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1120 instanceProperty.setRules(rules);
1122 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1125 String value = rule.getValue();
1126 if (numberOfMatches == 1) {
1127 instanceProperty.setValue(value);
1128 if (log.isDebugEnabled()) {
1129 log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1130 pathOfInstances, value);
1132 } else if (numberOfMatches == 2) {
1133 // In case of another property value match, then use the
1135 // value to be the default value of the property.
1136 instanceProperty.setDefaultValue(value);
1137 if (log.isDebugEnabled()) {
1138 log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1139 pathOfInstances, value);
1150 * Add data type to graph.
1152 * 1. Add data type node
1154 * 2. Add edge between the former node to its parent(if exists)
1156 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1158 * @param dataTypeDefinition
1161 private Either<DataTypeData, JanusGraphOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1162 log.debug("Got data type {}", dataTypeDefinition);
1163 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getModel(), dataTypeDefinition.getName());
1164 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1165 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1166 Either<DataTypeData, JanusGraphOperationStatus> createDataTypeResult = janusGraphGenericDao.createNode(dataTypeData, DataTypeData.class);
1167 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1168 if (createDataTypeResult.isRight()) {
1169 JanusGraphOperationStatus operationStatus = createDataTypeResult.right().value();
1170 log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1171 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1172 return Either.right(operationStatus);
1174 DataTypeData resultCTD = createDataTypeResult.left().value();
1175 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1176 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(),
1177 dataTypeDefinition.getModel(),
1179 if (addPropertiesToDataType.isRight()) {
1180 log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1181 return Either.right(addPropertiesToDataType.right().value());
1184 final Either<GraphRelation, JanusGraphOperationStatus> modelRelationship = addDataTypeToModel(dataTypeDefinition);
1185 if (modelRelationship.isRight()) {
1186 return Either.right(modelRelationship.right().value());
1189 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1190 if (derivedFrom != null) {
1191 final Either<DataTypeDefinition, JanusGraphOperationStatus> derivedFromDataType = getDataTypeByNameValidForModel(derivedFrom,
1192 dataTypeDefinition.getModel());
1193 if (derivedFromDataType.isRight()) {
1194 return Either.right(derivedFromDataType.right().value());
1197 log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1198 UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1199 final String deriveFromUid = derivedFromDataType.left().value().getUniqueId();
1200 UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1201 Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
1202 .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1203 log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1204 if (createRelation.isRight()) {
1205 return Either.right(createRelation.right().value());
1208 return Either.left(createDataTypeResult.left().value());
1211 private Either<GraphRelation, JanusGraphOperationStatus> addDataTypeToModel(final DataTypeDefinition dataTypeDefinition) {
1212 final String model = dataTypeDefinition.getModel();
1213 if (model == null) {
1214 return Either.left(null);
1216 final GraphNode from = new UniqueIdData(NodeTypeEnum.Model, UniqueIdBuilder.buildModelUid(model));
1217 final GraphNode to = new UniqueIdData(NodeTypeEnum.DataType, dataTypeDefinition.getUniqueId());
1218 log.info("Connecting model {} to type {}", from, to);
1219 return janusGraphGenericDao.createRelation(from, to, GraphEdgeLabels.MODEL_ELEMENT, Collections.emptyMap());
1222 private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1223 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1224 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1225 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1226 if (creationDate == null) {
1227 creationDate = System.currentTimeMillis();
1229 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1230 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1231 return dataTypeData;
1235 * add properties to capability type.
1237 * Per property, add a property node and associate it to the capability type
1243 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType(final String uniqueId, final String modelName,
1244 final List<PropertyDefinition> properties) {
1245 Map<String, PropertyData> propertiesData = new HashMap<>();
1246 if (properties != null && !properties.isEmpty()) {
1247 for (PropertyDefinition propertyDefinition : properties) {
1248 String propertyName = propertyDefinition.getName();
1249 String propertyType = propertyDefinition.getType();
1250 Either<Boolean, JanusGraphOperationStatus> validPropertyType = isValidPropertyType(propertyType, modelName);
1251 if (validPropertyType.isRight()) {
1252 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1253 return Either.right(validPropertyType.right().value());
1255 Boolean isValid = validPropertyType.left().value();
1256 if (isValid == null || !isValid.booleanValue()) {
1257 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1258 return Either.right(JanusGraphOperationStatus.INVALID_TYPE);
1260 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1261 .addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1262 if (addPropertyToNodeType.isRight()) {
1263 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1264 log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1265 BeEcompErrorManager.getInstance()
1266 .logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus,
1267 ErrorSeverity.ERROR);
1268 return Either.right(operationStatus);
1270 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1272 DataTypeData dataTypeData = new DataTypeData();
1273 dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1274 long modificationTime = System.currentTimeMillis();
1275 dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1276 Either<DataTypeData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao.updateNode(dataTypeData, DataTypeData.class);
1277 if (updateNode.isRight()) {
1278 JanusGraphOperationStatus operationStatus = updateNode.right().value();
1279 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1280 BeEcompErrorManager.getInstance()
1281 .logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1282 return Either.right(operationStatus);
1284 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1287 return Either.left(propertiesData);
1290 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByNameValidForModel(final String name, final String modelName) {
1291 final Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1292 .getNode(GraphPropertiesDictionary.NAME.getProperty(), name, DataTypeData.class, modelName);
1293 if (dataTypesRes.isRight()) {
1294 final JanusGraphOperationStatus status = dataTypesRes.right().value();
1295 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, name, status);
1296 return Either.right(status);
1298 final DataTypeData dataType = dataTypesRes.left().value();
1299 final DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(dataType.getDataTypeDataDefinition());
1300 final JanusGraphOperationStatus propertiesStatus = fillProperties(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1301 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1302 log.error(BUSINESS_PROCESS_ERROR, FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, dataTypeDefinition.getUniqueId());
1303 return Either.right(propertiesStatus);
1305 final Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1306 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeDefinition.getUniqueId(), GraphEdgeLabels.DERIVED_FROM,
1307 NodeTypeEnum.DataType,
1308 DataTypeData.class);
1309 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, dataTypeDefinition.getUniqueId(), parentNode);
1310 if (parentNode.isRight()) {
1311 final JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1312 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1313 log.error(BUSINESS_PROCESS_ERROR, "Failed to find the parent data type of data type {}. status is {}",
1314 dataTypeDefinition.getUniqueId(), janusGraphOperationStatus);
1315 return Either.right(janusGraphOperationStatus);
1318 // derived from node was found
1319 final ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1320 final DataTypeData parentDataType = immutablePair.getKey();
1321 final Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentDataType.getUniqueId());
1322 if (dataTypeByUid.isRight()) {
1323 return Either.right(dataTypeByUid.right().value());
1325 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1326 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1328 return Either.left(dataTypeDefinition);
1332 * Build Data type object from graph by unique id
1337 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUid(String uniqueId) {
1338 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1339 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1340 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1341 if (dataTypesRes.isRight()) {
1342 JanusGraphOperationStatus status = dataTypesRes.right().value();
1343 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1344 return Either.right(status);
1346 DataTypeData ctData = dataTypesRes.left().value();
1347 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1348 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1349 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1350 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1351 return Either.right(propertiesStatus);
1353 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1354 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1355 DataTypeData.class);
1356 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1357 if (parentNode.isRight()) {
1358 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1359 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1360 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1361 result = Either.right(janusGraphOperationStatus);
1365 // derived from node was found
1366 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1367 DataTypeData parentCT = immutablePair.getKey();
1368 String parentUniqueId = parentCT.getUniqueId();
1369 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1370 if (dataTypeByUid.isRight()) {
1371 return Either.right(dataTypeByUid.right().value());
1373 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1374 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1376 result = Either.left(dataTypeDefinition);
1380 private JanusGraphOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1381 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this
1382 .findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1383 if (findPropertiesOfNode.isRight()) {
1384 JanusGraphOperationStatus janusGraphOperationStatus = findPropertiesOfNode.right().value();
1385 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, janusGraphOperationStatus);
1386 if (JanusGraphOperationStatus.NOT_FOUND.equals(janusGraphOperationStatus)) {
1387 return JanusGraphOperationStatus.OK;
1389 return janusGraphOperationStatus;
1392 Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1393 if (properties != null && !properties.isEmpty()) {
1394 List<PropertyDefinition> listOfProps = new ArrayList<>();
1395 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1396 String propName = entry.getKey();
1397 PropertyDefinition propertyDefinition = entry.getValue();
1398 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1399 newPropertyDefinition.setName(propName);
1400 listOfProps.add(newPropertyDefinition);
1402 dataTypeDefinition.setProperties(listOfProps);
1404 return JanusGraphOperationStatus.OK;
1408 private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1409 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1411 Either<DataTypeData, JanusGraphOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1412 if (eitherStatus.isRight()) {
1413 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1414 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1415 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1418 DataTypeData capabilityTypeData = eitherStatus.left().value();
1419 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1420 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1421 result = Either.left(dataTypeDefResult);
1425 if (!inTransaction) {
1426 if (result == null || result.isRight()) {
1427 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1428 janusGraphGenericDao.rollback();
1430 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1431 janusGraphGenericDao.commit();
1438 public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1439 return addDataType(dataTypeDefinition, true);
1443 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel,
1444 final boolean inTransaction) {
1445 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1447 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByNameValidForModel(name, validForModel);
1448 if (ctResult.isRight()) {
1449 JanusGraphOperationStatus status = ctResult.right().value();
1450 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1451 log.error("Failed to retrieve information on capability type {} status is {}", name, 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();
1472 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel) {
1473 return getDataTypeByName(name, validForModel, true);
1476 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByUidWithoutDerived(String uid, boolean inTransaction) {
1477 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1479 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1480 if (ctResult.isRight()) {
1481 JanusGraphOperationStatus status = ctResult.right().value();
1482 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1483 log.error(BUSINESS_PROCESS_ERROR, "Failed to retrieve information on data type {} status is {}", uid, status);
1485 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1488 result = Either.left(ctResult.left().value());
1491 if (!inTransaction) {
1492 if (result == null || result.isRight()) {
1493 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1494 janusGraphGenericDao.rollback();
1496 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1497 janusGraphGenericDao.commit();
1503 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1504 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1505 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1506 if (dataTypesRes.isRight()) {
1507 JanusGraphOperationStatus status = dataTypesRes.right().value();
1508 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1509 return Either.right(status);
1511 DataTypeData ctData = dataTypesRes.left().value();
1512 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1513 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1514 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1515 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1516 return Either.right(propertiesStatus);
1518 return Either.left(dataTypeDefinition);
1522 * convert between graph Node object to Java object
1524 * @param dataTypeData
1527 protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1528 log.debug("The object returned after create data type is {}", dataTypeData);
1529 return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1532 private Either<Boolean, JanusGraphOperationStatus> isValidPropertyType(String propertyType, final String modelName) {
1533 if (propertyType == null || propertyType.isEmpty()) {
1534 return Either.left(false);
1536 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1537 if (toscaPropertyType == null) {
1538 return isDefinedInDataTypes(propertyType, modelName);
1540 return Either.left(true);
1544 public Either<Boolean, JanusGraphOperationStatus> isDefinedInDataTypes(final String propertyType, final String modelName) {
1545 Either<DataTypeDefinition, JanusGraphOperationStatus> dataType = getDataTypeByNameValidForModel(propertyType, modelName);
1546 if (dataType.isRight()) {
1547 JanusGraphOperationStatus status = dataType.right().value();
1548 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1549 return Either.left(false);
1551 return Either.right(status);
1553 return Either.left(true);
1556 public Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> getAllDataTypes() {
1557 final Map<String, Map<String, DataTypeDefinition>> dataTypes = new HashMap<>();
1558 Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> result = Either.left(dataTypes);
1559 final Map<String, DataTypeDefinition> allDataTypesFound = new HashMap<>();
1561 final Map<String, List<String>> dataTypeUidstoModels = dataTypeOperation.getAllDataTypeUidsToModels();
1563 if (dataTypeUidstoModels != null) {
1564 log.trace("Number of data types to load is {}", dataTypeUidstoModels.size());
1565 for (Map.Entry<String, List<String>> entry : dataTypeUidstoModels.entrySet()) {
1566 log.trace("Going to fetch data type with uid {}", entry.getKey());
1567 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this
1568 .getAndAddDataTypeByUid(entry.getKey(), allDataTypesFound);
1569 if (dataTypeByUid.isRight()) {
1570 JanusGraphOperationStatus status = dataTypeByUid.right().value();
1571 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1572 status = JanusGraphOperationStatus.INVALID_ID;
1574 return Either.right(status);
1576 for (final String model : entry.getValue()) {
1577 if (!dataTypes.containsKey(model)) {
1578 dataTypes.put(model, new HashMap<String, DataTypeDefinition>());
1580 DataTypeDefinition dataTypeDefinition = allDataTypesFound.get(entry.getKey());
1581 dataTypes.get(model).put(dataTypeDefinition.getName(), dataTypeDefinition);
1586 if (log.isTraceEnabled()) {
1587 if (result.isRight()) {
1588 log.trace("After fetching all data types {}", result);
1590 Map<String, Map<String, DataTypeDefinition>> map = result.left().value();
1592 String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1593 log.trace("After fetching all data types {} ", types);
1601 * Build Data type object from graph by unique id
1606 private Either<DataTypeDefinition, JanusGraphOperationStatus> getAndAddDataTypeByUid(String uniqueId,
1607 Map<String, DataTypeDefinition> allDataTypes) {
1608 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1609 if (allDataTypes.containsKey(uniqueId)) {
1610 return Either.left(allDataTypes.get(uniqueId));
1612 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1613 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1614 if (dataTypesRes.isRight()) {
1615 JanusGraphOperationStatus status = dataTypesRes.right().value();
1616 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1617 return Either.right(status);
1619 DataTypeData ctData = dataTypesRes.left().value();
1620 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1621 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1622 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1623 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1624 return Either.right(propertiesStatus);
1626 allDataTypes.put(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1627 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1628 if (allDataTypes.containsKey(derivedFrom)) {
1629 DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1630 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1631 return Either.left(dataTypeDefinition);
1633 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1634 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1635 DataTypeData.class);
1636 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1637 if (parentNode.isRight()) {
1638 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1639 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1640 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1641 result = Either.right(janusGraphOperationStatus);
1645 // derived from node was found
1646 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1647 DataTypeData parentCT = immutablePair.getKey();
1648 String parentUniqueId = parentCT.getUniqueId();
1649 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1650 if (dataTypeByUid.isRight()) {
1651 return Either.right(dataTypeByUid.right().value());
1653 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1654 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1655 final var model = getModel(uniqueId);
1656 if (StringUtils.isNotEmpty(model)) {
1657 dataTypeDefinition.setModel(model);
1660 result = Either.left(dataTypeDefinition);
1664 private String getModel(final String uniqueId) {
1665 final Either<ImmutablePair<ModelData, GraphEdge>, JanusGraphOperationStatus> model = janusGraphGenericDao.getParentNode(
1666 UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.MODEL_ELEMENT,
1667 NodeTypeEnum.Model, ModelData.class);
1668 return model.isLeft() ? model.left().value().getLeft().getName() : StringUtils.EMPTY;
1671 public Either<String, JanusGraphOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
1672 String propertyType = propDataDef.getType();
1673 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
1674 return getInnerType(type, propDataDef::getSchema);
1677 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType,
1678 Map<String, DataTypeDefinition> dataTypes) {
1679 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
1680 final ToscaPropertyType type = getType(propertyType);
1683 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
1684 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter
1685 .validateAndUpdate(value, dataTypeDefinition, dataTypes);
1686 if (Boolean.FALSE.equals(validateResult.right)) {
1687 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
1688 return Either.right(false);
1690 JsonElement jsonElement = validateResult.left;
1691 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
1692 return Either.left(valueFromJsonElement);
1694 log.trace("before validating property type {}", propertyType);
1695 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
1696 if (!isValidProperty) {
1697 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
1698 return Either.right(false);
1701 Object convertedValue = value;
1702 if (!isEmptyValue(value) && isValidate) {
1703 PropertyValueConverter converter = type.getConverter();
1704 convertedValue = converter.convert(value, innerType, dataTypes);
1706 return Either.left(convertedValue);
1709 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType,
1710 Map<String, DataTypeDefinition> dataTypes) {
1711 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
1714 public Either<Object, Boolean> validateAndUpdatePropertyValue(final Component containerComponent, final PropertyDataDefinition property,
1715 final Map<String, DataTypeDefinition> dataTypes) {
1716 if (property.isToscaFunction()) {
1717 toscaFunctionValidator.validate(property, containerComponent);
1718 property.setValue(property.getToscaFunction().getValue());
1719 return Either.left(property.getValue());
1721 Either<String, JanusGraphOperationStatus> checkInnerType = checkInnerType(property);
1722 if (checkInnerType.isRight()) {
1723 return Either.right(false);
1725 final String innerType = checkInnerType.left().value();
1726 return validateAndUpdatePropertyValue(property.getType(), property.getValue(), true, innerType, dataTypes);
1729 public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType,
1731 return this.findPropertiesOfNode(nodeType, uniqueId).right().bind(this::handleNotFoundProperties).left()
1732 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
1735 private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(
1736 JanusGraphOperationStatus janusGraphOperationStatus) {
1737 if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
1738 return Either.left(new HashMap<>());
1740 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1743 private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId,
1744 NodeTypeEnum nodeType,
1746 Collection<PropertyDefinition> nodeProps) {
1747 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
1748 String currentNodeUid = uniqueId;
1749 Either<T, StorageOperationStatus> derivedFrom;
1750 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
1751 currentNodeUid = derivedFrom.left().value().getUniqueId();
1752 JanusGraphOperationStatus janusGraphOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
1753 if (janusGraphOperationStatus != JanusGraphOperationStatus.OK) {
1754 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
1755 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1758 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
1759 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
1762 private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
1763 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
1767 * @Override public PropertyOperation getPropertyOperation() { return this; }
1769 public JanusGraphOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
1770 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
1771 if (findPropertiesRes.isRight()) {
1772 return findPropertiesRes.right().value();
1774 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
1775 if (properties != null) {
1776 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
1777 propertySetter.accept(propertiesAsList);
1779 return JanusGraphOperationStatus.OK;
1782 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType) {
1783 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
1784 if (findPropertiesOfNode.isRight()) {
1785 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
1786 if (findPropertiesOfNode.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
1787 return Either.left(Maps.newHashMap());
1789 return findPropertiesOfNode;
1791 return findPropertiesOfNode;
1795 * add properties to element type.
1797 * Per property, add a property node and associate it to the element type
1800 * @param propertiesMap
1803 protected Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType,
1804 Map<String, PropertyDefinition> propertiesMap) {
1805 Map<String, PropertyData> propertiesData = new HashMap<>();
1806 if (propertiesMap != null) {
1807 for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
1808 String propertyName = propertyDefinitionEntry.getKey();
1809 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1810 .addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
1811 if (addPropertyToNodeType.isRight()) {
1812 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1813 log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName,
1815 return Either.right(operationStatus);
1817 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1820 return Either.left(propertiesData);
1823 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType,
1824 List<PropertyDefinition> properties) {
1825 Map<String, PropertyDefinition> propMap;
1826 if (properties == null) {
1829 propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
1831 return addPropertiesToElementType(uniqueId, elementType, propMap);
1835 public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1836 DataTypeDefinition oldDataTypeDefinition) {
1837 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
1840 private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1841 DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
1842 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1844 List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
1845 List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
1846 String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
1847 String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
1848 String dataTypeName = newDataTypeDefinition.getName();
1849 List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
1850 if (isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, propertiesToAdd)
1851 || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
1852 log.debug("The new data type {} is invalid.", dataTypeName);
1853 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
1856 if (CollectionUtils.isEmpty(propertiesToAdd)) {
1857 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
1858 result = Either.right(StorageOperationStatus.OK);
1861 Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
1862 if (MapUtils.isNotEmpty(newDescriptions)) {
1863 JanusGraphOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(),
1865 if (updatePropertiesStatus != JanusGraphOperationStatus.OK) {
1866 log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}",
1867 oldDataTypeDefinition, updatePropertiesStatus);
1868 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1869 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatePropertiesStatus));
1873 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(
1874 oldDataTypeDefinition.getUniqueId(), oldDataTypeDefinition.getModel(), propertiesToAdd);
1875 if (addPropertiesToDataType.isRight()) {
1876 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition,
1877 addPropertiesToDataType.right().value().name());
1878 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1879 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToDataType.right().value()));
1882 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
1883 if (dataTypeByUid.isRight()) {
1884 JanusGraphOperationStatus status = addPropertiesToDataType.right().value();
1885 log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
1886 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
1887 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
1889 result = Either.left(dataTypeByUid.left().value());
1894 if (!inTransaction) {
1895 if (result == null || result.isRight()) {
1896 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1897 janusGraphGenericDao.rollback();
1899 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1900 janusGraphGenericDao.commit();
1906 private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties,
1907 List<PropertyDefinition> outputPropertiesToAdd) {
1908 if (newProperties != null && oldProperties != null) {
1909 Map<String, PropertyDefinition> newPropsMapper = newProperties.stream()
1910 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1911 Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream()
1912 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1913 for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
1914 String propName = newPropertyEntry.getKey();
1915 PropertyDefinition propDef = newPropertyEntry.getValue();
1916 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
1917 if (oldPropertyDefinition == null) {
1918 log.debug("New property {} received in the data type {}", propName, dataTypeName);
1919 outputPropertiesToAdd.add(propDef);
1922 String oldType = oldPropertyDefinition.getType();
1923 String oldEntryType = getEntryType(oldPropertyDefinition);
1924 String newType = propDef.getType();
1925 String newEntryType = getEntryType(propDef);
1926 if (!oldType.equals(newType)) {
1927 log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType,
1931 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
1932 log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName,
1933 oldEntryType, newEntryType);
1941 private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
1942 if (oldEntryType == null && newEntryType == null) {
1944 } else if (oldEntryType != null && newEntryType != null) {
1945 return oldEntryType.equals(newEntryType);
1951 private String getEntryType(PropertyDefinition oldPropertyDefinition) {
1952 String entryType = null;
1953 SchemaDefinition schema = oldPropertyDefinition.getSchema();
1954 if (schema != null) {
1955 PropertyDataDefinition schemaProperty = schema.getProperty();
1956 if (schemaProperty != null) {
1957 entryType = schemaProperty.getType();
1963 private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
1964 if (newDerivedFromName != null) {
1965 boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
1967 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1968 oldDerivedFromName);
1971 } else if (oldDerivedFromName == null) {
1973 } else {// new=null, old != null
1974 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1975 oldDerivedFromName);
1985 public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
1986 Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
1987 if (graphResult.isRight()) {
1988 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
1990 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
1991 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
1992 if (vertexService.isRight()) {
1993 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
1994 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
1996 Vertex vertex = vertexService.left().value();
1997 VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
1998 Integer counter = 0;
1999 if (vertexProperty.isPresent() && vertexProperty.value() != null) {
2000 counter = (Integer) vertexProperty.value();
2003 vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
2004 return Either.left(counter);
2007 public Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesUniqueness(
2008 Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
2009 Either<List<PropertyDefinition>, JanusGraphOperationStatus> result = Either.left(properties);
2010 for (PropertyDefinition property : properties) {
2011 JanusGraphOperationStatus status = validatePropertyUniqueness(inheritedProperties, property);
2012 if (status != JanusGraphOperationStatus.OK) {
2013 result = Either.right(status);
2021 * Validates uniqueness of examined property by comparing it with properties in propertiesOfType and updates if need type and inner type of the
2024 private JanusGraphOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2025 String propertyName = property.getName();
2026 String propertyType = property.getType();
2027 JanusGraphOperationStatus result = JanusGraphOperationStatus.OK;
2028 if (inheritedProperties.containsKey(propertyName)) {
2029 PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2030 if (typesMismatch(propertyType, defaultProperty.getType())) {
2031 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2032 result = JanusGraphOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2034 property.setType(defaultProperty.getType());
2035 String innerType = defaultProperty.getSchemaType();
2036 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2037 if (schemaProperty != null) {
2038 schemaProperty.setType(innerType);
2045 private boolean typesMismatch(String type1, String type2) {
2046 return type1 != null && type2 != null && !type2.equals(type1);
2049 public <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllTypePropertiesFromAllDerivedFrom(
2050 String nextParentUid, NodeTypeEnum nodeType, Class<T> clazz) {
2051 Map<String, PropertyDefinition> allProperies = new HashMap<>();
2052 return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2055 private <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getTypePropertiesFromDerivedFromRecursively(
2056 String nextParentUid, Map<String, PropertyDefinition> allProperies, NodeTypeEnum nodeType, Class<T> clazz) {
2057 JanusGraphOperationStatus error;
2058 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
2059 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2060 if (childrenNodes.isRight()) {
2061 if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
2062 error = childrenNodes.right().value();
2063 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid,
2065 return Either.right(error);
2067 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.",
2069 return Either.left(allProperies);
2072 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2073 if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
2074 error = allPropertiesOfTypeRes.right().value();
2076 "#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}",
2077 nextParentUid, error);
2078 return Either.right(error);
2079 } else if (allPropertiesOfTypeRes.isLeft()) {
2080 if (allProperies.isEmpty()) {
2081 allProperies.putAll(allPropertiesOfTypeRes.left().value());
2083 allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey()))
2084 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2087 return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType,
2092 private JanusGraphOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2093 if (MapUtils.isNotEmpty(newDescriptions)) {
2094 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getDataTypePropertiesRes = janusGraphGenericDao
2095 .getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2096 if (getDataTypePropertiesRes.isRight()) {
2097 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2098 return getDataTypePropertiesRes.right().value();
2100 getDataTypePropertiesRes.left().value().stream().filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2101 .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2103 return JanusGraphOperationStatus.OK;
2106 private JanusGraphVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<JanusGraphVertex, Edge> pair) {
2107 return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2110 private String getPropertyNameFromEdge(ImmutablePair<JanusGraphVertex, Edge> pair) {
2111 return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2114 private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2115 Map<String, PropertyDefinition> newPropertiesMap = newProperties.stream().collect(Collectors.toMap(PropertyDefinition::getName, p -> p));
2116 return oldProperties.stream()
2117 .filter(p -> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2118 .collect(Collectors.toMap(PropertyDefinition::getName, p -> newPropertiesMap.get(p.getName()).getDescription()));
2121 private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty) {
2122 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2125 if (StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2128 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())) {
2131 return property.getDescription().equals(otherProperty.getDescription());
2134 public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
2137 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
2138 JsonObject result = new JsonObject();
2139 JsonArray jsonArray = new JsonArray();
2140 if (src instanceof InRangeConstraint) {
2141 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
2142 jsonArray.add(JsonParser.parseString(String.valueOf(rangeConstraint.getRangeMinValue())));
2143 jsonArray.add(JsonParser.parseString(String.valueOf(rangeConstraint.getRangeMaxValue())));
2144 result.add("inRange", jsonArray);
2145 } else if (src instanceof GreaterThanConstraint) {
2146 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
2147 jsonArray.add(JsonParser.parseString(String.valueOf(greaterThanConstraint.getGreaterThan())));
2148 result.add("greaterThan", jsonArray);
2149 } else if (src instanceof LessThanConstraint) {
2150 LessThanConstraint lessThanConstraint = (LessThanConstraint) src;
2151 jsonArray.add(JsonParser.parseString(String.valueOf(lessThanConstraint.getLessThan())));
2152 result.add("lessThan", jsonArray);
2153 } else if (src instanceof LessOrEqualConstraint) {
2154 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
2155 jsonArray.add(JsonParser.parseString(String.valueOf(lessOrEqualConstraint.getLessOrEqual())));
2156 result.add("lessOrEqual", jsonArray);
2158 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
2164 public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
2166 private static final String THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL = "The value of GreaterThanConstraint is null";
2169 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
2170 PropertyConstraint propertyConstraint = null;
2171 final Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
2172 if (!set.isEmpty()) {
2173 final Entry<String, JsonElement> element = set.iterator().next();
2174 final String key = element.getKey();
2175 final ConstraintType constraintType = ConstraintType.findByType(key).orElse(null);
2176 if (constraintType == null) {
2177 log.warn("ConstraintType was not found for constraint name:{}", key);
2179 if (set.size() == 1 || (set.size() == 2 && ConstraintType.PATTERN == constraintType)) {
2180 final JsonElement value = element.getValue();
2181 final Object typedValue = getTypedValue(value);
2182 switch (constraintType) {
2184 if (typedValue != null) {
2185 log.debug("Before adding value to EqualConstraint object. value = {}", typedValue);
2186 propertyConstraint = new EqualConstraint(typedValue);
2189 log.warn("The value of equal constraint is null");
2193 if (typedValue != null) {
2194 if (typedValue instanceof ArrayList) {
2195 ArrayList rangeArray = (ArrayList) typedValue;
2196 if (rangeArray.size() != 2 || rangeArray.contains("")) {
2197 log.error("The range constraint content is invalid. value = {}", typedValue);
2198 throw new JsonSyntaxException("The range constraint content is invalid");
2200 InRangeConstraint rangeConstraint = new InRangeConstraint();
2201 Object minValue = rangeArray.get(0);
2202 Object maxValue = rangeArray.get(1);
2203 rangeConstraint.setRangeMinValue(minValue);
2204 rangeConstraint.setRangeMaxValue(maxValue);
2205 propertyConstraint = rangeConstraint;
2209 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2213 if (typedValue != null) {
2214 log.debug("Before adding value to GreaterThanConstraint object. value = {}", typedValue);
2215 propertyConstraint = new GreaterThanConstraint(typedValue);
2218 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2222 if (typedValue != null) {
2223 log.debug("Before adding value to LessThanConstraint object. value = {}", typedValue);
2224 propertyConstraint = new LessThanConstraint(typedValue);
2227 log.warn("The value of LessThanConstraint is null");
2230 case GREATER_OR_EQUAL:
2231 if (typedValue != null) {
2232 log.debug("Before adding value to GreaterThanConstraint object. value = {}", typedValue);
2233 propertyConstraint = new GreaterOrEqualConstraint(typedValue);
2236 log.warn("The value of GreaterOrEqualConstraint is null");
2240 if (typedValue != null) {
2241 log.debug("Before adding value to LessOrEqualConstraint object. value = {}", typedValue);
2242 propertyConstraint = new LessOrEqualConstraint(typedValue);
2244 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2248 if (typedValue != null) {
2249 ArrayList validValuesArray = (ArrayList) typedValue;
2250 if (validValuesArray.size() == 0 || validValuesArray.contains("")) {
2251 log.error("The valid values constraint content is invalid. value = {}", typedValue);
2252 throw new JsonSyntaxException("The valid values constraint content is invalid");
2254 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2255 vvConstraint.setValidValues(validValuesArray);
2256 propertyConstraint = vvConstraint;
2261 if (value != null) {
2262 int asInt = value.getAsInt();
2263 log.debug("Before adding value to length constraint. value = {}", asInt);
2264 propertyConstraint = new LengthConstraint(asInt);
2267 log.warn("The value of length constraint is null");
2271 if (value != null) {
2272 int asInt = value.getAsInt();
2273 log.debug("Before adding value to Min Length object. value = {}", asInt);
2274 propertyConstraint = new MinLengthConstraint(asInt);
2277 log.warn("The value of MinLengthConstraint is null");
2281 if (value != null) {
2282 int asInt = value.getAsInt();
2283 log.debug("Before adding value to max length constraint. value = {}", asInt);
2284 propertyConstraint = new MaxLengthConstraint(asInt);
2287 log.warn("The value of max length constraint is null");
2291 if (value != null) {
2292 String asString = value.getAsString();
2293 log.debug("Before adding value to PatternConstraint object. value = {}", asString);
2294 propertyConstraint = new PatternConstraint(asString);
2297 log.warn("The value of pattern constraint is null");
2301 log.warn("Key {} is not supported. Ignored.", key);
2306 return propertyConstraint;
2309 private Object getTypedValue(JsonElement je) {
2310 if (je == null || je.isJsonNull()) {
2313 if (je.isJsonPrimitive()) {
2314 return getJsonPrimitive(je.getAsJsonPrimitive());
2316 if (je.isJsonArray()) {
2317 ArrayList<Object> array = new ArrayList<>();
2318 for (JsonElement e : je.getAsJsonArray()) {
2319 array.add(getJsonPrimitive(e.getAsJsonPrimitive()));
2326 private Object getJsonPrimitive(JsonPrimitive je) {
2327 if (je.isBoolean()) {
2328 return je.getAsBoolean();
2330 if (je.isString()) {
2331 return je.getAsString();
2333 if (je.isNumber()) {
2334 double number = je.getAsNumber().floatValue();
2335 if ((number % 1) == 0) {
2336 return je.getAsNumber().intValue();
2344 public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
2347 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
2348 ObjectCodec oc = json.getCodec();
2349 JsonNode node = oc.readTree(json);
2350 PropertyConstraint propertyConstraint = null;
2352 Iterator<Entry<String, JsonNode>> fieldsIterator = node.fields();
2353 while (fieldsIterator.hasNext()) {
2354 Entry<String, JsonNode> field = fieldsIterator.next();
2355 ConstraintType constraintType = ConstraintType.findByType(field.getKey()).orElse(null);
2356 JsonNode value = field.getValue();
2358 if (constraintType == null) {
2359 log.warn("ConstraintType was not found for constraint name:{}", field.getKey());
2361 if (value == null) {
2362 log.warn("The value of {} constraint is null", constraintType);
2364 switch (constraintType) {
2366 propertyConstraint = deserializeConstraintWithStringOperand(value, EqualConstraint.class);
2369 propertyConstraint = deserializeInRangeConstraintConstraint(value);
2372 propertyConstraint = deserializeConstraintWithStringOperand(value, GreaterThanConstraint.class);
2375 propertyConstraint = deserializeConstraintWithStringOperand(value, LessThanConstraint.class);
2377 case GREATER_OR_EQUAL:
2378 propertyConstraint = deserializeConstraintWithStringOperand(value, GreaterOrEqualConstraint.class);
2381 propertyConstraint = deserializeConstraintWithStringOperand(value, LessOrEqualConstraint.class);
2384 propertyConstraint = deserializeValidValuesConstraint(value);
2387 propertyConstraint = deserializeConstraintWithIntegerOperand(value, LengthConstraint.class);
2390 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MinLengthConstraint.class);
2393 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MaxLengthConstraint.class);
2396 propertyConstraint = deserializeConstraintWithStringPatternOperand(value, PatternConstraint.class);
2399 log.warn("Key {} is not supported. Ignored.", field.getKey());
2405 return propertyConstraint;
2408 private PropertyConstraint deserializeConstraintWithStringOperand(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2409 String asString = value.asText();
2410 log.debug("Before adding value to {} object. value = {}", constraintClass, asString);
2412 return constraintClass.getConstructor(Object.class).newInstance(asString);
2413 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2414 | SecurityException exception) {
2415 log.error("Error deserializing constraint", exception);
2420 private PropertyConstraint deserializeConstraintWithStringPatternOperand(JsonNode value,
2421 Class<? extends PropertyConstraint> constraintClass) {
2422 String asString = value.asText();
2423 log.debug("Before adding value to {} object. value = {}", constraintClass, asString);
2425 return constraintClass.getConstructor(String.class).newInstance(asString);
2426 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2427 | SecurityException exception) {
2428 log.error("Error deserializing constraint", exception);
2433 private PropertyConstraint deserializeConstraintWithIntegerOperand(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2434 Integer asInt = value.asInt();
2435 log.debug("Before adding value to {} object. value = {}", constraintClass, asInt);
2437 return constraintClass.getConstructor(Integer.class).newInstance(asInt);
2438 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2439 | SecurityException exception) {
2440 log.error("Error deserializing constraint", exception);
2445 private PropertyConstraint deserializeInRangeConstraintConstraint(JsonNode value) {
2446 if (value instanceof ArrayNode) {
2447 ArrayNode rangeArray = (ArrayNode) value;
2448 if (rangeArray.size() != 2) {
2449 log.error("The range constraint content is invalid. value = {}", value);
2451 InRangeConstraint rangeConstraint = new InRangeConstraint();
2452 String minValue = rangeArray.get(0).asText();
2454 JsonNode maxElement = rangeArray.get(1);
2455 if (maxElement.isNull()) {
2458 maxValue = maxElement.asText();
2460 rangeConstraint.setRangeMinValue(minValue);
2461 rangeConstraint.setRangeMaxValue(maxValue);
2462 return rangeConstraint;
2468 private PropertyConstraint deserializeValidValuesConstraint(JsonNode value) {
2469 ArrayNode rangeArray = (ArrayNode) value;
2470 if (rangeArray.size() == 0) {
2471 log.error("The valid values constraint content is invalid. value = {}", value);
2473 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2474 List<Object> validValues = new ArrayList<>();
2475 for (JsonNode jsonElement : rangeArray) {
2476 String item = jsonElement.asText();
2477 validValues.add(item);
2479 vvConstraint.setValidValues(validValues);
2480 return vvConstraint;