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.be.model.tosca.constraints.ConstraintUtil.convertToComparable;
23 import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR;
25 import com.fasterxml.jackson.core.ObjectCodec;
26 import com.fasterxml.jackson.databind.DeserializationContext;
27 import com.fasterxml.jackson.databind.JsonNode;
28 import com.fasterxml.jackson.databind.node.ArrayNode;
29 import com.google.common.collect.Lists;
30 import com.google.common.collect.Maps;
31 import com.google.gson.JsonArray;
32 import com.google.gson.JsonDeserializationContext;
33 import com.google.gson.JsonDeserializer;
34 import com.google.gson.JsonElement;
35 import com.google.gson.JsonObject;
36 import com.google.gson.JsonParseException;
37 import com.google.gson.JsonParser;
38 import com.google.gson.JsonPrimitive;
39 import com.google.gson.JsonSerializationContext;
40 import com.google.gson.JsonSerializer;
41 import com.google.gson.JsonSyntaxException;
42 import fj.data.Either;
43 import java.io.IOException;
44 import java.lang.reflect.InvocationTargetException;
45 import java.lang.reflect.Type;
46 import java.util.ArrayList;
47 import java.util.Collection;
48 import java.util.Collections;
49 import java.util.HashMap;
50 import java.util.Iterator;
51 import java.util.List;
53 import java.util.Map.Entry;
55 import java.util.function.Consumer;
56 import java.util.regex.Matcher;
57 import java.util.regex.Pattern;
58 import java.util.stream.Collectors;
59 import org.apache.commons.collections.CollectionUtils;
60 import org.apache.commons.collections.MapUtils;
61 import org.apache.commons.lang3.StringUtils;
62 import org.apache.commons.lang3.tuple.ImmutablePair;
63 import org.apache.tinkerpop.gremlin.structure.Edge;
64 import org.apache.tinkerpop.gremlin.structure.Vertex;
65 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
66 import org.janusgraph.core.JanusGraph;
67 import org.janusgraph.core.JanusGraphVertex;
68 import org.janusgraph.core.JanusGraphVertexProperty;
69 import org.openecomp.sdc.be.config.BeEcompErrorManager;
70 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
71 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
72 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
73 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
74 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
75 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
76 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
77 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
78 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
79 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
80 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
81 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
82 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
83 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
84 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
85 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
86 import org.openecomp.sdc.be.model.Component;
87 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
88 import org.openecomp.sdc.be.model.DataTypeDefinition;
89 import org.openecomp.sdc.be.model.IComplexDefaultValue;
90 import org.openecomp.sdc.be.model.PropertyConstraint;
91 import org.openecomp.sdc.be.model.PropertyDefinition;
92 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
93 import org.openecomp.sdc.be.model.operations.api.IPropertyOperation;
94 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
95 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
96 import org.openecomp.sdc.be.model.tosca.ToscaType;
97 import org.openecomp.sdc.be.model.tosca.constraints.EqualConstraint;
98 import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint;
99 import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
100 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
101 import org.openecomp.sdc.be.model.tosca.constraints.LengthConstraint;
102 import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
103 import org.openecomp.sdc.be.model.tosca.constraints.LessThanConstraint;
104 import org.openecomp.sdc.be.model.tosca.constraints.MaxLengthConstraint;
105 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
106 import org.openecomp.sdc.be.model.tosca.constraints.PatternConstraint;
107 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
108 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
109 import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator;
110 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
111 import org.openecomp.sdc.be.resources.data.DataTypeData;
112 import org.openecomp.sdc.be.resources.data.ModelData;
113 import org.openecomp.sdc.be.resources.data.PropertyData;
114 import org.openecomp.sdc.be.resources.data.PropertyValueData;
115 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
116 import org.openecomp.sdc.be.resources.data.UniqueIdData;
117 import org.openecomp.sdc.common.log.wrappers.Logger;
118 import org.springframework.beans.factory.annotation.Autowired;
120 @org.springframework.stereotype.Component("property-operation")
121 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
123 private static final String AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS = "After retrieving DERIVED_FROM node of {}. status is {}";
124 private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
125 private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
126 private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
127 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
128 private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS = "Failed to associate resource {} to property {} in graph. status is {}";
129 private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
130 private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
131 private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
132 private static final String PROPERTY = "Property";
133 private static final String UPDATE_DATA_TYPE = "UpdateDataType";
134 private static final Logger log = Logger.getLogger(PropertyOperation.class.getName());
135 private final DerivedFromOperation derivedFromOperation;
136 private ToscaFunctionValidator toscaFunctionValidator;
137 private DataTypeOperation dataTypeOperation;
140 public PropertyOperation(final HealingJanusGraphGenericDao janusGraphGenericDao, final DerivedFromOperation derivedFromOperation) {
141 this.janusGraphGenericDao = janusGraphGenericDao;
142 this.derivedFromOperation = derivedFromOperation;
146 public void setToscaFunctionValidator(final ToscaFunctionValidator toscaFunctionValidator) {
147 this.toscaFunctionValidator = toscaFunctionValidator;
150 //circular dependency DataTypeOperation->ModelOperation->ModelElementOperation->PropertyOperation
152 public void setDataTypeOperation(DataTypeOperation dataTypeOperation) {
153 this.dataTypeOperation = dataTypeOperation;
156 public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
157 log.debug("The object returned after create property is {}", propertyDataResult);
158 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
159 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
160 propertyDefResult.setName(propertyName);
161 return propertyDefResult;
164 public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
165 Either<PropertyData, JanusGraphOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
166 if (either.isRight()) {
167 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
168 return Either.right(storageStatus);
170 return Either.left(either.left().value());
174 * @param propertyDefinition
178 public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
179 log.trace("Going to validate property type and value. {}", propertyDefinition);
180 String propertyType = propertyDefinition.getType();
181 String value = propertyDefinition.getDefaultValue();
182 ToscaPropertyType type = getType(propertyType);
184 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
185 if (dataTypeDefinition == null) {
186 log.debug("The type {} of property cannot be found.", propertyType);
187 return StorageOperationStatus.INVALID_TYPE;
189 return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
191 String innerType = null;
192 Either<String, JanusGraphOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
193 if (checkInnerType.isRight()) {
194 return StorageOperationStatus.INVALID_TYPE;
196 innerType = checkInnerType.left().value();
197 log.trace("After validating property type {}", propertyType);
198 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
199 if (!isValidProperty) {
200 log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
201 return StorageOperationStatus.INVALID_VALUE;
203 PropertyValueConverter converter = type.getConverter();
204 if (isEmptyValue(value)) {
205 log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
206 propertyDefinition.setDefaultValue(EMPTY_VALUE);
207 } else if (!isEmptyValue(value)) {
208 String convertedValue = converter.convert(value, innerType, dataTypes);
209 propertyDefinition.setDefaultValue(convertedValue);
211 return StorageOperationStatus.OK;
214 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition,
216 ResourceMetadataData resourceData = new ResourceMetadataData();
217 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
218 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
219 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
220 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
221 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
222 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
223 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
224 if (createNodeResult.isRight()) {
225 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
226 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
227 return Either.right(operationStatus);
229 Map<String, Object> props = new HashMap<>();
230 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
231 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
232 .createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
233 if (createRelResult.isRight()) {
234 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
235 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
236 return Either.right(operationStatus);
238 return Either.left(createNodeResult.left().value());
241 public JanusGraphOperationStatus addPropertyToGraphByVertex(JanusGraphVertex metadataVertex, String propertyName,
242 PropertyDefinition propertyDefinition, String resourceId) {
243 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
244 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
245 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
246 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
247 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData);
248 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
249 if (createNodeResult.isRight()) {
250 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
251 log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
252 return operationStatus;
254 Map<String, Object> props = new HashMap<>();
255 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
256 JanusGraphVertex propertyVertex = createNodeResult.left().value();
257 JanusGraphOperationStatus createRelResult = janusGraphGenericDao.createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
258 if (!createRelResult.equals(JanusGraphOperationStatus.OK)) {
259 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
260 return createRelResult;
262 return createRelResult;
265 public JanusGraphGenericDao getJanusGraphGenericDao() {
266 return janusGraphGenericDao;
272 * @param janusGraphGenericDao
274 public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
275 this.janusGraphGenericDao = janusGraphGenericDao;
278 public Either<PropertyData, JanusGraphOperationStatus> deletePropertyFromGraph(String propertyId) {
279 log.debug("Before deleting property from graph {}", propertyId);
280 return janusGraphGenericDao.deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
283 public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition,
284 Map<String, DataTypeDefinition> dataTypes) {
285 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
286 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
287 return Either.right(validateAndUpdateProperty);
289 Either<PropertyData, JanusGraphOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
290 if (either.isRight()) {
291 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
292 return Either.right(storageStatus);
294 return Either.left(either.left().value());
297 public Either<PropertyData, JanusGraphOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
298 if (log.isDebugEnabled()) {
299 log.debug("Before updating property on graph {}", propertyId);
301 // get the original property data
302 Either<PropertyData, JanusGraphOperationStatus> statusProperty = janusGraphGenericDao
303 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
304 if (statusProperty.isRight()) {
305 log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
306 return Either.right(statusProperty.right().value());
308 PropertyData orgPropertyData = statusProperty.left().value();
309 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
310 // create new property data to update
311 PropertyData newPropertyData = new PropertyData();
312 newPropertyData.setPropertyDataDefinition(propertyDefinition);
313 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
314 // update the original property data with new values
315 if (orgPropertyDataDefinition.getDefaultValue() == null) {
316 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
318 if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
319 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
322 if (orgPropertyDataDefinition.getDescription() == null) {
323 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
325 if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
326 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
329 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
330 orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
332 if (newPropertyData.getConstraints() != null) {
333 orgPropertyData.setConstraints(newPropertyData.getConstraints());
335 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
336 return janusGraphGenericDao.updateNode(orgPropertyData, PropertyData.class);
339 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition,
340 NodeTypeEnum nodeType, String uniqueId) {
341 return addPropertyToNodeType(propertyName, propertyDefinition, nodeType, uniqueId, true);
344 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(final String propertyName,
345 final PropertyDefinition propertyDefinition,
346 final NodeTypeEnum nodeType, final String uniqueId,
347 final boolean inTransaction) {
348 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
349 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
350 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
351 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
352 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
353 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
354 if (createNodeResult.isRight()) {
355 if (!inTransaction) {
356 janusGraphGenericDao.rollback();
358 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
359 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
360 return Either.right(operationStatus);
362 Map<String, Object> props = new HashMap<>();
363 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
364 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
365 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
366 Either<GraphRelation, JanusGraphOperationStatus> createRelResult =
367 janusGraphGenericDao.createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
368 if (createRelResult.isRight()) {
369 if (!inTransaction) {
370 janusGraphGenericDao.rollback();
372 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
373 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
374 return Either.right(operationStatus);
376 if (!inTransaction) {
377 janusGraphGenericDao.commit();
379 return Either.left(createNodeResult.left().value());
382 public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
383 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
384 Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
385 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
387 if (childrenNodes.isRight()) {
388 JanusGraphOperationStatus operationStatus = childrenNodes.right().value();
389 return Either.right(operationStatus);
391 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
392 if (values != null) {
393 for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
394 GraphEdge edge = immutablePair.getValue();
395 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
396 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
397 PropertyData propertyData = immutablePair.getKey();
398 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
399 resourceProps.put(propertyName, propertyDefinition);
402 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
403 return Either.left(resourceProps);
406 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
407 return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId).right()
408 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
411 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
412 Map<String, PropertyDefinition> newProperties) {
413 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
414 Map<String, PropertyDefinition> reallyNewProperties;
415 Map<String, PropertyData> unchangedPropsData;
416 if (oldPropertiesRes.isRight()) {
417 JanusGraphOperationStatus err = oldPropertiesRes.right().value();
418 if (err == JanusGraphOperationStatus.NOT_FOUND) {
419 reallyNewProperties = newProperties;
420 unchangedPropsData = Collections.emptyMap();
422 return Either.right(err);
425 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
426 reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
427 for (Entry<String, PropertyDefinition> oldEntry : oldProperties.entrySet()) {
428 String key = oldEntry.getKey();
429 PropertyDefinition newPropDef = newProperties != null ? newProperties.get(key) : null;
430 PropertyDefinition oldPropDef = oldEntry.getValue();
431 JanusGraphOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
432 if (status != JanusGraphOperationStatus.OK) {
433 return Either.right(status);
436 unchangedPropsData = oldProperties.entrySet().stream()
437 .collect(Collectors.toMap(Entry::getKey, e -> new PropertyData(e.getValue(), null)));
439 // add other properties
440 return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
444 * @param newProperties
445 * @param oldProperties
448 private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties,
449 Map<String, PropertyDefinition> oldProperties) {
450 return newProperties != null ? newProperties.entrySet().stream().filter(entry -> !oldProperties.containsKey(entry.getKey()))
451 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)) : null;
458 private JanusGraphOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
459 if (!isUpdateAllowed(newPropDef, oldPropDef)) {
460 return JanusGraphOperationStatus.MATCH_NOT_FOUND;
462 if (isUpdateRequired(newPropDef, oldPropDef)) {
463 modifyOldPropByNewOne(newPropDef, oldPropDef);
464 List<PropertyConstraint> constraints = oldPropDef.getConstraints();
465 PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
466 Either<PropertyData, JanusGraphOperationStatus> updateResult = janusGraphGenericDao.updateNode(node, PropertyData.class);
467 if (updateResult.isRight()) {
468 return updateResult.right().value();
471 return JanusGraphOperationStatus.OK;
478 private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
479 if (newPropDef == null) {
480 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
483 // If the property type is missing it's something that we could want to fix
484 if (oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
485 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
492 * Update only fields which modification is permitted.
497 private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
498 oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
499 oldPropDef.setDescription(newPropDef.getDescription());
500 oldPropDef.setRequired(newPropDef.isRequired());
501 // Type is updated to fix possible null type issue in janusGraph DB
502 oldPropDef.setType(newPropDef.getType());
505 private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
506 return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) || !StringUtils
507 .equals(oldPropDef.getDescription(), newPropDef.getDescription()) || oldPropDef.isRequired() != newPropDef.isRequired();
511 * Adds newProperties and returns in case of success (left part of Either) map of all properties i. e. added ones and contained in
516 * @param newProperties
517 * @param unchangedPropsData
520 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId,
521 Map<String, PropertyDefinition> newProperties,
522 Map<String, PropertyData> unchangedPropsData) {
523 return addPropertiesToElementType(uniqueId, nodeType, newProperties).left().map(m -> {
524 m.putAll(unchangedPropsData);
529 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType,
531 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
532 if (propertiesOfNodeRes.isRight()) {
533 JanusGraphOperationStatus status = propertiesOfNodeRes.right().value();
534 if (status == JanusGraphOperationStatus.NOT_FOUND) {
535 return Either.right(StorageOperationStatus.OK);
537 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
539 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
540 for (PropertyDefinition propertyDefinition : value.values()) {
541 String propertyUid = propertyDefinition.getUniqueId();
542 Either<PropertyData, JanusGraphOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
543 if (deletePropertyRes.isRight()) {
544 log.error("Failed to delete property with id {}", propertyUid);
545 JanusGraphOperationStatus status = deletePropertyRes.right().value();
546 if (status == JanusGraphOperationStatus.NOT_FOUND) {
547 status = JanusGraphOperationStatus.INVALID_ID;
549 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
552 log.debug("The properties deleted from node {} are {}", uniqueId, value);
553 return Either.left(value);
557 * 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
558 * (including derived from hierarchy)
562 * @param propertyName
563 * @param propertyType
566 public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
567 boolean result = false;
568 if (!CollectionUtils.isEmpty(properties)) {
569 for (PropertyDefinition propertyDefinition : properties) {
570 if (propertyDefinition.getName().equals(propertyName) && (propertyDefinition.getParentUniqueId().equals(resourceUid)
571 || !propertyDefinition.getType().equals(propertyType))) {
580 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType,
581 Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
582 if (rules == null || rules.isEmpty()) {
583 return new ImmutablePair<>(null, true);
585 for (PropertyRule rule : rules) {
586 String value = rule.getValue();
587 Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
588 if (updateResult.isRight()) {
589 Boolean status = updateResult.right().value();
591 return new ImmutablePair<>(value, status);
594 String newValue = null;
595 Object object = updateResult.left().value();
596 if (object != null) {
597 newValue = object.toString();
599 rule.setValue(newValue);
602 return new ImmutablePair<>(null, true);
605 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
606 String resourceInstanceId) {
607 List<PropertyRule> rules = resourceInstanceProperty.getRules();
609 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
610 rules = new ArrayList<>();
611 rules.add(propertyRule);
613 rules = sortRules(rules);
615 propertyValueData.setRules(rules);
618 private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
619 String resourceInstanceId) {
620 List<String> path = resourceInstanceProperty.getPath();
621 // FOR BC. Since old Property values on VFC/VF does not have rules on
625 // Update could be done on one level only, thus we can use this
627 // operation to avoid migration.
628 if (path == null || path.isEmpty()) {
629 path = new ArrayList<>();
630 path.add(resourceInstanceId);
632 PropertyRule propertyRule = new PropertyRule();
633 propertyRule.setRule(path);
634 propertyRule.setValue(propertyValueData.getValue());
638 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
639 // TODO: sort the rules by size and binary representation.
641 // (x, y, .+) --> 110 6 priority 1
643 // (x, .+, z) --> 101 5 priority 2
647 public ImmutablePair<JanusGraphOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
648 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
649 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllRes = this
650 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
651 if (getAllRes.isRight()) {
652 JanusGraphOperationStatus status = getAllRes.right().value();
653 log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
654 return new ImmutablePair<>(status, null);
656 List<ComponentInstanceProperty> list = getAllRes.left().value();
658 for (ComponentInstanceProperty instanceProperty : list) {
659 String propertyUniqueId = instanceProperty.getUniqueId();
660 String valueUniqueUid = instanceProperty.getValueUniqueUid();
661 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
662 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
663 log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
664 return new ImmutablePair<>(JanusGraphOperationStatus.ALREADY_EXIST, valueUniqueUid);
668 return new ImmutablePair<>(JanusGraphOperationStatus.NOT_FOUND, null);
671 public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
672 String resourceInstanceId) {
673 List<PropertyRule> currentRules = propertyValueData.getRules();
674 List<PropertyRule> rules = resourceInstanceProperty.getRules();
675 // if rules are not supported.
677 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
678 rules = new ArrayList<>();
679 rules.add(propertyRule);
680 if (currentRules != null) {
681 rules = mergeRules(currentRules, rules);
684 // Full mode. all rules are sent in update operation.
685 rules = sortRules(rules);
687 propertyValueData.setRules(rules);
690 private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
691 List<PropertyRule> mergedRules = new ArrayList<>();
692 if (newRules == null || newRules.isEmpty()) {
695 for (PropertyRule rule : currentRules) {
696 PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
697 mergedRules.add(propertyRule);
699 for (PropertyRule rule : newRules) {
700 PropertyRule foundRule = findRuleInList(rule, mergedRules);
701 if (foundRule != null) {
702 foundRule.setValue(rule.getValue());
704 mergedRules.add(rule);
710 private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
711 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
714 PropertyRule foundRule = null;
715 for (PropertyRule propertyRule : rules) {
716 if (rule.getRuleSize() != propertyRule.getRuleSize()) {
719 boolean equals = propertyRule.compareRule(rule);
721 foundRule = propertyRule;
729 * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
731 * @param resourceInstanceUid
734 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
735 String resourceInstanceUid) {
736 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
739 public Either<PropertyValueData, JanusGraphOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
740 Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
741 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
742 if (findResInstanceRes.isRight()) {
743 JanusGraphOperationStatus status = findResInstanceRes.right().value();
744 if (status == JanusGraphOperationStatus.NOT_FOUND) {
745 status = JanusGraphOperationStatus.INVALID_ID;
747 return Either.right(status);
749 Either<PropertyValueData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
750 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
751 if (findPropertyDefRes.isRight()) {
752 JanusGraphOperationStatus status = findPropertyDefRes.right().value();
753 if (status == JanusGraphOperationStatus.NOT_FOUND) {
754 status = JanusGraphOperationStatus.INVALID_ID;
756 return Either.right(status);
758 Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
759 .getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
760 if (relation.isRight()) {
761 // TODO: add error in case of error
762 JanusGraphOperationStatus status = relation.right().value();
763 if (status == JanusGraphOperationStatus.NOT_FOUND) {
764 status = JanusGraphOperationStatus.INVALID_ID;
766 return Either.right(status);
768 Either<PropertyValueData, JanusGraphOperationStatus> deleteNode = janusGraphGenericDao
769 .deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
770 if (deleteNode.isRight()) {
771 return Either.right(deleteNode.right().value());
773 PropertyValueData value = deleteNode.left().value();
774 return Either.left(value);
777 public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid,
778 String resourceInstanceId,
779 boolean inTransaction) {
780 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
782 Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = this
783 .removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
784 if (eitherStatus.isRight()) {
785 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId,
786 eitherStatus.right().value().name());
787 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
790 PropertyValueData propertyValueData = eitherStatus.left().value();
791 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
792 propertyValueResult.setUniqueId(resourceInstanceId);
793 propertyValueResult.setValue(propertyValueData.getValue());
794 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
795 result = Either.left(propertyValueResult);
799 if (!inTransaction) {
800 if (result == null || result.isRight()) {
801 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
802 janusGraphGenericDao.rollback();
804 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
805 janusGraphGenericDao.commit();
811 public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData,
812 ComponentInstanceProperty resourceInstanceProperty) {
813 String value = propertyValueData.getValue();
814 String uid = propertyValueData.getUniqueId();
815 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
816 instanceProperty.setPath(resourceInstanceProperty.getPath());
817 return instanceProperty;
821 public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
822 if (propertyDefinition == null) {
825 String innerType = null;
826 String propertyType = propertyDefinition.getType();
827 ToscaPropertyType type = getType(propertyType);
828 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
829 SchemaDefinition def = propertyDefinition.getSchema();
833 PropertyDataDefinition propDef = def.getProperty();
834 if (propDef == null) {
837 innerType = propDef.getType();
839 String value = propertyDefinition.getDefaultValue();
841 return isValidValue(type, value, innerType, dataTypes);
843 log.trace("The given type {} is not a pre defined one.", propertyType);
844 DataTypeDefinition foundDt = dataTypes.get(propertyType);
845 if (foundDt != null) {
846 return isValidComplexValue(foundDt, value, dataTypes);
853 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final String model) {
854 if (property == null) {
857 if (ToscaPropertyType.isValidType(property.getType()) == null) {
858 Either<Boolean, JanusGraphOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType(), model);
859 if (definedInDataTypes.isRight()) {
862 Boolean isExist = definedInDataTypes.left().value();
863 return isExist.booleanValue();
869 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final Map<String, DataTypeDefinition> dataTypes) {
870 if (property == null) {
873 return ToscaPropertyType.isValidType(property.getType()) != null || dataTypes.containsKey(property.getType());
877 public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
878 if (property == null) {
879 return new ImmutablePair<>(null, false);
881 SchemaDefinition schema;
882 PropertyDataDefinition innerProp;
883 String innerType = null;
884 if ((schema = property.getSchema()) != null) {
885 if ((innerProp = schema.getProperty()) != null) {
886 innerType = innerProp.getType();
889 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
890 if (innerToscaType == null) {
891 DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
892 if (dataTypeDefinition == null) {
893 log.debug("The inner type {} is not a data type.", innerType);
894 return new ImmutablePair<>(innerType, false);
896 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
899 return new ImmutablePair<>(innerType, true);
902 private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
903 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
904 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
905 return validateAndUpdate.right.booleanValue();
908 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
909 String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
910 Either<JanusGraphVertex, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
911 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
912 if (findResInstanceRes.isRight()) {
913 JanusGraphOperationStatus status = findResInstanceRes.right().value();
914 if (status == JanusGraphOperationStatus.NOT_FOUND) {
915 status = JanusGraphOperationStatus.INVALID_ID;
917 return Either.right(status);
919 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> propertyImplNodes = janusGraphGenericDao
920 .getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
921 if (propertyImplNodes.isRight()) {
922 JanusGraphOperationStatus status = propertyImplNodes.right().value();
923 return Either.right(status);
925 List<ImmutablePair<JanusGraphVertex, Edge>> list = propertyImplNodes.left().value();
926 if (list == null || list.isEmpty()) {
927 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
929 List<ComponentInstanceProperty> result = new ArrayList<>();
930 for (ImmutablePair<JanusGraphVertex, Edge> propertyValue : list) {
931 JanusGraphVertex propertyValueDataVertex = propertyValue.getLeft();
932 String propertyValueUid = (String) janusGraphGenericDao
933 .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
934 String value = (String) janusGraphGenericDao.getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
935 ImmutablePair<JanusGraphVertex, Edge> propertyDefPair = janusGraphGenericDao
936 .getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
937 if (propertyDefPair == null) {
938 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
940 Map<String, Object> properties = janusGraphGenericDao.getProperties(propertyValueDataVertex);
941 PropertyValueData propertyValueData = GraphElementFactory
942 .createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
943 String propertyUniqueId = (String) janusGraphGenericDao
944 .getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
945 ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
946 // set property original unique id
947 resourceInstanceProperty.setUniqueId(propertyUniqueId);
950 // TODO: esofer add resource id
951 resourceInstanceProperty.setParentUniqueId(null);
953 resourceInstanceProperty.setValue(value);
954 // set property value unique id
955 resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
957 resourceInstanceProperty.setRules(propertyValueData.getRules());
958 result.add(resourceInstanceProperty);
960 return Either.left(result);
964 * Find the default value from the list of component instances. Start the search from the second component instance
966 * @param pathOfComponentInstances
967 * @param propertyUniqueId
968 * @param defaultValue
971 public Either<String, JanusGraphOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances,
972 String propertyUniqueId, String defaultValue) {
973 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
974 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
975 return Either.left(defaultValue);
977 String result = defaultValue;
978 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
979 String compInstanceId = pathOfComponentInstances.get(i);
980 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> propertyValuesResult = this
981 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
982 log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
983 if (propertyValuesResult.isRight()) {
984 JanusGraphOperationStatus status = propertyValuesResult.right().value();
985 if (status != JanusGraphOperationStatus.NOT_FOUND) {
986 return Either.right(status);
991 ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
992 log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
993 if (foundCompInstanceProperty == null) {
996 List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i),
997 foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
998 log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
999 PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
1000 log.trace("Match rule is {}", matchedRule);
1001 if (matchedRule != null) {
1002 result = matchedRule.getValue();
1006 return Either.left(result);
1009 private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
1010 ComponentInstanceProperty result = null;
1014 for (ComponentInstanceProperty instProperty : list) {
1015 if (instProperty.getUniqueId().equals(propertyUniqueId)) {
1016 result = instProperty;
1023 private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
1024 if (rules != null) {
1027 rules = buildDefaultRule(compInstanceId, ruleSize, value);
1031 private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
1032 List<PropertyRule> rules = componentInstanceProperty.getRules();
1033 if (rules == null) {
1034 rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
1039 private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
1040 List<PropertyRule> rules = new ArrayList<>();
1041 List<String> rule = new ArrayList<>();
1042 rule.add(componentInstanceId);
1043 for (int i = 0; i < size - 1; i++) {
1044 rule.add(PropertyRule.getRuleAnyMatch());
1046 PropertyRule propertyRule = new PropertyRule(rule, value);
1047 rules.add(propertyRule);
1051 private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1052 PropertyRule propertyRule = null;
1053 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1054 String firstCompInstance = pathOfInstances.get(level);
1055 if (rules != null) {
1056 for (PropertyRule rule : rules) {
1057 int ruleSize = rule.getRule().size();
1058 // check the length of the rule equals to the length of the
1061 if (ruleSize != pathOfInstances.size() - level) {
1064 // check that the rule starts with correct component instance id
1065 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1068 String secondToken = rule.getToken(2);
1069 if (secondToken != null && (secondToken.equals(PropertyRule.getForceAll()) || secondToken.equals(PropertyRule.getALL()))) {
1070 propertyRule = rule;
1073 String patternStr = buildStringForMatch(rule.getRule(), 0);
1074 Pattern pattern = Pattern.compile(patternStr);
1075 Matcher matcher = pattern.matcher(stringForMatch);
1076 if (matcher.matches()) {
1077 if (log.isTraceEnabled()) {
1078 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1080 propertyRule = rule;
1085 return propertyRule;
1088 private boolean checkFirstItem(String left, String right) {
1089 if (left != null && left.equals(right)) {
1095 private String buildStringForMatch(List<String> pathOfInstances, int level) {
1096 StringBuilder builder = new StringBuilder();
1097 for (int i = level; i < pathOfInstances.size(); i++) {
1098 builder.append(pathOfInstances.get(i));
1099 if (i < pathOfInstances.size() - 1) {
1100 builder.append("#");
1103 return builder.toString();
1106 public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty,
1107 Map<String, ComponentInstanceProperty> instanceIdToValue) {
1108 List<String> pathOfInstances = instanceProperty.getPath();
1110 int size = pathOfInstances.size();
1111 int numberOfMatches = 0;
1112 for (String instanceId : pathOfInstances) {
1113 ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1114 if (componentInstanceProperty != null) {
1115 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1116 // If it is the first level instance, then update valueUniuqeId
1118 // parameter in order to know on update that
1120 // we should update and not create new node on graph.
1122 instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1123 instanceProperty.setRules(rules);
1125 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1128 String value = rule.getValue();
1129 if (numberOfMatches == 1) {
1130 instanceProperty.setValue(value);
1131 if (log.isDebugEnabled()) {
1132 log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1133 pathOfInstances, value);
1135 } else if (numberOfMatches == 2) {
1136 // In case of another property value match, then use the
1138 // value to be the default value of the property.
1139 instanceProperty.setDefaultValue(value);
1140 if (log.isDebugEnabled()) {
1141 log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1142 pathOfInstances, value);
1153 * Add data type to graph.
1155 * 1. Add data type node
1157 * 2. Add edge between the former node to its parent(if exists)
1159 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1161 * @param dataTypeDefinition
1164 private Either<DataTypeData, JanusGraphOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1165 log.debug("Got data type {}", dataTypeDefinition);
1166 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getModel(), dataTypeDefinition.getName());
1167 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1168 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1169 Either<DataTypeData, JanusGraphOperationStatus> createDataTypeResult = janusGraphGenericDao.createNode(dataTypeData, DataTypeData.class);
1170 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1171 if (createDataTypeResult.isRight()) {
1172 JanusGraphOperationStatus operationStatus = createDataTypeResult.right().value();
1173 log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1174 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1175 return Either.right(operationStatus);
1177 DataTypeData resultCTD = createDataTypeResult.left().value();
1178 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1179 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(),
1180 dataTypeDefinition.getModel(),
1182 if (addPropertiesToDataType.isRight()) {
1183 log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1184 return Either.right(addPropertiesToDataType.right().value());
1187 final Either<GraphRelation, JanusGraphOperationStatus> modelRelationship = addDataTypeToModel(dataTypeDefinition);
1188 if (modelRelationship.isRight()) {
1189 return Either.right(modelRelationship.right().value());
1192 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1193 if (derivedFrom != null) {
1194 final Either<DataTypeDefinition, JanusGraphOperationStatus> derivedFromDataType = getDataTypeByNameValidForModel(derivedFrom,
1195 dataTypeDefinition.getModel());
1196 if (derivedFromDataType.isRight()) {
1197 return Either.right(derivedFromDataType.right().value());
1200 log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1201 UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1202 final String deriveFromUid = derivedFromDataType.left().value().getUniqueId();
1203 UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1204 Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
1205 .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1206 log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1207 if (createRelation.isRight()) {
1208 return Either.right(createRelation.right().value());
1211 return Either.left(createDataTypeResult.left().value());
1214 private Either<GraphRelation, JanusGraphOperationStatus> addDataTypeToModel(final DataTypeDefinition dataTypeDefinition) {
1215 final String model = dataTypeDefinition.getModel();
1216 if (model == null) {
1217 return Either.left(null);
1219 final GraphNode from = new UniqueIdData(NodeTypeEnum.Model, UniqueIdBuilder.buildModelUid(model));
1220 final GraphNode to = new UniqueIdData(NodeTypeEnum.DataType, dataTypeDefinition.getUniqueId());
1221 log.info("Connecting model {} to type {}", from, to);
1222 return janusGraphGenericDao.createRelation(from, to, GraphEdgeLabels.MODEL_ELEMENT, Collections.emptyMap());
1225 private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1226 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1227 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1228 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1229 if (creationDate == null) {
1230 creationDate = System.currentTimeMillis();
1232 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1233 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1234 return dataTypeData;
1238 * add properties to capability type.
1240 * Per property, add a property node and associate it to the capability type
1246 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType(final String uniqueId, final String modelName,
1247 final List<PropertyDefinition> properties) {
1248 Map<String, PropertyData> propertiesData = new HashMap<>();
1249 if (properties != null && !properties.isEmpty()) {
1250 for (PropertyDefinition propertyDefinition : properties) {
1251 String propertyName = propertyDefinition.getName();
1252 String propertyType = propertyDefinition.getType();
1253 Either<Boolean, JanusGraphOperationStatus> validPropertyType = isValidPropertyType(propertyType, modelName);
1254 if (validPropertyType.isRight()) {
1255 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1256 return Either.right(validPropertyType.right().value());
1258 Boolean isValid = validPropertyType.left().value();
1259 if (isValid == null || !isValid.booleanValue()) {
1260 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1261 return Either.right(JanusGraphOperationStatus.INVALID_TYPE);
1263 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1264 .addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1265 if (addPropertyToNodeType.isRight()) {
1266 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1267 log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1268 BeEcompErrorManager.getInstance()
1269 .logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus,
1270 ErrorSeverity.ERROR);
1271 return Either.right(operationStatus);
1273 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1275 DataTypeData dataTypeData = new DataTypeData();
1276 dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1277 long modificationTime = System.currentTimeMillis();
1278 dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1279 Either<DataTypeData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao.updateNode(dataTypeData, DataTypeData.class);
1280 if (updateNode.isRight()) {
1281 JanusGraphOperationStatus operationStatus = updateNode.right().value();
1282 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1283 BeEcompErrorManager.getInstance()
1284 .logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1285 return Either.right(operationStatus);
1287 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1290 return Either.left(propertiesData);
1293 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByNameValidForModel(final String name, final String modelName) {
1294 final Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1295 .getNode(GraphPropertiesDictionary.NAME.getProperty(), name, DataTypeData.class, modelName);
1296 if (dataTypesRes.isRight()) {
1297 final JanusGraphOperationStatus status = dataTypesRes.right().value();
1298 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, name, status);
1299 return Either.right(status);
1301 final DataTypeData dataType = dataTypesRes.left().value();
1302 final DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(dataType.getDataTypeDataDefinition());
1303 final JanusGraphOperationStatus propertiesStatus = fillProperties(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1304 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1305 log.error(BUSINESS_PROCESS_ERROR, FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, dataTypeDefinition.getUniqueId());
1306 return Either.right(propertiesStatus);
1308 final Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1309 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeDefinition.getUniqueId(), GraphEdgeLabels.DERIVED_FROM,
1310 NodeTypeEnum.DataType,
1311 DataTypeData.class);
1312 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, dataTypeDefinition.getUniqueId(), parentNode);
1313 if (parentNode.isRight()) {
1314 final JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1315 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1316 log.error(BUSINESS_PROCESS_ERROR, "Failed to find the parent data type of data type {}. status is {}",
1317 dataTypeDefinition.getUniqueId(), janusGraphOperationStatus);
1318 return Either.right(janusGraphOperationStatus);
1321 // derived from node was found
1322 final ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1323 final DataTypeData parentDataType = immutablePair.getKey();
1324 final Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentDataType.getUniqueId());
1325 if (dataTypeByUid.isRight()) {
1326 return Either.right(dataTypeByUid.right().value());
1328 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1329 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1331 return Either.left(dataTypeDefinition);
1335 * Build Data type object from graph by unique id
1340 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUid(String uniqueId) {
1341 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1342 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1343 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1344 if (dataTypesRes.isRight()) {
1345 JanusGraphOperationStatus status = dataTypesRes.right().value();
1346 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1347 return Either.right(status);
1349 DataTypeData ctData = dataTypesRes.left().value();
1350 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1351 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1352 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1353 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1354 return Either.right(propertiesStatus);
1356 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1357 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1358 DataTypeData.class);
1359 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1360 if (parentNode.isRight()) {
1361 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1362 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1363 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1364 result = Either.right(janusGraphOperationStatus);
1368 // derived from node was found
1369 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1370 DataTypeData parentCT = immutablePair.getKey();
1371 String parentUniqueId = parentCT.getUniqueId();
1372 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1373 if (dataTypeByUid.isRight()) {
1374 return Either.right(dataTypeByUid.right().value());
1376 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1377 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1379 result = Either.left(dataTypeDefinition);
1383 private JanusGraphOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1384 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this
1385 .findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1386 if (findPropertiesOfNode.isRight()) {
1387 JanusGraphOperationStatus janusGraphOperationStatus = findPropertiesOfNode.right().value();
1388 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, janusGraphOperationStatus);
1389 if (JanusGraphOperationStatus.NOT_FOUND.equals(janusGraphOperationStatus)) {
1390 return JanusGraphOperationStatus.OK;
1392 return janusGraphOperationStatus;
1395 Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1396 if (properties != null && !properties.isEmpty()) {
1397 List<PropertyDefinition> listOfProps = new ArrayList<>();
1398 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1399 String propName = entry.getKey();
1400 PropertyDefinition propertyDefinition = entry.getValue();
1401 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1402 newPropertyDefinition.setName(propName);
1403 listOfProps.add(newPropertyDefinition);
1405 dataTypeDefinition.setProperties(listOfProps);
1407 return JanusGraphOperationStatus.OK;
1411 private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1412 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1414 Either<DataTypeData, JanusGraphOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1415 if (eitherStatus.isRight()) {
1416 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1417 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1418 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1421 DataTypeData capabilityTypeData = eitherStatus.left().value();
1422 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1423 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1424 result = Either.left(dataTypeDefResult);
1428 if (!inTransaction) {
1429 if (result == null || result.isRight()) {
1430 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1431 janusGraphGenericDao.rollback();
1433 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1434 janusGraphGenericDao.commit();
1441 public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1442 return addDataType(dataTypeDefinition, true);
1446 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel,
1447 final boolean inTransaction) {
1448 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1450 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByNameValidForModel(name, validForModel);
1451 if (ctResult.isRight()) {
1452 JanusGraphOperationStatus status = ctResult.right().value();
1453 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1454 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1456 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1459 result = Either.left(ctResult.left().value());
1462 if (!inTransaction) {
1463 if (result == null || result.isRight()) {
1464 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1465 janusGraphGenericDao.rollback();
1467 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1468 janusGraphGenericDao.commit();
1475 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel) {
1476 return getDataTypeByName(name, validForModel, true);
1479 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByUidWithoutDerived(String uid, boolean inTransaction) {
1480 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1482 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1483 if (ctResult.isRight()) {
1484 JanusGraphOperationStatus status = ctResult.right().value();
1485 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1486 log.error(BUSINESS_PROCESS_ERROR, "Failed to retrieve information on data type {} status is {}", uid, status);
1488 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1491 result = Either.left(ctResult.left().value());
1494 if (!inTransaction) {
1495 if (result == null || result.isRight()) {
1496 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1497 janusGraphGenericDao.rollback();
1499 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1500 janusGraphGenericDao.commit();
1506 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1507 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1508 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1509 if (dataTypesRes.isRight()) {
1510 JanusGraphOperationStatus status = dataTypesRes.right().value();
1511 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1512 return Either.right(status);
1514 DataTypeData ctData = dataTypesRes.left().value();
1515 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1516 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1517 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1518 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1519 return Either.right(propertiesStatus);
1521 return Either.left(dataTypeDefinition);
1525 * convert between graph Node object to Java object
1527 * @param dataTypeData
1530 protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1531 log.debug("The object returned after create data type is {}", dataTypeData);
1532 return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1535 private Either<Boolean, JanusGraphOperationStatus> isValidPropertyType(String propertyType, final String modelName) {
1536 if (propertyType == null || propertyType.isEmpty()) {
1537 return Either.left(false);
1539 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1540 if (toscaPropertyType == null) {
1541 return isDefinedInDataTypes(propertyType, modelName);
1543 return Either.left(true);
1547 public Either<Boolean, JanusGraphOperationStatus> isDefinedInDataTypes(final String propertyType, final String modelName) {
1548 Either<DataTypeDefinition, JanusGraphOperationStatus> dataType = getDataTypeByNameValidForModel(propertyType, modelName);
1549 if (dataType.isRight()) {
1550 JanusGraphOperationStatus status = dataType.right().value();
1551 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1552 return Either.left(false);
1554 return Either.right(status);
1556 return Either.left(true);
1559 public Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> getAllDataTypes() {
1560 final Map<String, Map<String, DataTypeDefinition>> dataTypes = new HashMap<>();
1561 Either<Map<String, Map<String, DataTypeDefinition>>, JanusGraphOperationStatus> result = Either.left(dataTypes);
1562 final Map<String, DataTypeDefinition> allDataTypesFound = new HashMap<>();
1564 final Map<String, List<String>> dataTypeUidstoModels = dataTypeOperation.getAllDataTypeUidsToModels();
1566 if (dataTypeUidstoModels != null) {
1567 log.trace("Number of data types to load is {}", dataTypeUidstoModels.size());
1568 for (Map.Entry<String, List<String>> entry : dataTypeUidstoModels.entrySet()) {
1569 log.trace("Going to fetch data type with uid {}", entry.getKey());
1570 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this
1571 .getAndAddDataTypeByUid(entry.getKey(), allDataTypesFound);
1572 if (dataTypeByUid.isRight()) {
1573 JanusGraphOperationStatus status = dataTypeByUid.right().value();
1574 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1575 status = JanusGraphOperationStatus.INVALID_ID;
1577 return Either.right(status);
1579 for (final String model : entry.getValue()) {
1580 if (!dataTypes.containsKey(model)) {
1581 dataTypes.put(model, new HashMap<String, DataTypeDefinition>());
1583 DataTypeDefinition dataTypeDefinition = allDataTypesFound.get(entry.getKey());
1584 dataTypes.get(model).put(dataTypeDefinition.getName(), dataTypeDefinition);
1589 if (log.isTraceEnabled()) {
1590 if (result.isRight()) {
1591 log.trace("After fetching all data types {}", result);
1593 Map<String, Map<String, DataTypeDefinition>> map = result.left().value();
1595 String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1596 log.trace("After fetching all data types {} ", types);
1604 * Build Data type object from graph by unique id
1609 private Either<DataTypeDefinition, JanusGraphOperationStatus> getAndAddDataTypeByUid(String uniqueId,
1610 Map<String, DataTypeDefinition> allDataTypes) {
1611 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1612 if (allDataTypes.containsKey(uniqueId)) {
1613 return Either.left(allDataTypes.get(uniqueId));
1615 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1616 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1617 if (dataTypesRes.isRight()) {
1618 JanusGraphOperationStatus status = dataTypesRes.right().value();
1619 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1620 return Either.right(status);
1622 DataTypeData ctData = dataTypesRes.left().value();
1623 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1624 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1625 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1626 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1627 return Either.right(propertiesStatus);
1629 allDataTypes.put(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1630 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1631 if (allDataTypes.containsKey(derivedFrom)) {
1632 DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1633 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1634 return Either.left(dataTypeDefinition);
1636 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1637 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1638 DataTypeData.class);
1639 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1640 if (parentNode.isRight()) {
1641 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1642 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1643 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1644 result = Either.right(janusGraphOperationStatus);
1648 // derived from node was found
1649 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1650 DataTypeData parentCT = immutablePair.getKey();
1651 String parentUniqueId = parentCT.getUniqueId();
1652 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1653 if (dataTypeByUid.isRight()) {
1654 return Either.right(dataTypeByUid.right().value());
1656 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1657 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1658 final var model = getModel(uniqueId);
1659 if (StringUtils.isNotEmpty(model)) {
1660 dataTypeDefinition.setModel(model);
1663 result = Either.left(dataTypeDefinition);
1667 private String getModel(final String uniqueId) {
1668 final Either<ImmutablePair<ModelData, GraphEdge>, JanusGraphOperationStatus> model = janusGraphGenericDao.getParentNode(
1669 UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.MODEL_ELEMENT,
1670 NodeTypeEnum.Model, ModelData.class);
1671 return model.isLeft() ? model.left().value().getLeft().getName() : StringUtils.EMPTY;
1674 public Either<String, JanusGraphOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
1675 String propertyType = propDataDef.getType();
1676 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
1677 return getInnerType(type, propDataDef::getSchema);
1680 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType,
1681 Map<String, DataTypeDefinition> dataTypes) {
1682 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
1683 final ToscaPropertyType type = getType(propertyType);
1686 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
1687 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter
1688 .validateAndUpdate(value, dataTypeDefinition, dataTypes);
1689 if (Boolean.FALSE.equals(validateResult.right)) {
1690 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
1691 return Either.right(false);
1693 JsonElement jsonElement = validateResult.left;
1694 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
1695 return Either.left(valueFromJsonElement);
1697 log.trace("before validating property type {}", propertyType);
1698 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
1699 if (!isValidProperty) {
1700 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
1701 return Either.right(false);
1704 Object convertedValue = value;
1705 if (!isEmptyValue(value) && isValidate) {
1706 PropertyValueConverter converter = type.getConverter();
1707 convertedValue = converter.convert(value, innerType, dataTypes);
1709 return Either.left(convertedValue);
1712 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType,
1713 Map<String, DataTypeDefinition> dataTypes) {
1714 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
1717 public Either<Object, Boolean> validateAndUpdatePropertyValue(final Component containerComponent, final PropertyDataDefinition property,
1718 final Map<String, DataTypeDefinition> dataTypes) {
1719 if (property.isToscaFunction()) {
1720 toscaFunctionValidator.validate(property, containerComponent);
1721 property.setValue(property.getToscaFunction().getValue());
1722 return Either.left(property.getValue());
1724 Either<String, JanusGraphOperationStatus> checkInnerType = checkInnerType(property);
1725 if (checkInnerType.isRight()) {
1726 return Either.right(false);
1728 final String innerType = checkInnerType.left().value();
1729 return validateAndUpdatePropertyValue(property.getType(), property.getValue(), true, innerType, dataTypes);
1732 public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType,
1734 return this.findPropertiesOfNode(nodeType, uniqueId).right().bind(this::handleNotFoundProperties).left()
1735 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
1738 private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(
1739 JanusGraphOperationStatus janusGraphOperationStatus) {
1740 if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
1741 return Either.left(new HashMap<>());
1743 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1746 private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId,
1747 NodeTypeEnum nodeType,
1749 Collection<PropertyDefinition> nodeProps) {
1750 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
1751 String currentNodeUid = uniqueId;
1752 Either<T, StorageOperationStatus> derivedFrom;
1753 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
1754 currentNodeUid = derivedFrom.left().value().getUniqueId();
1755 JanusGraphOperationStatus janusGraphOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
1756 if (janusGraphOperationStatus != JanusGraphOperationStatus.OK) {
1757 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
1758 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1761 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
1762 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
1765 private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
1766 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
1770 * @Override public PropertyOperation getPropertyOperation() { return this; }
1772 public JanusGraphOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
1773 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
1774 if (findPropertiesRes.isRight()) {
1775 return findPropertiesRes.right().value();
1777 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
1778 if (properties != null) {
1779 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
1780 propertySetter.accept(propertiesAsList);
1782 return JanusGraphOperationStatus.OK;
1785 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType) {
1786 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
1787 if (findPropertiesOfNode.isRight()) {
1788 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
1789 if (findPropertiesOfNode.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
1790 return Either.left(Maps.newHashMap());
1792 return findPropertiesOfNode;
1794 return findPropertiesOfNode;
1798 * add properties to element type.
1800 * Per property, add a property node and associate it to the element type
1803 * @param propertiesMap
1806 protected Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType,
1807 Map<String, PropertyDefinition> propertiesMap) {
1808 Map<String, PropertyData> propertiesData = new HashMap<>();
1809 if (propertiesMap != null) {
1810 for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
1811 String propertyName = propertyDefinitionEntry.getKey();
1812 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1813 .addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
1814 if (addPropertyToNodeType.isRight()) {
1815 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1816 log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName,
1818 return Either.right(operationStatus);
1820 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1823 return Either.left(propertiesData);
1826 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType,
1827 List<PropertyDefinition> properties) {
1828 Map<String, PropertyDefinition> propMap;
1829 if (properties == null) {
1832 propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
1834 return addPropertiesToElementType(uniqueId, elementType, propMap);
1838 public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1839 DataTypeDefinition oldDataTypeDefinition) {
1840 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
1843 private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1844 DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
1845 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1847 List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
1848 List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
1849 String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
1850 String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
1851 String dataTypeName = newDataTypeDefinition.getName();
1852 List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
1853 if (isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, propertiesToAdd)
1854 || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
1855 log.debug("The new data type {} is invalid.", dataTypeName);
1856 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
1859 if (CollectionUtils.isEmpty(propertiesToAdd)) {
1860 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
1861 result = Either.right(StorageOperationStatus.OK);
1864 Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
1865 if (MapUtils.isNotEmpty(newDescriptions)) {
1866 JanusGraphOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(),
1868 if (updatePropertiesStatus != JanusGraphOperationStatus.OK) {
1869 log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}",
1870 oldDataTypeDefinition, updatePropertiesStatus);
1871 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1872 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatePropertiesStatus));
1876 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(
1877 oldDataTypeDefinition.getUniqueId(), oldDataTypeDefinition.getModel(), propertiesToAdd);
1878 if (addPropertiesToDataType.isRight()) {
1879 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition,
1880 addPropertiesToDataType.right().value().name());
1881 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1882 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToDataType.right().value()));
1885 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
1886 if (dataTypeByUid.isRight()) {
1887 JanusGraphOperationStatus status = addPropertiesToDataType.right().value();
1888 log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
1889 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
1890 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
1892 result = Either.left(dataTypeByUid.left().value());
1897 if (!inTransaction) {
1898 if (result == null || result.isRight()) {
1899 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1900 janusGraphGenericDao.rollback();
1902 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1903 janusGraphGenericDao.commit();
1909 private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties,
1910 List<PropertyDefinition> outputPropertiesToAdd) {
1911 if (newProperties != null && oldProperties != null) {
1912 Map<String, PropertyDefinition> newPropsMapper = newProperties.stream()
1913 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1914 Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream()
1915 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1916 for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
1917 String propName = newPropertyEntry.getKey();
1918 PropertyDefinition propDef = newPropertyEntry.getValue();
1919 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
1920 if (oldPropertyDefinition == null) {
1921 log.debug("New property {} received in the data type {}", propName, dataTypeName);
1922 outputPropertiesToAdd.add(propDef);
1925 String oldType = oldPropertyDefinition.getType();
1926 String oldEntryType = getEntryType(oldPropertyDefinition);
1927 String newType = propDef.getType();
1928 String newEntryType = getEntryType(propDef);
1929 if (!oldType.equals(newType)) {
1930 log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType,
1934 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
1935 log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName,
1936 oldEntryType, newEntryType);
1944 private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
1945 if (oldEntryType == null && newEntryType == null) {
1947 } else if (oldEntryType != null && newEntryType != null) {
1948 return oldEntryType.equals(newEntryType);
1954 private String getEntryType(PropertyDefinition oldPropertyDefinition) {
1955 String entryType = null;
1956 SchemaDefinition schema = oldPropertyDefinition.getSchema();
1957 if (schema != null) {
1958 PropertyDataDefinition schemaProperty = schema.getProperty();
1959 if (schemaProperty != null) {
1960 entryType = schemaProperty.getType();
1966 private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
1967 if (newDerivedFromName != null) {
1968 boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
1970 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1971 oldDerivedFromName);
1974 } else if (oldDerivedFromName == null) {
1976 } else {// new=null, old != null
1977 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1978 oldDerivedFromName);
1988 public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
1989 Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
1990 if (graphResult.isRight()) {
1991 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
1993 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
1994 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
1995 if (vertexService.isRight()) {
1996 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
1997 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
1999 Vertex vertex = vertexService.left().value();
2000 VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
2001 Integer counter = 0;
2002 if (vertexProperty.isPresent() && vertexProperty.value() != null) {
2003 counter = (Integer) vertexProperty.value();
2006 vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
2007 return Either.left(counter);
2010 public Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesUniqueness(
2011 Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
2012 Either<List<PropertyDefinition>, JanusGraphOperationStatus> result = Either.left(properties);
2013 for (PropertyDefinition property : properties) {
2014 JanusGraphOperationStatus status = validatePropertyUniqueness(inheritedProperties, property);
2015 if (status != JanusGraphOperationStatus.OK) {
2016 result = Either.right(status);
2024 * Validates uniqueness of examined property by comparing it with properties in propertiesOfType and updates if need type and inner type of the
2027 private JanusGraphOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2028 String propertyName = property.getName();
2029 String propertyType = property.getType();
2030 JanusGraphOperationStatus result = JanusGraphOperationStatus.OK;
2031 if (inheritedProperties.containsKey(propertyName)) {
2032 PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2033 if (typesMismatch(propertyType, defaultProperty.getType())) {
2034 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2035 result = JanusGraphOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2037 property.setType(defaultProperty.getType());
2038 String innerType = defaultProperty.getSchemaType();
2039 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2040 if (schemaProperty != null) {
2041 schemaProperty.setType(innerType);
2048 private boolean typesMismatch(String type1, String type2) {
2049 return type1 != null && type2 != null && !type2.equals(type1);
2052 public <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllTypePropertiesFromAllDerivedFrom(
2053 String nextParentUid, NodeTypeEnum nodeType, Class<T> clazz) {
2054 Map<String, PropertyDefinition> allProperies = new HashMap<>();
2055 return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2058 private <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getTypePropertiesFromDerivedFromRecursively(
2059 String nextParentUid, Map<String, PropertyDefinition> allProperies, NodeTypeEnum nodeType, Class<T> clazz) {
2060 JanusGraphOperationStatus error;
2061 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
2062 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2063 if (childrenNodes.isRight()) {
2064 if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
2065 error = childrenNodes.right().value();
2066 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid,
2068 return Either.right(error);
2070 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.",
2072 return Either.left(allProperies);
2075 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2076 if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
2077 error = allPropertiesOfTypeRes.right().value();
2079 "#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}",
2080 nextParentUid, error);
2081 return Either.right(error);
2082 } else if (allPropertiesOfTypeRes.isLeft()) {
2083 if (allProperies.isEmpty()) {
2084 allProperies.putAll(allPropertiesOfTypeRes.left().value());
2086 allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey()))
2087 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2090 return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType,
2095 private JanusGraphOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2096 if (MapUtils.isNotEmpty(newDescriptions)) {
2097 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getDataTypePropertiesRes = janusGraphGenericDao
2098 .getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2099 if (getDataTypePropertiesRes.isRight()) {
2100 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2101 return getDataTypePropertiesRes.right().value();
2103 getDataTypePropertiesRes.left().value().stream().filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2104 .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2106 return JanusGraphOperationStatus.OK;
2109 private JanusGraphVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<JanusGraphVertex, Edge> pair) {
2110 return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2113 private String getPropertyNameFromEdge(ImmutablePair<JanusGraphVertex, Edge> pair) {
2114 return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2117 private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2118 Map<String, PropertyDefinition> newPropertiesMap = newProperties.stream().collect(Collectors.toMap(PropertyDefinition::getName, p -> p));
2119 return oldProperties.stream()
2120 .filter(p -> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2121 .collect(Collectors.toMap(PropertyDefinition::getName, p -> newPropertiesMap.get(p.getName()).getDescription()));
2124 private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty) {
2125 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2128 if (StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2131 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())) {
2134 return property.getDescription().equals(otherProperty.getDescription());
2137 public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
2140 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
2141 JsonObject result = new JsonObject();
2142 JsonArray jsonArray = new JsonArray();
2143 if (src instanceof InRangeConstraint) {
2144 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
2145 jsonArray.add(JsonParser.parseString(String.valueOf(rangeConstraint.getMin())));
2146 jsonArray.add(JsonParser.parseString(String.valueOf(rangeConstraint.getMax())));
2147 result.add("inRange", jsonArray);
2148 } else if (src instanceof GreaterThanConstraint) {
2149 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
2150 jsonArray.add(JsonParser.parseString(String.valueOf(greaterThanConstraint.getGreaterThan())));
2151 result.add("greaterThan", jsonArray);
2152 } else if (src instanceof LessThanConstraint) {
2153 LessThanConstraint lessThanConstraint = (LessThanConstraint) src;
2154 jsonArray.add(JsonParser.parseString(String.valueOf(lessThanConstraint.getLessThan())));
2155 result.add("lessThan", jsonArray);
2156 } else if (src instanceof LessOrEqualConstraint) {
2157 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
2158 jsonArray.add(JsonParser.parseString(String.valueOf(lessOrEqualConstraint.getLessOrEqual())));
2159 result.add("lessOrEqual", jsonArray);
2161 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
2167 public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
2170 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
2171 PropertyConstraint propertyConstraint = null;
2172 final Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
2173 if (!set.isEmpty()) {
2174 final Entry<String, JsonElement> element = set.iterator().next();
2175 final String key = element.getKey();
2176 final ConstraintType constraintType = ConstraintType.findByType(key).orElse(null);
2177 if (constraintType == null) {
2178 log.warn("ConstraintType was not found for constraint name:{}", key);
2180 if (set.size() == 1 || (set.size() == 2 && ConstraintType.PATTERN == constraintType)) {
2181 final JsonElement value = element.getValue();
2182 final Object typedValue = getTypedValue(value);
2183 switch (constraintType) {
2185 if (typedValue != null) {
2186 log.debug("Before adding value to EqualConstraint object. value = {}", typedValue);
2187 propertyConstraint = new EqualConstraint(typedValue);
2189 log.warn("The value of EqualConstraint is null");
2193 if (typedValue instanceof ArrayList) {
2194 List<Object> rangeArray = (ArrayList<Object>) typedValue;
2195 if (rangeArray.size() != 2 || rangeArray.contains("")) {
2196 log.error("The range constraint content is invalid. value = {}", typedValue);
2197 throw new JsonSyntaxException("The range constraint content is invalid");
2199 Object minValue = rangeArray.get(0);
2200 Object maxValue = rangeArray.get(1);
2201 InRangeConstraint rangeConstraint = new InRangeConstraint(Lists.newArrayList(minValue, maxValue));
2202 rangeConstraint.setMin(convertToComparable(ToscaType.RANGE, String.valueOf(minValue)));
2203 rangeConstraint.setMax(convertToComparable(ToscaType.RANGE, String.valueOf(maxValue)));
2204 propertyConstraint = rangeConstraint;
2207 log.warn("The value of InRangeConstraint is null");
2211 if (typedValue != null) {
2212 log.debug("Before adding value to GreaterThanConstraint object. value = {}", typedValue);
2213 propertyConstraint = new GreaterThanConstraint(typedValue);
2215 log.warn("The value of GreaterThanConstraint is null");
2219 if (typedValue != null) {
2220 log.debug("Before adding value to LessThanConstraint object. value = {}", typedValue);
2221 propertyConstraint = new LessThanConstraint(typedValue);
2223 log.warn("The value of LessThanConstraint is null");
2226 case GREATER_OR_EQUAL:
2227 if (typedValue != null) {
2228 log.debug("Before adding value to GreaterThanConstraint object. value = {}", typedValue);
2229 propertyConstraint = new GreaterOrEqualConstraint(typedValue);
2231 log.warn("The value of GreaterOrEqualConstraint is null");
2235 if (typedValue != null) {
2236 log.debug("Before adding value to LessOrEqualConstraint object. value = {}", typedValue);
2237 propertyConstraint = new LessOrEqualConstraint(typedValue);
2239 log.warn("The value of LessOrEqualConstraint is null");
2243 if (typedValue instanceof ArrayList) {
2244 List<Object> validValuesArray = (ArrayList<Object>) typedValue;
2245 if (validValuesArray.size() == 0 || validValuesArray.contains("")) {
2246 log.error("The valid values constraint content is invalid. value = {}", typedValue);
2247 throw new JsonSyntaxException("The valid values constraint content is invalid");
2249 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2250 vvConstraint.setValidValues(validValuesArray);
2251 propertyConstraint = vvConstraint;
2254 log.warn("The value of ValidValuesConstraint is null");
2258 if (value != null) {
2259 int asInt = value.getAsInt();
2260 log.debug("Before adding value to length constraint. value = {}", asInt);
2261 propertyConstraint = new LengthConstraint(asInt);
2263 log.warn("The value of LengthConstraint is null");
2267 if (value != null) {
2268 int asInt = value.getAsInt();
2269 log.debug("Before adding value to Min Length object. value = {}", asInt);
2270 propertyConstraint = new MinLengthConstraint(asInt);
2272 log.warn("The value of MinLengthConstraint is null");
2276 if (value != null) {
2277 int asInt = value.getAsInt();
2278 log.debug("Before adding value to max length constraint. value = {}", asInt);
2279 propertyConstraint = new MaxLengthConstraint(asInt);
2281 log.warn("The value of MaxLengthConstraint is null");
2285 if (value != null) {
2286 String asString = value.getAsString();
2287 log.debug("Before adding value to PatternConstraint object. value = {}", asString);
2288 propertyConstraint = new PatternConstraint(asString);
2290 log.warn("The value of PatternConstraint is null");
2294 log.warn("Key {} is not supported. Ignored.", key);
2299 return propertyConstraint;
2302 private Object getTypedValue(JsonElement je) {
2303 if (je == null || je.isJsonNull()) {
2306 if (je.isJsonPrimitive()) {
2307 return getJsonPrimitive(je.getAsJsonPrimitive());
2309 if (je.isJsonArray()) {
2310 ArrayList<Object> array = new ArrayList<>();
2311 for (JsonElement e : je.getAsJsonArray()) {
2312 array.add(getJsonPrimitive(e.getAsJsonPrimitive()));
2319 private Object getJsonPrimitive(JsonPrimitive je) {
2320 if (je.isBoolean()) {
2321 return je.getAsBoolean();
2323 if (je.isString()) {
2324 return je.getAsString();
2326 if (je.isNumber()) {
2327 double number = je.getAsNumber().floatValue();
2328 if ((number % 1) == 0) {
2329 return je.getAsNumber().intValue();
2337 public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
2340 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
2341 ObjectCodec oc = json.getCodec();
2342 JsonNode node = oc.readTree(json);
2343 PropertyConstraint propertyConstraint = null;
2345 Iterator<Entry<String, JsonNode>> fieldsIterator = node.fields();
2346 while (fieldsIterator.hasNext()) {
2347 Entry<String, JsonNode> field = fieldsIterator.next();
2348 ConstraintType constraintType = ConstraintType.findByType(field.getKey()).orElse(null);
2349 JsonNode value = field.getValue();
2351 if (constraintType == null) {
2352 log.warn("ConstraintType was not found for constraint name:{}", field.getKey());
2354 if (value == null) {
2355 log.warn("The value of {} constraint is null", constraintType);
2357 switch (constraintType) {
2359 propertyConstraint = deserializeConstraintWithStringOperand(value, EqualConstraint.class);
2362 propertyConstraint = deserializeInRangeConstraintConstraint(value);
2365 propertyConstraint = deserializeConstraintWithStringOperand(value, GreaterThanConstraint.class);
2368 propertyConstraint = deserializeConstraintWithStringOperand(value, LessThanConstraint.class);
2370 case GREATER_OR_EQUAL:
2371 propertyConstraint = deserializeConstraintWithStringOperand(value, GreaterOrEqualConstraint.class);
2374 propertyConstraint = deserializeConstraintWithStringOperand(value, LessOrEqualConstraint.class);
2377 propertyConstraint = deserializeValidValuesConstraint(value);
2380 propertyConstraint = deserializeConstraintWithIntegerOperand(value, LengthConstraint.class);
2383 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MinLengthConstraint.class);
2386 propertyConstraint = deserializeConstraintWithIntegerOperand(value, MaxLengthConstraint.class);
2389 propertyConstraint = deserializeConstraintWithStringPatternOperand(value, PatternConstraint.class);
2392 log.warn("Key {} is not supported. Ignored.", field.getKey());
2398 return propertyConstraint;
2401 private PropertyConstraint deserializeConstraintWithStringOperand(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2402 String asString = value.asText();
2403 log.debug("Before adding value to {} object. value = {}", constraintClass, asString);
2405 return constraintClass.getConstructor(Object.class).newInstance(asString);
2406 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2407 | SecurityException exception) {
2408 log.error("Error deserializing constraint", exception);
2413 private PropertyConstraint deserializeConstraintWithStringPatternOperand(JsonNode value,
2414 Class<? extends PropertyConstraint> constraintClass) {
2415 String asString = value.asText();
2416 log.debug("Before adding value to {} object. value = {}", constraintClass, asString);
2418 return constraintClass.getConstructor(String.class).newInstance(asString);
2419 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2420 | SecurityException exception) {
2421 log.error("Error deserializing constraint", exception);
2426 private PropertyConstraint deserializeConstraintWithIntegerOperand(JsonNode value, Class<? extends PropertyConstraint> constraintClass) {
2427 Integer asInt = value.asInt();
2428 log.debug("Before adding value to {} object. value = {}", constraintClass, asInt);
2430 return constraintClass.getConstructor(Integer.class).newInstance(asInt);
2431 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
2432 | SecurityException exception) {
2433 log.error("Error deserializing constraint", exception);
2438 private PropertyConstraint deserializeInRangeConstraintConstraint(JsonNode value) {
2439 if (value instanceof ArrayNode) {
2440 ArrayNode rangeArray = (ArrayNode) value;
2441 if (rangeArray.size() != 2) {
2442 log.error("The range constraint content is invalid. value = {}", value);
2444 String minValue = rangeArray.get(0).asText();
2445 String maxValue = rangeArray.get(1).asText();
2446 InRangeConstraint rangeConstraint = new InRangeConstraint(Lists.newArrayList(minValue, maxValue));
2447 rangeConstraint.setMin(convertToComparable(ToscaType.RANGE, minValue));
2448 rangeConstraint.setMax(convertToComparable(ToscaType.RANGE, maxValue));
2449 return rangeConstraint;
2455 private PropertyConstraint deserializeValidValuesConstraint(JsonNode value) {
2456 ArrayNode rangeArray = (ArrayNode) value;
2457 if (rangeArray.size() == 0) {
2458 log.error("The valid values constraint content is invalid. value = {}", value);
2460 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2461 List<Object> validValues = new ArrayList<>();
2462 for (JsonNode jsonElement : rangeArray) {
2463 String item = jsonElement.asText();
2464 validValues.add(item);
2466 vvConstraint.setValidValues(validValues);
2467 return vvConstraint;