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.JsonSerializationContext;
37 import com.google.gson.JsonSerializer;
38 import fj.data.Either;
39 import java.io.IOException;
40 import java.lang.reflect.InvocationTargetException;
41 import java.lang.reflect.Type;
42 import java.util.ArrayList;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.HashMap;
46 import java.util.Iterator;
47 import java.util.List;
49 import java.util.Map.Entry;
51 import java.util.function.Consumer;
52 import java.util.regex.Matcher;
53 import java.util.regex.Pattern;
54 import java.util.stream.Collectors;
55 import org.apache.commons.collections.CollectionUtils;
56 import org.apache.commons.collections.MapUtils;
57 import org.apache.commons.lang3.StringUtils;
58 import org.apache.commons.lang3.tuple.ImmutablePair;
59 import org.apache.tinkerpop.gremlin.structure.Edge;
60 import org.apache.tinkerpop.gremlin.structure.Vertex;
61 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
62 import org.janusgraph.core.JanusGraph;
63 import org.janusgraph.core.JanusGraphVertex;
64 import org.janusgraph.core.JanusGraphVertexProperty;
65 import org.openecomp.sdc.be.config.BeEcompErrorManager;
66 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
67 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
68 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
69 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
70 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
71 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
72 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
73 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
74 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
75 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
76 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
77 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
78 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
79 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
80 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
81 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
82 import org.openecomp.sdc.be.model.Component;
83 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
84 import org.openecomp.sdc.be.model.DataTypeDefinition;
85 import org.openecomp.sdc.be.model.IComplexDefaultValue;
86 import org.openecomp.sdc.be.model.PropertyConstraint;
87 import org.openecomp.sdc.be.model.PropertyDefinition;
88 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
89 import org.openecomp.sdc.be.model.operations.api.IPropertyOperation;
90 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
91 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
92 import org.openecomp.sdc.be.model.tosca.constraints.EqualConstraint;
93 import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint;
94 import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
95 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
96 import org.openecomp.sdc.be.model.tosca.constraints.LengthConstraint;
97 import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
98 import org.openecomp.sdc.be.model.tosca.constraints.LessThanConstraint;
99 import org.openecomp.sdc.be.model.tosca.constraints.MaxLengthConstraint;
100 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
101 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
102 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
103 import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator;
104 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
105 import org.openecomp.sdc.be.resources.data.DataTypeData;
106 import org.openecomp.sdc.be.resources.data.ModelData;
107 import org.openecomp.sdc.be.resources.data.PropertyData;
108 import org.openecomp.sdc.be.resources.data.PropertyValueData;
109 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
110 import org.openecomp.sdc.be.resources.data.UniqueIdData;
111 import org.openecomp.sdc.common.log.wrappers.Logger;
112 import org.springframework.beans.factory.annotation.Autowired;
114 @org.springframework.stereotype.Component("property-operation")
115 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
117 private static final String AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS = "After retrieving DERIVED_FROM node of {}. status is {}";
118 private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
119 private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
120 private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
121 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
122 private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS = "Failed to associate resource {} to property {} in graph. status is {}";
123 private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
124 private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
125 private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
126 private static final String PROPERTY = "Property";
127 private static final String UPDATE_DATA_TYPE = "UpdateDataType";
128 private static final Logger log = Logger.getLogger(PropertyOperation.class.getName());
129 private final DerivedFromOperation derivedFromOperation;
130 private ToscaFunctionValidator toscaFunctionValidator;
131 private DataTypeOperation dataTypeOperation;
134 public PropertyOperation(final HealingJanusGraphGenericDao janusGraphGenericDao, final DerivedFromOperation derivedFromOperation) {
135 this.janusGraphGenericDao = janusGraphGenericDao;
136 this.derivedFromOperation = derivedFromOperation;
140 public void setToscaFunctionValidator(final ToscaFunctionValidator toscaFunctionValidator) {
141 this.toscaFunctionValidator = toscaFunctionValidator;
144 //circular dependency DataTypeOperation->ModelOperation->ModelElementOperation->PropertyOperation
146 public void setDataTypeOperation(DataTypeOperation dataTypeOperation) {
147 this.dataTypeOperation = dataTypeOperation;
150 public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
151 log.debug("The object returned after create property is {}", propertyDataResult);
152 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
153 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
154 propertyDefResult.setName(propertyName);
155 return propertyDefResult;
158 public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
159 Either<PropertyData, JanusGraphOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
160 if (either.isRight()) {
161 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
162 return Either.right(storageStatus);
164 return Either.left(either.left().value());
168 * @param propertyDefinition
172 public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
173 log.trace("Going to validate property type and value. {}", propertyDefinition);
174 String propertyType = propertyDefinition.getType();
175 String value = propertyDefinition.getDefaultValue();
176 ToscaPropertyType type = getType(propertyType);
178 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
179 if (dataTypeDefinition == null) {
180 log.debug("The type {} of property cannot be found.", propertyType);
181 return StorageOperationStatus.INVALID_TYPE;
183 return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
185 String innerType = null;
186 Either<String, JanusGraphOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
187 if (checkInnerType.isRight()) {
188 return StorageOperationStatus.INVALID_TYPE;
190 innerType = checkInnerType.left().value();
191 log.trace("After validating property type {}", propertyType);
192 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
193 if (!isValidProperty) {
194 log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
195 return StorageOperationStatus.INVALID_VALUE;
197 PropertyValueConverter converter = type.getConverter();
198 if (isEmptyValue(value)) {
199 log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
200 propertyDefinition.setDefaultValue(EMPTY_VALUE);
201 } else if (!isEmptyValue(value)) {
202 String convertedValue = converter.convert(value, innerType, dataTypes);
203 propertyDefinition.setDefaultValue(convertedValue);
205 return StorageOperationStatus.OK;
208 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition,
210 ResourceMetadataData resourceData = new ResourceMetadataData();
211 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
212 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
213 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
214 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
215 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
216 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
217 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
218 if (createNodeResult.isRight()) {
219 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
220 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
221 return Either.right(operationStatus);
223 Map<String, Object> props = new HashMap<>();
224 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
225 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
226 .createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
227 if (createRelResult.isRight()) {
228 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
229 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
230 return Either.right(operationStatus);
232 return Either.left(createNodeResult.left().value());
235 public JanusGraphOperationStatus addPropertyToGraphByVertex(JanusGraphVertex metadataVertex, String propertyName,
236 PropertyDefinition propertyDefinition, String resourceId) {
237 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
238 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
239 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
240 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
241 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData);
242 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
243 if (createNodeResult.isRight()) {
244 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
245 log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
246 return operationStatus;
248 Map<String, Object> props = new HashMap<>();
249 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
250 JanusGraphVertex propertyVertex = createNodeResult.left().value();
251 JanusGraphOperationStatus createRelResult = janusGraphGenericDao.createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
252 if (!createRelResult.equals(JanusGraphOperationStatus.OK)) {
253 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
254 return createRelResult;
256 return createRelResult;
259 public JanusGraphGenericDao getJanusGraphGenericDao() {
260 return janusGraphGenericDao;
266 * @param janusGraphGenericDao
268 public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
269 this.janusGraphGenericDao = janusGraphGenericDao;
272 public Either<PropertyData, JanusGraphOperationStatus> deletePropertyFromGraph(String propertyId) {
273 log.debug("Before deleting property from graph {}", propertyId);
274 return janusGraphGenericDao.deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
277 public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition,
278 Map<String, DataTypeDefinition> dataTypes) {
279 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
280 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
281 return Either.right(validateAndUpdateProperty);
283 Either<PropertyData, JanusGraphOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
284 if (either.isRight()) {
285 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
286 return Either.right(storageStatus);
288 return Either.left(either.left().value());
291 public Either<PropertyData, JanusGraphOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
292 if (log.isDebugEnabled()) {
293 log.debug("Before updating property on graph {}", propertyId);
295 // get the original property data
296 Either<PropertyData, JanusGraphOperationStatus> statusProperty = janusGraphGenericDao
297 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
298 if (statusProperty.isRight()) {
299 log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
300 return Either.right(statusProperty.right().value());
302 PropertyData orgPropertyData = statusProperty.left().value();
303 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
304 // create new property data to update
305 PropertyData newPropertyData = new PropertyData();
306 newPropertyData.setPropertyDataDefinition(propertyDefinition);
307 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
308 // update the original property data with new values
309 if (orgPropertyDataDefinition.getDefaultValue() == null) {
310 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
312 if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
313 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
316 if (orgPropertyDataDefinition.getDescription() == null) {
317 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
319 if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
320 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
323 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
324 orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
326 if (newPropertyData.getConstraints() != null) {
327 orgPropertyData.setConstraints(newPropertyData.getConstraints());
329 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
330 return janusGraphGenericDao.updateNode(orgPropertyData, PropertyData.class);
333 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition,
334 NodeTypeEnum nodeType, String uniqueId) {
335 return addPropertyToNodeType(propertyName, propertyDefinition, nodeType, uniqueId, true);
338 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(final String propertyName,
339 final PropertyDefinition propertyDefinition,
340 final NodeTypeEnum nodeType, final String uniqueId,
341 final boolean inTransaction) {
342 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
343 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
344 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
345 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
346 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
347 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
348 if (createNodeResult.isRight()) {
349 if (!inTransaction) {
350 janusGraphGenericDao.rollback();
352 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
353 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
354 return Either.right(operationStatus);
356 Map<String, Object> props = new HashMap<>();
357 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
358 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
359 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
360 Either<GraphRelation, JanusGraphOperationStatus> createRelResult =
361 janusGraphGenericDao.createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
362 if (createRelResult.isRight()) {
363 if (!inTransaction) {
364 janusGraphGenericDao.rollback();
366 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
367 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
368 return Either.right(operationStatus);
370 if (!inTransaction) {
371 janusGraphGenericDao.commit();
373 return Either.left(createNodeResult.left().value());
376 public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
377 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
378 Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
379 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
381 if (childrenNodes.isRight()) {
382 JanusGraphOperationStatus operationStatus = childrenNodes.right().value();
383 return Either.right(operationStatus);
385 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
386 if (values != null) {
387 for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
388 GraphEdge edge = immutablePair.getValue();
389 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
390 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
391 PropertyData propertyData = immutablePair.getKey();
392 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
393 resourceProps.put(propertyName, propertyDefinition);
396 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
397 return Either.left(resourceProps);
400 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
401 return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId).right()
402 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
405 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
406 Map<String, PropertyDefinition> newProperties) {
407 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
408 Map<String, PropertyDefinition> reallyNewProperties;
409 Map<String, PropertyData> unchangedPropsData;
410 if (oldPropertiesRes.isRight()) {
411 JanusGraphOperationStatus err = oldPropertiesRes.right().value();
412 if (err == JanusGraphOperationStatus.NOT_FOUND) {
413 reallyNewProperties = newProperties;
414 unchangedPropsData = Collections.emptyMap();
416 return Either.right(err);
419 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
420 reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
421 for (Entry<String, PropertyDefinition> oldEntry : oldProperties.entrySet()) {
422 String key = oldEntry.getKey();
423 PropertyDefinition newPropDef = newProperties != null ? newProperties.get(key) : null;
424 PropertyDefinition oldPropDef = oldEntry.getValue();
425 JanusGraphOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
426 if (status != JanusGraphOperationStatus.OK) {
427 return Either.right(status);
430 unchangedPropsData = oldProperties.entrySet().stream()
431 .collect(Collectors.toMap(Entry::getKey, e -> new PropertyData(e.getValue(), null)));
433 // add other properties
434 return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
438 * @param newProperties
439 * @param oldProperties
442 private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties,
443 Map<String, PropertyDefinition> oldProperties) {
444 return newProperties != null ? newProperties.entrySet().stream().filter(entry -> !oldProperties.containsKey(entry.getKey()))
445 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)) : null;
452 private JanusGraphOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
453 if (!isUpdateAllowed(newPropDef, oldPropDef)) {
454 return JanusGraphOperationStatus.MATCH_NOT_FOUND;
456 if (isUpdateRequired(newPropDef, oldPropDef)) {
457 modifyOldPropByNewOne(newPropDef, oldPropDef);
458 List<PropertyConstraint> constraints = oldPropDef.getConstraints();
459 PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
460 Either<PropertyData, JanusGraphOperationStatus> updateResult = janusGraphGenericDao.updateNode(node, PropertyData.class);
461 if (updateResult.isRight()) {
462 return updateResult.right().value();
465 return JanusGraphOperationStatus.OK;
472 private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
473 if (newPropDef == null) {
474 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
477 // If the property type is missing it's something that we could want to fix
478 if (oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
479 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
486 * Update only fields which modification is permitted.
491 private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
492 oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
493 oldPropDef.setDescription(newPropDef.getDescription());
494 oldPropDef.setRequired(newPropDef.isRequired());
495 // Type is updated to fix possible null type issue in janusGraph DB
496 oldPropDef.setType(newPropDef.getType());
499 private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
500 return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) || !StringUtils
501 .equals(oldPropDef.getDescription(), newPropDef.getDescription()) || oldPropDef.isRequired() != newPropDef.isRequired();
505 * Adds newProperties and returns in case of success (left part of Either) map of all properties i. e. added ones and contained in
510 * @param newProperties
511 * @param unchangedPropsData
514 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId,
515 Map<String, PropertyDefinition> newProperties,
516 Map<String, PropertyData> unchangedPropsData) {
517 return addPropertiesToElementType(uniqueId, nodeType, newProperties).left().map(m -> {
518 m.putAll(unchangedPropsData);
523 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType,
525 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
526 if (propertiesOfNodeRes.isRight()) {
527 JanusGraphOperationStatus status = propertiesOfNodeRes.right().value();
528 if (status == JanusGraphOperationStatus.NOT_FOUND) {
529 return Either.right(StorageOperationStatus.OK);
531 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
533 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
534 for (PropertyDefinition propertyDefinition : value.values()) {
535 String propertyUid = propertyDefinition.getUniqueId();
536 Either<PropertyData, JanusGraphOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
537 if (deletePropertyRes.isRight()) {
538 log.error("Failed to delete property with id {}", propertyUid);
539 JanusGraphOperationStatus status = deletePropertyRes.right().value();
540 if (status == JanusGraphOperationStatus.NOT_FOUND) {
541 status = JanusGraphOperationStatus.INVALID_ID;
543 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
546 log.debug("The properties deleted from node {} are {}", uniqueId, value);
547 return Either.left(value);
551 * 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
552 * (including derived from hierarchy)
556 * @param propertyName
557 * @param propertyType
560 public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
561 boolean result = false;
562 if (!CollectionUtils.isEmpty(properties)) {
563 for (PropertyDefinition propertyDefinition : properties) {
564 if (propertyDefinition.getName().equals(propertyName) && (propertyDefinition.getParentUniqueId().equals(resourceUid)
565 || !propertyDefinition.getType().equals(propertyType))) {
574 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType,
575 Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
576 if (rules == null || rules.isEmpty()) {
577 return new ImmutablePair<>(null, true);
579 for (PropertyRule rule : rules) {
580 String value = rule.getValue();
581 Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
582 if (updateResult.isRight()) {
583 Boolean status = updateResult.right().value();
585 return new ImmutablePair<>(value, status);
588 String newValue = null;
589 Object object = updateResult.left().value();
590 if (object != null) {
591 newValue = object.toString();
593 rule.setValue(newValue);
596 return new ImmutablePair<>(null, true);
599 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
600 String resourceInstanceId) {
601 List<PropertyRule> rules = resourceInstanceProperty.getRules();
603 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
604 rules = new ArrayList<>();
605 rules.add(propertyRule);
607 rules = sortRules(rules);
609 propertyValueData.setRules(rules);
612 private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
613 String resourceInstanceId) {
614 List<String> path = resourceInstanceProperty.getPath();
615 // FOR BC. Since old Property values on VFC/VF does not have rules on
619 // Update could be done on one level only, thus we can use this
621 // operation to avoid migration.
622 if (path == null || path.isEmpty()) {
623 path = new ArrayList<>();
624 path.add(resourceInstanceId);
626 PropertyRule propertyRule = new PropertyRule();
627 propertyRule.setRule(path);
628 propertyRule.setValue(propertyValueData.getValue());
632 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
633 // TODO: sort the rules by size and binary representation.
635 // (x, y, .+) --> 110 6 priority 1
637 // (x, .+, z) --> 101 5 priority 2
641 public ImmutablePair<JanusGraphOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
642 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
643 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllRes = this
644 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
645 if (getAllRes.isRight()) {
646 JanusGraphOperationStatus status = getAllRes.right().value();
647 log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
648 return new ImmutablePair<>(status, null);
650 List<ComponentInstanceProperty> list = getAllRes.left().value();
652 for (ComponentInstanceProperty instanceProperty : list) {
653 String propertyUniqueId = instanceProperty.getUniqueId();
654 String valueUniqueUid = instanceProperty.getValueUniqueUid();
655 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
656 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
657 log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
658 return new ImmutablePair<>(JanusGraphOperationStatus.ALREADY_EXIST, valueUniqueUid);
662 return new ImmutablePair<>(JanusGraphOperationStatus.NOT_FOUND, null);
665 public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
666 String resourceInstanceId) {
667 List<PropertyRule> currentRules = propertyValueData.getRules();
668 List<PropertyRule> rules = resourceInstanceProperty.getRules();
669 // if rules are not supported.
671 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
672 rules = new ArrayList<>();
673 rules.add(propertyRule);
674 if (currentRules != null) {
675 rules = mergeRules(currentRules, rules);
678 // Full mode. all rules are sent in update operation.
679 rules = sortRules(rules);
681 propertyValueData.setRules(rules);
684 private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
685 List<PropertyRule> mergedRules = new ArrayList<>();
686 if (newRules == null || newRules.isEmpty()) {
689 for (PropertyRule rule : currentRules) {
690 PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
691 mergedRules.add(propertyRule);
693 for (PropertyRule rule : newRules) {
694 PropertyRule foundRule = findRuleInList(rule, mergedRules);
695 if (foundRule != null) {
696 foundRule.setValue(rule.getValue());
698 mergedRules.add(rule);
704 private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
705 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
708 PropertyRule foundRule = null;
709 for (PropertyRule propertyRule : rules) {
710 if (rule.getRuleSize() != propertyRule.getRuleSize()) {
713 boolean equals = propertyRule.compareRule(rule);
715 foundRule = propertyRule;
723 * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
725 * @param resourceInstanceUid
728 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
729 String resourceInstanceUid) {
730 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
733 public Either<PropertyValueData, JanusGraphOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
734 Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
735 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
736 if (findResInstanceRes.isRight()) {
737 JanusGraphOperationStatus status = findResInstanceRes.right().value();
738 if (status == JanusGraphOperationStatus.NOT_FOUND) {
739 status = JanusGraphOperationStatus.INVALID_ID;
741 return Either.right(status);
743 Either<PropertyValueData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
744 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
745 if (findPropertyDefRes.isRight()) {
746 JanusGraphOperationStatus status = findPropertyDefRes.right().value();
747 if (status == JanusGraphOperationStatus.NOT_FOUND) {
748 status = JanusGraphOperationStatus.INVALID_ID;
750 return Either.right(status);
752 Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
753 .getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
754 if (relation.isRight()) {
755 // TODO: add error in case of error
756 JanusGraphOperationStatus status = relation.right().value();
757 if (status == JanusGraphOperationStatus.NOT_FOUND) {
758 status = JanusGraphOperationStatus.INVALID_ID;
760 return Either.right(status);
762 Either<PropertyValueData, JanusGraphOperationStatus> deleteNode = janusGraphGenericDao
763 .deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
764 if (deleteNode.isRight()) {
765 return Either.right(deleteNode.right().value());
767 PropertyValueData value = deleteNode.left().value();
768 return Either.left(value);
771 public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid,
772 String resourceInstanceId,
773 boolean inTransaction) {
774 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
776 Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = this
777 .removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
778 if (eitherStatus.isRight()) {
779 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId,
780 eitherStatus.right().value().name());
781 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
784 PropertyValueData propertyValueData = eitherStatus.left().value();
785 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
786 propertyValueResult.setUniqueId(resourceInstanceId);
787 propertyValueResult.setValue(propertyValueData.getValue());
788 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
789 result = Either.left(propertyValueResult);
793 if (!inTransaction) {
794 if (result == null || result.isRight()) {
795 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
796 janusGraphGenericDao.rollback();
798 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
799 janusGraphGenericDao.commit();
805 public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData,
806 ComponentInstanceProperty resourceInstanceProperty) {
807 String value = propertyValueData.getValue();
808 String uid = propertyValueData.getUniqueId();
809 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
810 instanceProperty.setPath(resourceInstanceProperty.getPath());
811 return instanceProperty;
815 public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
816 if (propertyDefinition == null) {
819 String innerType = null;
820 String propertyType = propertyDefinition.getType();
821 ToscaPropertyType type = getType(propertyType);
822 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
823 SchemaDefinition def = propertyDefinition.getSchema();
827 PropertyDataDefinition propDef = def.getProperty();
828 if (propDef == null) {
831 innerType = propDef.getType();
833 String value = propertyDefinition.getDefaultValue();
835 return isValidValue(type, value, innerType, dataTypes);
837 log.trace("The given type {} is not a pre defined one.", propertyType);
838 DataTypeDefinition foundDt = dataTypes.get(propertyType);
839 if (foundDt != null) {
840 return isValidComplexValue(foundDt, value, dataTypes);
847 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final String model) {
848 if (property == null) {
851 if (ToscaPropertyType.isValidType(property.getType()) == null) {
852 Either<Boolean, JanusGraphOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType(), model);
853 if (definedInDataTypes.isRight()) {
856 Boolean isExist = definedInDataTypes.left().value();
857 return isExist.booleanValue();
863 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final Map<String, DataTypeDefinition> dataTypes) {
864 if (property == null) {
867 return ToscaPropertyType.isValidType(property.getType()) != null || dataTypes.containsKey(property.getType());
871 public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
872 if (property == null) {
873 return new ImmutablePair<>(null, false);
875 SchemaDefinition schema;
876 PropertyDataDefinition innerProp;
877 String innerType = null;
878 if ((schema = property.getSchema()) != null) {
879 if ((innerProp = schema.getProperty()) != null) {
880 innerType = innerProp.getType();
883 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
884 if (innerToscaType == null) {
885 DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
886 if (dataTypeDefinition == null) {
887 log.debug("The inner type {} is not a data type.", innerType);
888 return new ImmutablePair<>(innerType, false);
890 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
893 return new ImmutablePair<>(innerType, true);
896 private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
897 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
898 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
899 return validateAndUpdate.right.booleanValue();
902 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
903 String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
904 Either<JanusGraphVertex, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
905 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
906 if (findResInstanceRes.isRight()) {
907 JanusGraphOperationStatus status = findResInstanceRes.right().value();
908 if (status == JanusGraphOperationStatus.NOT_FOUND) {
909 status = JanusGraphOperationStatus.INVALID_ID;
911 return Either.right(status);
913 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> propertyImplNodes = janusGraphGenericDao
914 .getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
915 if (propertyImplNodes.isRight()) {
916 JanusGraphOperationStatus status = propertyImplNodes.right().value();
917 return Either.right(status);
919 List<ImmutablePair<JanusGraphVertex, Edge>> list = propertyImplNodes.left().value();
920 if (list == null || list.isEmpty()) {
921 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
923 List<ComponentInstanceProperty> result = new ArrayList<>();
924 for (ImmutablePair<JanusGraphVertex, Edge> propertyValue : list) {
925 JanusGraphVertex propertyValueDataVertex = propertyValue.getLeft();
926 String propertyValueUid = (String) janusGraphGenericDao
927 .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
928 String value = (String) janusGraphGenericDao.getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
929 ImmutablePair<JanusGraphVertex, Edge> propertyDefPair = janusGraphGenericDao
930 .getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
931 if (propertyDefPair == null) {
932 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
934 Map<String, Object> properties = janusGraphGenericDao.getProperties(propertyValueDataVertex);
935 PropertyValueData propertyValueData = GraphElementFactory
936 .createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
937 String propertyUniqueId = (String) janusGraphGenericDao
938 .getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
939 ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
940 // set property original unique id
941 resourceInstanceProperty.setUniqueId(propertyUniqueId);
944 // TODO: esofer add resource id
945 resourceInstanceProperty.setParentUniqueId(null);
947 resourceInstanceProperty.setValue(value);
948 // set property value unique id
949 resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
951 resourceInstanceProperty.setRules(propertyValueData.getRules());
952 result.add(resourceInstanceProperty);
954 return Either.left(result);
958 * Find the default value from the list of component instances. Start the search from the second component instance
960 * @param pathOfComponentInstances
961 * @param propertyUniqueId
962 * @param defaultValue
965 public Either<String, JanusGraphOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances,
966 String propertyUniqueId, String defaultValue) {
967 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
968 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
969 return Either.left(defaultValue);
971 String result = defaultValue;
972 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
973 String compInstanceId = pathOfComponentInstances.get(i);
974 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> propertyValuesResult = this
975 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
976 log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
977 if (propertyValuesResult.isRight()) {
978 JanusGraphOperationStatus status = propertyValuesResult.right().value();
979 if (status != JanusGraphOperationStatus.NOT_FOUND) {
980 return Either.right(status);
985 ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
986 log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
987 if (foundCompInstanceProperty == null) {
990 List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i),
991 foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
992 log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
993 PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
994 log.trace("Match rule is {}", matchedRule);
995 if (matchedRule != null) {
996 result = matchedRule.getValue();
1000 return Either.left(result);
1003 private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
1004 ComponentInstanceProperty result = null;
1008 for (ComponentInstanceProperty instProperty : list) {
1009 if (instProperty.getUniqueId().equals(propertyUniqueId)) {
1010 result = instProperty;
1017 private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
1018 if (rules != null) {
1021 rules = buildDefaultRule(compInstanceId, ruleSize, value);
1025 private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
1026 List<PropertyRule> rules = componentInstanceProperty.getRules();
1027 if (rules == null) {
1028 rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
1033 private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
1034 List<PropertyRule> rules = new ArrayList<>();
1035 List<String> rule = new ArrayList<>();
1036 rule.add(componentInstanceId);
1037 for (int i = 0; i < size - 1; i++) {
1038 rule.add(PropertyRule.getRuleAnyMatch());
1040 PropertyRule propertyRule = new PropertyRule(rule, value);
1041 rules.add(propertyRule);
1045 private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1046 PropertyRule propertyRule = null;
1047 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1048 String firstCompInstance = pathOfInstances.get(level);
1049 if (rules != null) {
1050 for (PropertyRule rule : rules) {
1051 int ruleSize = rule.getRule().size();
1052 // check the length of the rule equals to the length of the
1055 if (ruleSize != pathOfInstances.size() - level) {
1058 // check that the rule starts with correct component instance id
1059 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1062 String secondToken = rule.getToken(2);
1063 if (secondToken != null && (secondToken.equals(PropertyRule.getForceAll()) || secondToken.equals(PropertyRule.getALL()))) {
1064 propertyRule = rule;
1067 String patternStr = buildStringForMatch(rule.getRule(), 0);
1068 Pattern pattern = Pattern.compile(patternStr);
1069 Matcher matcher = pattern.matcher(stringForMatch);
1070 if (matcher.matches()) {
1071 if (log.isTraceEnabled()) {
1072 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1074 propertyRule = rule;
1079 return propertyRule;
1082 private boolean checkFirstItem(String left, String right) {
1083 if (left != null && left.equals(right)) {
1089 private String buildStringForMatch(List<String> pathOfInstances, int level) {
1090 StringBuilder builder = new StringBuilder();
1091 for (int i = level; i < pathOfInstances.size(); i++) {
1092 builder.append(pathOfInstances.get(i));
1093 if (i < pathOfInstances.size() - 1) {
1094 builder.append("#");
1097 return builder.toString();
1100 public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty,
1101 Map<String, ComponentInstanceProperty> instanceIdToValue) {
1102 List<String> pathOfInstances = instanceProperty.getPath();
1104 int size = pathOfInstances.size();
1105 int numberOfMatches = 0;
1106 for (String instanceId : pathOfInstances) {
1107 ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1108 if (componentInstanceProperty != null) {
1109 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1110 // If it is the first level instance, then update valueUniuqeId
1112 // parameter in order to know on update that
1114 // we should update and not create new node on graph.
1116 instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1117 instanceProperty.setRules(rules);
1119 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1122 String value = rule.getValue();
1123 if (numberOfMatches == 1) {
1124 instanceProperty.setValue(value);
1125 if (log.isDebugEnabled()) {
1126 log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1127 pathOfInstances, value);
1129 } else if (numberOfMatches == 2) {
1130 // In case of another property value match, then use the
1132 // value to be the default value of the property.
1133 instanceProperty.setDefaultValue(value);
1134 if (log.isDebugEnabled()) {
1135 log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1136 pathOfInstances, value);
1147 * Add data type to graph.
1149 * 1. Add data type node
1151 * 2. Add edge between the former node to its parent(if exists)
1153 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1155 * @param dataTypeDefinition
1158 private Either<DataTypeData, JanusGraphOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1159 log.debug("Got data type {}", dataTypeDefinition);
1160 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getModel(), dataTypeDefinition.getName());
1161 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1162 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1163 Either<DataTypeData, JanusGraphOperationStatus> createDataTypeResult = janusGraphGenericDao.createNode(dataTypeData, DataTypeData.class);
1164 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1165 if (createDataTypeResult.isRight()) {
1166 JanusGraphOperationStatus operationStatus = createDataTypeResult.right().value();
1167 log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1168 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1169 return Either.right(operationStatus);
1171 DataTypeData resultCTD = createDataTypeResult.left().value();
1172 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1173 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(),
1174 dataTypeDefinition.getModel(),
1176 if (addPropertiesToDataType.isRight()) {
1177 log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1178 return Either.right(addPropertiesToDataType.right().value());
1181 final Either<GraphRelation, JanusGraphOperationStatus> modelRelationship = addDataTypeToModel(dataTypeDefinition);
1182 if (modelRelationship.isRight()) {
1183 return Either.right(modelRelationship.right().value());
1186 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1187 if (derivedFrom != null) {
1188 final Either<DataTypeDefinition, JanusGraphOperationStatus> derivedFromDataType = getDataTypeByNameValidForModel(derivedFrom,
1189 dataTypeDefinition.getModel());
1190 if (derivedFromDataType.isRight()) {
1191 return Either.right(derivedFromDataType.right().value());
1194 log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1195 UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1196 final String deriveFromUid = derivedFromDataType.left().value().getUniqueId();
1197 UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1198 Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
1199 .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1200 log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1201 if (createRelation.isRight()) {
1202 return Either.right(createRelation.right().value());
1205 return Either.left(createDataTypeResult.left().value());
1208 private Either<GraphRelation, JanusGraphOperationStatus> addDataTypeToModel(final DataTypeDefinition dataTypeDefinition) {
1209 final String model = dataTypeDefinition.getModel();
1210 if (model == null) {
1211 return Either.left(null);
1213 final GraphNode from = new UniqueIdData(NodeTypeEnum.Model, UniqueIdBuilder.buildModelUid(model));
1214 final GraphNode to = new UniqueIdData(NodeTypeEnum.DataType, dataTypeDefinition.getUniqueId());
1215 log.info("Connecting model {} to type {}", from, to);
1216 return janusGraphGenericDao.createRelation(from, to, GraphEdgeLabels.MODEL_ELEMENT, Collections.emptyMap());
1219 private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1220 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1221 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1222 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1223 if (creationDate == null) {
1224 creationDate = System.currentTimeMillis();
1226 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1227 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1228 return dataTypeData;
1232 * add properties to capability type.
1234 * Per property, add a property node and associate it to the capability type
1240 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType(final String uniqueId, final String modelName,
1241 final List<PropertyDefinition> properties) {
1242 Map<String, PropertyData> propertiesData = new HashMap<>();
1243 if (properties != null && !properties.isEmpty()) {
1244 for (PropertyDefinition propertyDefinition : properties) {
1245 String propertyName = propertyDefinition.getName();
1246 String propertyType = propertyDefinition.getType();
1247 Either<Boolean, JanusGraphOperationStatus> validPropertyType = isValidPropertyType(propertyType, modelName);
1248 if (validPropertyType.isRight()) {
1249 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1250 return Either.right(validPropertyType.right().value());
1252 Boolean isValid = validPropertyType.left().value();
1253 if (isValid == null || !isValid.booleanValue()) {
1254 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1255 return Either.right(JanusGraphOperationStatus.INVALID_TYPE);
1257 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1258 .addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1259 if (addPropertyToNodeType.isRight()) {
1260 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1261 log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1262 BeEcompErrorManager.getInstance()
1263 .logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus,
1264 ErrorSeverity.ERROR);
1265 return Either.right(operationStatus);
1267 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1269 DataTypeData dataTypeData = new DataTypeData();
1270 dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1271 long modificationTime = System.currentTimeMillis();
1272 dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1273 Either<DataTypeData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao.updateNode(dataTypeData, DataTypeData.class);
1274 if (updateNode.isRight()) {
1275 JanusGraphOperationStatus operationStatus = updateNode.right().value();
1276 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1277 BeEcompErrorManager.getInstance()
1278 .logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1279 return Either.right(operationStatus);
1281 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1284 return Either.left(propertiesData);
1287 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByNameValidForModel(final String name, final String modelName) {
1288 final Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1289 .getNode(GraphPropertiesDictionary.NAME.getProperty(), name, DataTypeData.class, modelName);
1290 if (dataTypesRes.isRight()) {
1291 final JanusGraphOperationStatus status = dataTypesRes.right().value();
1292 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, name, status);
1293 return Either.right(status);
1295 final DataTypeData dataType = dataTypesRes.left().value();
1296 final DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(dataType.getDataTypeDataDefinition());
1297 final JanusGraphOperationStatus propertiesStatus = fillProperties(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1298 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1299 log.error(BUSINESS_PROCESS_ERROR, FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, dataTypeDefinition.getUniqueId());
1300 return Either.right(propertiesStatus);
1302 final Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1303 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeDefinition.getUniqueId(), GraphEdgeLabels.DERIVED_FROM,
1304 NodeTypeEnum.DataType,
1305 DataTypeData.class);
1306 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, dataTypeDefinition.getUniqueId(), parentNode);
1307 if (parentNode.isRight()) {
1308 final JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1309 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1310 log.error(BUSINESS_PROCESS_ERROR, "Failed to find the parent data type of data type {}. status is {}",
1311 dataTypeDefinition.getUniqueId(), janusGraphOperationStatus);
1312 return Either.right(janusGraphOperationStatus);
1315 // derived from node was found
1316 final ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1317 final DataTypeData parentDataType = immutablePair.getKey();
1318 final Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentDataType.getUniqueId());
1319 if (dataTypeByUid.isRight()) {
1320 return Either.right(dataTypeByUid.right().value());
1322 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1323 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1325 return Either.left(dataTypeDefinition);
1329 * Build Data type object from graph by unique id
1334 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUid(String uniqueId) {
1335 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1336 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1337 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1338 if (dataTypesRes.isRight()) {
1339 JanusGraphOperationStatus status = dataTypesRes.right().value();
1340 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1341 return Either.right(status);
1343 DataTypeData ctData = dataTypesRes.left().value();
1344 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1345 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1346 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1347 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1348 return Either.right(propertiesStatus);
1350 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1351 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1352 DataTypeData.class);
1353 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1354 if (parentNode.isRight()) {
1355 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1356 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1357 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1358 result = Either.right(janusGraphOperationStatus);
1362 // derived from node was found
1363 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1364 DataTypeData parentCT = immutablePair.getKey();
1365 String parentUniqueId = parentCT.getUniqueId();
1366 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1367 if (dataTypeByUid.isRight()) {
1368 return Either.right(dataTypeByUid.right().value());
1370 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1371 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1373 result = Either.left(dataTypeDefinition);
1377 private JanusGraphOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1378 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this
1379 .findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1380 if (findPropertiesOfNode.isRight()) {
1381 JanusGraphOperationStatus janusGraphOperationStatus = findPropertiesOfNode.right().value();
1382 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, janusGraphOperationStatus);
1383 if (JanusGraphOperationStatus.NOT_FOUND.equals(janusGraphOperationStatus)) {
1384 return JanusGraphOperationStatus.OK;
1386 return janusGraphOperationStatus;
1389 Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1390 if (properties != null && !properties.isEmpty()) {
1391 List<PropertyDefinition> listOfProps = new ArrayList<>();
1392 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1393 String propName = entry.getKey();
1394 PropertyDefinition propertyDefinition = entry.getValue();
1395 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1396 newPropertyDefinition.setName(propName);
1397 listOfProps.add(newPropertyDefinition);
1399 dataTypeDefinition.setProperties(listOfProps);
1401 return JanusGraphOperationStatus.OK;
1405 private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1406 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1408 Either<DataTypeData, JanusGraphOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1409 if (eitherStatus.isRight()) {
1410 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1411 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1412 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1415 DataTypeData capabilityTypeData = eitherStatus.left().value();
1416 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1417 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1418 result = Either.left(dataTypeDefResult);
1422 if (!inTransaction) {
1423 if (result == null || result.isRight()) {
1424 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1425 janusGraphGenericDao.rollback();
1427 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1428 janusGraphGenericDao.commit();
1435 public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1436 return addDataType(dataTypeDefinition, true);
1440 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel,
1441 final boolean inTransaction) {
1442 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1444 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByNameValidForModel(name, validForModel);
1445 if (ctResult.isRight()) {
1446 JanusGraphOperationStatus status = ctResult.right().value();
1447 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1448 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1450 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1453 result = Either.left(ctResult.left().value());
1456 if (!inTransaction) {
1457 if (result == null || result.isRight()) {
1458 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1459 janusGraphGenericDao.rollback();
1461 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1462 janusGraphGenericDao.commit();
1469 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel) {
1470 return getDataTypeByName(name, validForModel, true);
1473 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByUidWithoutDerived(String uid, boolean inTransaction) {
1474 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1476 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1477 if (ctResult.isRight()) {
1478 JanusGraphOperationStatus status = ctResult.right().value();
1479 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1480 log.error(BUSINESS_PROCESS_ERROR, "Failed to retrieve information on data type {} status is {}", uid, status);
1482 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1485 result = Either.left(ctResult.left().value());
1488 if (!inTransaction) {
1489 if (result == null || result.isRight()) {
1490 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1491 janusGraphGenericDao.rollback();
1493 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1494 janusGraphGenericDao.commit();
1500 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1501 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1502 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1503 if (dataTypesRes.isRight()) {
1504 JanusGraphOperationStatus status = dataTypesRes.right().value();
1505 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1506 return Either.right(status);
1508 DataTypeData ctData = dataTypesRes.left().value();
1509 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1510 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1511 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1512 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1513 return Either.right(propertiesStatus);
1515 return Either.left(dataTypeDefinition);
1519 * convert between graph Node object to Java object
1521 * @param dataTypeData
1524 protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1525 log.debug("The object returned after create data type is {}", dataTypeData);
1526 return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1529 private Either<Boolean, JanusGraphOperationStatus> isValidPropertyType(String propertyType, final String modelName) {
1530 if (propertyType == null || propertyType.isEmpty()) {
1531 return Either.left(false);
1533 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1534 if (toscaPropertyType == null) {
1535 return isDefinedInDataTypes(propertyType, modelName);
1537 return Either.left(true);
1541 public Either<Boolean, JanusGraphOperationStatus> isDefinedInDataTypes(final String propertyType, final String modelName) {
1542 Either<DataTypeDefinition, JanusGraphOperationStatus> dataType = getDataTypeByNameValidForModel(propertyType, modelName);
1543 if (dataType.isRight()) {
1544 JanusGraphOperationStatus status = dataType.right().value();
1545 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1546 return Either.left(false);
1548 return Either.right(status);
1550 return Either.left(true);
1553 public Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> getAllDataTypes() {
1554 final Map<String, Map<String, DataTypeDefinition>> dataTypes = new HashMap<>();
1555 Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> result = Either.left(dataTypes);
1556 final Map<String, DataTypeDefinition> allDataTypesFound = new HashMap<>();
1558 final Map<String, List<String>> dataTypeUidstoModels = dataTypeOperation.getAllDataTypeUidsToModels();
1560 if (dataTypeUidstoModels != null) {
1561 log.trace("Number of data types to load is {}", dataTypeUidstoModels.size());
1562 for (Map.Entry<String, List<String>> entry : dataTypeUidstoModels.entrySet()) {
1563 log.trace("Going to fetch data type with uid {}", entry.getKey());
1564 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this
1565 .getAndAddDataTypeByUid(entry.getKey(), allDataTypesFound);
1566 if (dataTypeByUid.isRight()) {
1567 JanusGraphOperationStatus status = dataTypeByUid.right().value();
1568 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1569 status = JanusGraphOperationStatus.INVALID_ID;
1571 return Either.right(status);
1573 for (final String model : entry.getValue()) {
1574 if (!dataTypes.containsKey(model)) {
1575 dataTypes.put(model, new HashMap<String, DataTypeDefinition>());
1577 DataTypeDefinition dataTypeDefinition = allDataTypesFound.get(entry.getKey());
1578 dataTypes.get(model).put(dataTypeDefinition.getName(), dataTypeDefinition);
1583 if (log.isTraceEnabled()) {
1584 if (result.isRight()) {
1585 log.trace("After fetching all data types {}", result);
1587 Map<String, Map<String, DataTypeDefinition>> map = result.left().value();
1589 String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1590 log.trace("After fetching all data types {} ", types);
1598 * Build Data type object from graph by unique id
1603 private Either<DataTypeDefinition, JanusGraphOperationStatus> getAndAddDataTypeByUid(String uniqueId,
1604 Map<String, DataTypeDefinition> allDataTypes) {
1605 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1606 if (allDataTypes.containsKey(uniqueId)) {
1607 return Either.left(allDataTypes.get(uniqueId));
1609 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1610 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1611 if (dataTypesRes.isRight()) {
1612 JanusGraphOperationStatus status = dataTypesRes.right().value();
1613 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1614 return Either.right(status);
1616 DataTypeData ctData = dataTypesRes.left().value();
1617 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1618 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1619 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1620 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1621 return Either.right(propertiesStatus);
1623 allDataTypes.put(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1624 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1625 if (allDataTypes.containsKey(derivedFrom)) {
1626 DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1627 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1628 return Either.left(dataTypeDefinition);
1630 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1631 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1632 DataTypeData.class);
1633 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1634 if (parentNode.isRight()) {
1635 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1636 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1637 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1638 result = Either.right(janusGraphOperationStatus);
1642 // derived from node was found
1643 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1644 DataTypeData parentCT = immutablePair.getKey();
1645 String parentUniqueId = parentCT.getUniqueId();
1646 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1647 if (dataTypeByUid.isRight()) {
1648 return Either.right(dataTypeByUid.right().value());
1650 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1651 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1652 final var model = getModel(uniqueId);
1653 if (StringUtils.isNotEmpty(model)) {
1654 dataTypeDefinition.setModel(model);
1657 result = Either.left(dataTypeDefinition);
1661 private String getModel(final String uniqueId) {
1662 final Either<ImmutablePair<ModelData, GraphEdge>, JanusGraphOperationStatus> model = janusGraphGenericDao.getParentNode(
1663 UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.MODEL_ELEMENT,
1664 NodeTypeEnum.Model, ModelData.class);
1665 return model.isLeft() ? model.left().value().getLeft().getName() : StringUtils.EMPTY;
1668 public Either<String, JanusGraphOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
1669 String propertyType = propDataDef.getType();
1670 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
1671 return getInnerType(type, propDataDef::getSchema);
1674 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType,
1675 Map<String, DataTypeDefinition> dataTypes) {
1676 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
1677 final ToscaPropertyType type = getType(propertyType);
1680 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
1681 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter
1682 .validateAndUpdate(value, dataTypeDefinition, dataTypes);
1683 if (Boolean.FALSE.equals(validateResult.right)) {
1684 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
1685 return Either.right(false);
1687 JsonElement jsonElement = validateResult.left;
1688 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
1689 return Either.left(valueFromJsonElement);
1691 log.trace("before validating property type {}", propertyType);
1692 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
1693 if (!isValidProperty) {
1694 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
1695 return Either.right(false);
1698 Object convertedValue = value;
1699 if (!isEmptyValue(value) && isValidate) {
1700 PropertyValueConverter converter = type.getConverter();
1701 convertedValue = converter.convert(value, innerType, dataTypes);
1703 return Either.left(convertedValue);
1706 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType,
1707 Map<String, DataTypeDefinition> dataTypes) {
1708 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
1711 public Either<Object, Boolean> validateAndUpdatePropertyValue(final Component containerComponent, final PropertyDataDefinition property,
1712 final Map<String, DataTypeDefinition> dataTypes) {
1713 if (property.isToscaFunction()) {
1714 toscaFunctionValidator.validate(property, containerComponent);
1715 property.setValue(property.getToscaFunction().getValue());
1716 return Either.left(property.getValue());
1718 Either<String, JanusGraphOperationStatus> checkInnerType = checkInnerType(property);
1719 if (checkInnerType.isRight()) {
1720 return Either.right(false);
1722 final String innerType = checkInnerType.left().value();
1723 return validateAndUpdatePropertyValue(property.getType(), property.getValue(), true, innerType, dataTypes);
1726 public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType,
1728 return this.findPropertiesOfNode(nodeType, uniqueId).right().bind(this::handleNotFoundProperties).left()
1729 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
1732 private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(
1733 JanusGraphOperationStatus janusGraphOperationStatus) {
1734 if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
1735 return Either.left(new HashMap<>());
1737 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1740 private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId,
1741 NodeTypeEnum nodeType,
1743 Collection<PropertyDefinition> nodeProps) {
1744 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
1745 String currentNodeUid = uniqueId;
1746 Either<T, StorageOperationStatus> derivedFrom;
1747 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
1748 currentNodeUid = derivedFrom.left().value().getUniqueId();
1749 JanusGraphOperationStatus janusGraphOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
1750 if (janusGraphOperationStatus != JanusGraphOperationStatus.OK) {
1751 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
1752 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1755 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
1756 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
1759 private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
1760 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
1764 * @Override public PropertyOperation getPropertyOperation() { return this; }
1766 public JanusGraphOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
1767 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
1768 if (findPropertiesRes.isRight()) {
1769 return findPropertiesRes.right().value();
1771 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
1772 if (properties != null) {
1773 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
1774 propertySetter.accept(propertiesAsList);
1776 return JanusGraphOperationStatus.OK;
1779 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType) {
1780 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
1781 if (findPropertiesOfNode.isRight()) {
1782 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
1783 if (findPropertiesOfNode.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
1784 return Either.left(Maps.newHashMap());
1786 return findPropertiesOfNode;
1788 return findPropertiesOfNode;
1792 * add properties to element type.
1794 * Per property, add a property node and associate it to the element type
1797 * @param propertiesMap
1800 protected Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType,
1801 Map<String, PropertyDefinition> propertiesMap) {
1802 Map<String, PropertyData> propertiesData = new HashMap<>();
1803 if (propertiesMap != null) {
1804 for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
1805 String propertyName = propertyDefinitionEntry.getKey();
1806 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1807 .addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
1808 if (addPropertyToNodeType.isRight()) {
1809 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1810 log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName,
1812 return Either.right(operationStatus);
1814 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1817 return Either.left(propertiesData);
1820 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType,
1821 List<PropertyDefinition> properties) {
1822 Map<String, PropertyDefinition> propMap;
1823 if (properties == null) {
1826 propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
1828 return addPropertiesToElementType(uniqueId, elementType, propMap);
1832 public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1833 DataTypeDefinition oldDataTypeDefinition) {
1834 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
1837 private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1838 DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
1839 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1841 List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
1842 List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
1843 String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
1844 String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
1845 String dataTypeName = newDataTypeDefinition.getName();
1846 List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
1847 if (isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, propertiesToAdd)
1848 || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
1849 log.debug("The new data type {} is invalid.", dataTypeName);
1850 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
1853 if (CollectionUtils.isEmpty(propertiesToAdd)) {
1854 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
1855 result = Either.right(StorageOperationStatus.OK);
1858 Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
1859 if (MapUtils.isNotEmpty(newDescriptions)) {
1860 JanusGraphOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(),
1862 if (updatePropertiesStatus != JanusGraphOperationStatus.OK) {
1863 log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}",
1864 oldDataTypeDefinition, updatePropertiesStatus);
1865 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1866 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatePropertiesStatus));
1870 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(
1871 oldDataTypeDefinition.getUniqueId(), oldDataTypeDefinition.getModel(), propertiesToAdd);
1872 if (addPropertiesToDataType.isRight()) {
1873 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition,
1874 addPropertiesToDataType.right().value().name());
1875 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1876 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToDataType.right().value()));
1879 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
1880 if (dataTypeByUid.isRight()) {
1881 JanusGraphOperationStatus status = addPropertiesToDataType.right().value();
1882 log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
1883 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
1884 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
1886 result = Either.left(dataTypeByUid.left().value());
1891 if (!inTransaction) {
1892 if (result == null || result.isRight()) {
1893 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1894 janusGraphGenericDao.rollback();
1896 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1897 janusGraphGenericDao.commit();
1903 private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties,
1904 List<PropertyDefinition> outputPropertiesToAdd) {
1905 if (newProperties != null && oldProperties != null) {
1906 Map<String, PropertyDefinition> newPropsMapper = newProperties.stream()
1907 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1908 Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream()
1909 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1910 for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
1911 String propName = newPropertyEntry.getKey();
1912 PropertyDefinition propDef = newPropertyEntry.getValue();
1913 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
1914 if (oldPropertyDefinition == null) {
1915 log.debug("New property {} received in the data type {}", propName, dataTypeName);
1916 outputPropertiesToAdd.add(propDef);
1919 String oldType = oldPropertyDefinition.getType();
1920 String oldEntryType = getEntryType(oldPropertyDefinition);
1921 String newType = propDef.getType();
1922 String newEntryType = getEntryType(propDef);
1923 if (!oldType.equals(newType)) {
1924 log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType,
1928 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
1929 log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName,
1930 oldEntryType, newEntryType);
1938 private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
1939 if (oldEntryType == null && newEntryType == null) {
1941 } else if (oldEntryType != null && newEntryType != null) {
1942 return oldEntryType.equals(newEntryType);
1948 private String getEntryType(PropertyDefinition oldPropertyDefinition) {
1949 String entryType = null;
1950 SchemaDefinition schema = oldPropertyDefinition.getSchema();
1951 if (schema != null) {
1952 PropertyDataDefinition schemaProperty = schema.getProperty();
1953 if (schemaProperty != null) {
1954 entryType = schemaProperty.getType();
1960 private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
1961 if (newDerivedFromName != null) {
1962 boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
1964 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1965 oldDerivedFromName);
1968 } else if (oldDerivedFromName == null) {
1970 } else {// new=null, old != null
1971 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1972 oldDerivedFromName);
1982 public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
1983 Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
1984 if (graphResult.isRight()) {
1985 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
1987 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
1988 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
1989 if (vertexService.isRight()) {
1990 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
1991 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
1993 Vertex vertex = vertexService.left().value();
1994 VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
1995 Integer counter = 0;
1996 if (vertexProperty.isPresent() && vertexProperty.value() != null) {
1997 counter = (Integer) vertexProperty.value();
2000 vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
2001 return Either.left(counter);
2004 public Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesUniqueness(
2005 Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
2006 Either<List<PropertyDefinition>, JanusGraphOperationStatus> result = Either.left(properties);
2007 for (PropertyDefinition property : properties) {
2008 JanusGraphOperationStatus status = validatePropertyUniqueness(inheritedProperties, property);
2009 if (status != JanusGraphOperationStatus.OK) {
2010 result = Either.right(status);
2018 * Validates uniqueness of examined property by comparing it with properties in propertiesOfType and updates if need type and inner type of the
2021 private JanusGraphOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2022 String propertyName = property.getName();
2023 String propertyType = property.getType();
2024 JanusGraphOperationStatus result = JanusGraphOperationStatus.OK;
2025 if (inheritedProperties.containsKey(propertyName)) {
2026 PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2027 if (typesMismatch(propertyType, defaultProperty.getType())) {
2028 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2029 result = JanusGraphOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2031 property.setType(defaultProperty.getType());
2032 String innerType = defaultProperty.getSchemaType();
2033 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2034 if (schemaProperty != null) {
2035 schemaProperty.setType(innerType);
2042 private boolean typesMismatch(String type1, String type2) {
2043 return type1 != null && type2 != null && !type2.equals(type1);
2046 public <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllTypePropertiesFromAllDerivedFrom(
2047 String nextParentUid, NodeTypeEnum nodeType, Class<T> clazz) {
2048 Map<String, PropertyDefinition> allProperies = new HashMap<>();
2049 return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2052 private <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getTypePropertiesFromDerivedFromRecursively(
2053 String nextParentUid, Map<String, PropertyDefinition> allProperies, NodeTypeEnum nodeType, Class<T> clazz) {
2054 JanusGraphOperationStatus error;
2055 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
2056 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2057 if (childrenNodes.isRight()) {
2058 if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
2059 error = childrenNodes.right().value();
2060 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid,
2062 return Either.right(error);
2064 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.",
2066 return Either.left(allProperies);
2069 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2070 if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
2071 error = allPropertiesOfTypeRes.right().value();
2073 "#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}",
2074 nextParentUid, error);
2075 return Either.right(error);
2076 } else if (allPropertiesOfTypeRes.isLeft()) {
2077 if (allProperies.isEmpty()) {
2078 allProperies.putAll(allPropertiesOfTypeRes.left().value());
2080 allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey()))
2081 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2084 return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType,
2089 private JanusGraphOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2090 if (MapUtils.isNotEmpty(newDescriptions)) {
2091 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getDataTypePropertiesRes = janusGraphGenericDao
2092 .getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2093 if (getDataTypePropertiesRes.isRight()) {
2094 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2095 return getDataTypePropertiesRes.right().value();
2097 getDataTypePropertiesRes.left().value().stream().filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2098 .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2100 return JanusGraphOperationStatus.OK;
2103 private JanusGraphVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<JanusGraphVertex, Edge> pair) {
2104 return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2107 private String getPropertyNameFromEdge(ImmutablePair<JanusGraphVertex, Edge> pair) {
2108 return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2111 private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2112 Map<String, PropertyDefinition> newPropertiesMap = newProperties.stream().collect(Collectors.toMap(PropertyDefinition::getName, p -> p));
2113 return oldProperties.stream()
2114 .filter(p -> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2115 .collect(Collectors.toMap(PropertyDefinition::getName, p -> newPropertiesMap.get(p.getName()).getDescription()));
2118 private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty) {
2119 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2122 if (StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2125 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())) {
2128 return property.getDescription().equals(otherProperty.getDescription());
2131 public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
2134 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
2135 JsonObject result = new JsonObject();
2136 JsonArray jsonArray = new JsonArray();
2137 if (src instanceof InRangeConstraint) {
2138 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
2139 jsonArray.add(JsonParser.parseString(rangeConstraint.getRangeMinValue()));
2140 jsonArray.add(JsonParser.parseString(rangeConstraint.getRangeMaxValue()));
2141 result.add("inRange", jsonArray);
2142 } else if (src instanceof GreaterThanConstraint) {
2143 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
2144 jsonArray.add(JsonParser.parseString(greaterThanConstraint.getGreaterThan()));
2145 result.add("greaterThan", jsonArray);
2146 } else if (src instanceof LessOrEqualConstraint) {
2147 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
2148 jsonArray.add(JsonParser.parseString(lessOrEqualConstraint.getLessOrEqual()));
2149 result.add("lessOrEqual", jsonArray);
2151 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
2157 public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
2159 private static final String THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL = "The value of GreaterThanConstraint is null";
2162 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
2163 PropertyConstraint propertyConstraint = null;
2164 Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
2165 if (set.size() == 1) {
2166 Entry<String, JsonElement> element = set.iterator().next();
2167 String key = element.getKey();
2168 JsonElement value = element.getValue();
2169 ConstraintType constraintType = ConstraintType.findByType(key).orElse(null);
2170 if (constraintType == null) {
2171 log.warn("ConstraintType was not found for constraint name:{}", key);
2173 switch (constraintType) {
2175 if (value != null) {
2176 String asString = value.getAsString();
2177 log.debug("Before adding value to EqualConstraint object. value = {}", asString);
2178 propertyConstraint = new EqualConstraint(asString);
2181 log.warn("The value of equal constraint is null");
2185 if (value != null) {
2186 if (value instanceof JsonArray) {
2187 JsonArray rangeArray = (JsonArray) value;
2188 if (rangeArray.size() != 2) {
2189 log.error("The range constraint content is invalid. value = {}", value);
2191 InRangeConstraint rangeConstraint = new InRangeConstraint();
2192 String minValue = rangeArray.get(0).getAsString();
2194 JsonElement maxElement = rangeArray.get(1);
2195 if (maxElement.isJsonNull()) {
2196 maxValue = String.valueOf(maxElement.getAsJsonNull());
2198 maxValue = maxElement.getAsString();
2200 rangeConstraint.setRangeMinValue(minValue);
2201 rangeConstraint.setRangeMaxValue(maxValue);
2202 propertyConstraint = rangeConstraint;
2206 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2210 if (value != null) {
2211 String asString = value.getAsString();
2212 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
2213 propertyConstraint = new GreaterThanConstraint(asString);
2216 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2220 if (value != null) {
2221 String asString = value.getAsString();
2222 log.debug("Before adding value to LessThanConstraint object. value = {}", asString);
2223 propertyConstraint = new LessThanConstraint(asString);
2226 log.warn("The value of LessThanConstraint is null");
2229 case GREATER_OR_EQUAL:
2230 if (value != null) {
2231 String asString = value.getAsString();
2232 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
2233 propertyConstraint = new GreaterOrEqualConstraint(asString);
2236 log.warn("The value of GreaterOrEqualConstraint is null");
2240 if (value != null) {
2241 String asString = value.getAsString();
2242 log.debug("Before adding value to LessOrEqualConstraint object. value = {}", asString);
2243 propertyConstraint = new LessOrEqualConstraint(asString);
2245 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2249 if (value != null) {
2250 JsonArray rangeArray = (JsonArray) value;
2251 if (rangeArray.size() == 0) {
2252 log.error("The valid values constraint content is invalid. value = {}", value);
2254 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2255 List<String> validValues = new ArrayList<>();
2256 for (JsonElement jsonElement : rangeArray) {
2257 String item = jsonElement.getAsString();
2258 validValues.add(item);
2260 vvConstraint.setValidValues(validValues);
2261 propertyConstraint = vvConstraint;
2266 if (value != null) {
2267 int asInt = value.getAsInt();
2268 log.debug("Before adding value to length constraint. value = {}", asInt);
2269 propertyConstraint = new LengthConstraint(asInt);
2272 log.warn("The value of length constraint is null");
2276 if (value != null) {
2277 int asInt = value.getAsInt();
2278 log.debug("Before adding value to Min Length object. value = {}", asInt);
2279 propertyConstraint = new MinLengthConstraint(asInt);
2282 log.warn("The value of MinLengthConstraint is null");
2286 if (value != null) {
2287 int asInt = value.getAsInt();
2288 log.debug("Before adding value to max length constraint. value = {}", asInt);
2289 propertyConstraint = new MaxLengthConstraint(asInt);
2292 log.warn("The value of max length constraint is null");
2296 log.warn("Key {} is not supported. Ignored.", key);
2300 return propertyConstraint;
2304 public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
2307 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
2308 ObjectCodec oc = json.getCodec();
2309 JsonNode node = oc.readTree(json);
2310 PropertyConstraint propertyConstraint = null;
2312 Iterator<Entry<String, JsonNode>> fieldsIterator = node.fields();
2313 while (fieldsIterator.hasNext()) {
2314 Entry<String, JsonNode> field = fieldsIterator.next();
2315 ConstraintType constraintType = ConstraintType.findByType(field.getKey()).orElse(null);
2316 JsonNode value = field.getValue();
2318 if (constraintType == null) {
2319 log.warn("ConstraintType was not found for constraint name:{}", field.getKey());
2321 if (value == null) {
2322 log.warn("The value of {} constraint is null", constraintType);
2324 switch (constraintType) {
2326 propertyConstraint = deserializeConstraintWithStringOperand(value, EqualConstraint.class);
2329 propertyConstraint = deserializeInRangeConstraintConstraint(value);
2332 propertyConstraint = deserializeConstraintWithStringOperand(value, GreaterThanConstraint.class);
2335 propertyConstraint = deserializeConstraintWithStringOperand(value, LessThanConstraint.class);
2337 case GREATER_OR_EQUAL:
2338 propertyConstraint = deserializeConstraintWithStringOperand(value, GreaterOrEqualConstraint.class);
2341 propertyConstraint = deserializeConstraintWithStringOperand(value, LessOrEqualConstraint.class);
2344 propertyConstraint = deserializeValidValuesConstraint(value);
2347 propertyConstraint = deserializeConstraintWithIntegerOperand(value, LengthConstraint.class);
2350 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MinLengthConstraint.class);
2353 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MaxLengthConstraint.class);
2356 log.warn("Key {} is not supported. Ignored.", field.getKey());
2362 return propertyConstraint;
2365 private PropertyConstraint deserializeConstraintWithStringOperand(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2366 String asString = value.asText();
2367 log.debug("Before adding value to {} object. value = {}", constraintClass, asString);
2369 return constraintClass.getConstructor(String.class).newInstance(asString);
2370 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2371 | SecurityException exception) {
2372 log.error("Error deserializing constraint", exception);
2377 private PropertyConstraint deserializeConstraintWithIntegerOperand(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2378 Integer asInt = value.asInt();
2379 log.debug("Before adding value to {} object. value = {}", constraintClass, asInt);
2381 return constraintClass.getConstructor(Integer.class).newInstance(asInt);
2382 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2383 | SecurityException exception) {
2384 log.error("Error deserializing constraint", exception);
2389 private PropertyConstraint deserializeInRangeConstraintConstraint(JsonNode value) {
2390 if (value instanceof ArrayNode) {
2391 ArrayNode rangeArray = (ArrayNode) value;
2392 if (rangeArray.size() != 2) {
2393 log.error("The range constraint content is invalid. value = {}", value);
2395 InRangeConstraint rangeConstraint = new InRangeConstraint();
2396 String minValue = rangeArray.get(0).asText();
2398 JsonNode maxElement = rangeArray.get(1);
2399 if (maxElement.isNull()) {
2402 maxValue = maxElement.asText();
2404 rangeConstraint.setRangeMinValue(minValue);
2405 rangeConstraint.setRangeMaxValue(maxValue);
2406 return rangeConstraint;
2412 private PropertyConstraint deserializeValidValuesConstraint(JsonNode value) {
2413 ArrayNode rangeArray = (ArrayNode) value;
2414 if (rangeArray.size() == 0) {
2415 log.error("The valid values constraint content is invalid. value = {}", value);
2417 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2418 List<String> validValues = new ArrayList<>();
2419 for (JsonNode jsonElement : rangeArray) {
2420 String item = jsonElement.asText();
2421 validValues.add(item);
2423 vvConstraint.setValidValues(validValues);
2424 return vvConstraint;