2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.be.model.operations.impl;
23 import com.fasterxml.jackson.core.ObjectCodec;
24 import com.fasterxml.jackson.databind.DeserializationContext;
25 import com.fasterxml.jackson.databind.JsonNode;
26 import com.google.common.collect.Maps;
27 import com.google.gson.*;
28 import com.thinkaurelius.titan.core.TitanGraph;
29 import com.thinkaurelius.titan.core.TitanVertex;
30 import com.thinkaurelius.titan.core.TitanVertexProperty;
31 import fj.data.Either;
32 import org.apache.commons.collections.CollectionUtils;
33 import org.apache.commons.collections.MapUtils;
34 import org.apache.commons.lang3.StringUtils;
35 import org.apache.commons.lang3.tuple.ImmutablePair;
36 import org.apache.tinkerpop.gremlin.structure.Edge;
37 import org.apache.tinkerpop.gremlin.structure.Vertex;
38 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
39 import org.openecomp.sdc.be.config.BeEcompErrorManager;
40 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
41 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
42 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
43 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
44 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
45 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
46 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
47 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
48 import org.openecomp.sdc.be.dao.titan.TitanGenericDao;
49 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
50 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
51 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
52 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
53 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
54 import org.openecomp.sdc.be.model.*;
55 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
56 import org.openecomp.sdc.be.model.operations.api.IPropertyOperation;
57 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
58 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
59 import org.openecomp.sdc.be.model.tosca.constraints.*;
60 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
61 import org.openecomp.sdc.be.resources.data.*;
62 import org.openecomp.sdc.common.log.wrappers.Logger;
63 import org.springframework.stereotype.Component;
65 import java.io.IOException;
66 import java.lang.reflect.Type;
68 import java.util.Map.Entry;
69 import java.util.function.Consumer;
70 import java.util.regex.Matcher;
71 import java.util.regex.Pattern;
72 import java.util.stream.Collectors;
75 @Component("property-operation")
76 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
77 private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
78 private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
79 private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
80 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
81 private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS = "Failed to associate resource {} to property {} in graph. status is {}";
82 private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
83 private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
84 private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
85 private DerivedFromOperation derivedFromOperation;
86 private static final String PROPERTY = "Property";
87 private static final String UPDATE_DATA_TYPE = "UpdateDataType";
89 public static void main(String[] args) {
91 List<Pattern> buildFunctionPatterns = buildFunctionPatterns();
93 for (Pattern pattern : buildFunctionPatterns) {
95 String[] strs = { "str_replace", "{ str_replace:", " {str_replace:", " { str_replace:", "{str_replace:" };
96 for (String str : strs) {
97 Matcher m = pattern.matcher(str);
98 System.out.println(pattern.pattern() + " " + str + " " + m.find());
104 public PropertyOperation(TitanGenericDao titanGenericDao, DerivedFromOperation derivedFromOperation) {
105 this.titanGenericDao = titanGenericDao;
106 this.derivedFromOperation = derivedFromOperation;
109 private static Logger log = Logger.getLogger(PropertyOperation.class.getName());
112 * The value of functions is in a json format. Build pattern for each function name
114 * { str_replace: .... } {str_replace: .... } {str_replace: .... } { str_replace: .... }
118 private static List<Pattern> buildFunctionPatterns() {
120 List<Pattern> functionPatterns = new ArrayList<>();
122 String[] functions = { "get_input", "get_property" };
124 for (String function : functions) {
125 Pattern pattern = Pattern.compile("^[ ]*\\{[ ]*" + function + ":");
126 functionPatterns.add(pattern);
129 return functionPatterns;
132 public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
133 log.debug("The object returned after create property is {}", propertyDataResult);
135 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
136 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
137 propertyDefResult.setName(propertyName);
139 return propertyDefResult;
142 public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
145 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
146 JsonParser parser = new JsonParser();
147 JsonObject result = new JsonObject();
148 JsonArray jsonArray = new JsonArray();
149 if (src instanceof InRangeConstraint) {
150 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
151 jsonArray.add(parser.parse(rangeConstraint.getRangeMinValue()));
152 jsonArray.add(parser.parse(rangeConstraint.getRangeMaxValue()));
153 result.add("inRange", jsonArray);
154 } else if (src instanceof GreaterThanConstraint) {
155 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
156 jsonArray.add(parser.parse(greaterThanConstraint.getGreaterThan()));
157 result.add("greaterThan", jsonArray);
158 } else if (src instanceof LessOrEqualConstraint) {
159 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
160 jsonArray.add(parser.parse(lessOrEqualConstraint.getLessOrEqual()));
161 result.add("lessOrEqual", jsonArray);
163 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
171 public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
173 private static final String THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL = "The value of GreaterThanConstraint is null";
176 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
178 PropertyConstraint propertyConstraint = null;
180 Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
182 if (set.size() == 1) {
183 Entry<String, JsonElement> element = set.iterator().next();
184 String key = element.getKey();
185 JsonElement value = element.getValue();
187 ConstraintType constraintType = ConstraintType.getByType(key);
188 if (constraintType == null) {
189 log.warn("ConstraintType was not found for constraint name:{}", key);
191 switch (constraintType) {
195 if (value instanceof JsonArray) {
196 JsonArray rangeArray = (JsonArray) value;
197 if (rangeArray.size() != 2) {
198 log.error("The range constraint content is invalid. value = {}", value);
200 InRangeConstraint rangeConstraint = new InRangeConstraint();
201 String minValue = rangeArray.get(0).getAsString();
202 String maxValue = rangeArray.get(1).getAsString();
203 rangeConstraint.setRangeMinValue(minValue);
204 rangeConstraint.setRangeMaxValue(maxValue);
205 propertyConstraint = rangeConstraint;
210 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
215 String asString = value.getAsString();
216 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
217 propertyConstraint = new GreaterThanConstraint(asString);
220 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
226 String asString = value.getAsString();
227 log.debug("Before adding value to LessThanConstraint object. value = {}", asString);
228 propertyConstraint = new LessThanConstraint(asString);
231 log.warn("The value of LessThanConstraint is null");
234 case GREATER_OR_EQUAL:
236 String asString = value.getAsString();
237 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
238 propertyConstraint = new GreaterOrEqualConstraint(asString);
241 log.warn("The value of GreaterOrEqualConstraint is null");
247 String asString = value.getAsString();
248 log.debug("Before adding value to LessOrEqualConstraint object. value = {}", asString);
249 propertyConstraint = new LessOrEqualConstraint(asString);
251 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
258 if (value instanceof JsonArray) {
259 JsonArray rangeArray = (JsonArray) value;
260 if (rangeArray.size() == 0) {
261 log.error("The valid values constraint content is invalid. value = {}", value);
263 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
264 List<String> validValues = new ArrayList<>();
265 for (JsonElement jsonElement : rangeArray) {
266 String item = jsonElement.getAsString();
267 validValues.add(item);
269 vvConstraint.setValidValues(validValues);
270 propertyConstraint = vvConstraint;
275 log.warn("The value of ValidValuesConstraint is null");
281 int asInt = value.getAsInt();
282 log.debug("Before adding value to Min Length object. value = {}", asInt);
283 propertyConstraint = new MinLengthConstraint(asInt);
286 log.warn("The value of MinLengthConstraint is null");
290 log.warn("Key {} is not supported. Ignored.", key);
295 return propertyConstraint;
301 public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
303 Either<PropertyData, TitanOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
304 if (either.isRight()) {
305 StorageOperationStatus storageStatus = DaoStatusConverter.convertTitanStatusToStorageStatus(either.right().value());
306 return Either.right(storageStatus);
308 return Either.left(either.left().value());
312 * @param propertyDefinition
316 public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
318 log.trace("Going to validate property type and value. {}", propertyDefinition);
320 String propertyType = propertyDefinition.getType();
321 String value = propertyDefinition.getDefaultValue();
323 ToscaPropertyType type = getType(propertyType);
327 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
328 if (dataTypeDefinition == null) {
329 log.debug("The type {} of property cannot be found.", propertyType);
330 return StorageOperationStatus.INVALID_TYPE;
333 return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
336 String innerType = null;
338 Either<String, TitanOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
339 if (checkInnerType.isRight()) {
340 return StorageOperationStatus.INVALID_TYPE;
342 innerType = checkInnerType.left().value();
344 log.trace("After validating property type {}", propertyType);
346 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
347 if (!isValidProperty) {
348 log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
349 return StorageOperationStatus.INVALID_VALUE;
352 PropertyValueConverter converter = type.getConverter();
354 if (isEmptyValue(value)) {
355 log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
356 propertyDefinition.setDefaultValue(EMPTY_VALUE);
357 } else if (!isEmptyValue(value)) {
358 String convertedValue = converter.convert(value, innerType, dataTypes);
359 propertyDefinition.setDefaultValue(convertedValue);
361 return StorageOperationStatus.OK;
364 public Either<PropertyData, TitanOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
366 ResourceMetadataData resourceData = new ResourceMetadataData();
367 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
369 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
371 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
372 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
374 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
375 Either<PropertyData, TitanOperationStatus> createNodeResult = titanGenericDao.createNode(propertyData, PropertyData.class);
376 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
377 if (createNodeResult.isRight()) {
378 TitanOperationStatus operationStatus = createNodeResult.right().value();
379 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
380 return Either.right(operationStatus);
383 Map<String, Object> props = new HashMap<>();
384 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
385 Either<GraphRelation, TitanOperationStatus> createRelResult = titanGenericDao.createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
386 if (createRelResult.isRight()) {
387 TitanOperationStatus operationStatus = createNodeResult.right().value();
388 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
389 return Either.right(operationStatus);
392 return Either.left(createNodeResult.left().value());
396 public TitanOperationStatus addPropertyToGraphByVertex(TitanVertex metadataVertex, String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
398 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
400 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
401 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
403 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
404 Either<TitanVertex, TitanOperationStatus> createNodeResult = titanGenericDao.createNode(propertyData);
405 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
406 if (createNodeResult.isRight()) {
407 TitanOperationStatus operationStatus = createNodeResult.right().value();
408 log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
409 return operationStatus;
412 Map<String, Object> props = new HashMap<>();
413 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
414 TitanVertex propertyVertex = createNodeResult.left().value();
415 TitanOperationStatus createRelResult = titanGenericDao.createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
416 if (!createRelResult.equals(TitanOperationStatus.OK)) {
417 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
418 return createRelResult;
421 return createRelResult;
425 public TitanGenericDao getTitanGenericDao() {
426 return titanGenericDao;
429 public Either<PropertyData, TitanOperationStatus> deletePropertyFromGraph(String propertyId) {
430 log.debug("Before deleting property from graph {}", propertyId);
431 return titanGenericDao.deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
434 public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
436 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
437 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
438 return Either.right(validateAndUpdateProperty);
441 Either<PropertyData, TitanOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
442 if (either.isRight()) {
443 StorageOperationStatus storageStatus = DaoStatusConverter.convertTitanStatusToStorageStatus(either.right().value());
444 return Either.right(storageStatus);
446 return Either.left(either.left().value());
449 public Either<PropertyData, TitanOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
450 if (log.isDebugEnabled())
451 log.debug("Before updating property on graph {}", propertyId);
453 // get the original property data
454 Either<PropertyData, TitanOperationStatus> statusProperty = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
455 if (statusProperty.isRight()) {
456 log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
457 return Either.right(statusProperty.right().value());
459 PropertyData orgPropertyData = statusProperty.left().value();
460 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
462 // create new property data to update
463 PropertyData newPropertyData = new PropertyData();
464 newPropertyData.setPropertyDataDefinition(propertyDefinition);
465 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
467 // update the original property data with new values
468 if (orgPropertyDataDefinition.getDefaultValue() == null) {
469 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
471 if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
472 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
475 if (orgPropertyDataDefinition.getDescription() == null) {
476 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
478 if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
479 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
482 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
483 orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
485 if (newPropertyData.getConstraints() != null) {
486 orgPropertyData.setConstraints(newPropertyData.getConstraints());
488 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
490 return titanGenericDao.updateNode(orgPropertyData, PropertyData.class);
496 * @param titanGenericDao
498 public void setTitanGenericDao(TitanGenericDao titanGenericDao) {
499 this.titanGenericDao = titanGenericDao;
502 public Either<PropertyData, TitanOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition, NodeTypeEnum nodeType, String uniqueId) {
504 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
506 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
507 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
509 if (log.isDebugEnabled())
510 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
511 Either<PropertyData, TitanOperationStatus> createNodeResult = titanGenericDao.createNode(propertyData, PropertyData.class);
512 if (log.isDebugEnabled())
513 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
514 if (createNodeResult.isRight()) {
515 TitanOperationStatus operationStatus = createNodeResult.right().value();
516 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
517 return Either.right(operationStatus);
520 Map<String, Object> props = new HashMap<>();
521 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
523 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
524 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
525 Either<GraphRelation, TitanOperationStatus> createRelResult = titanGenericDao.createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
526 if (createRelResult.isRight()) {
527 TitanOperationStatus operationStatus = createNodeResult.right().value();
528 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
529 return Either.right(operationStatus);
532 return Either.left(createNodeResult.left().value());
536 public Either<Map<String, PropertyDefinition>, TitanOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
538 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
540 Either<List<ImmutablePair<PropertyData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
543 if (childrenNodes.isRight()) {
544 TitanOperationStatus operationStatus = childrenNodes.right().value();
545 return Either.right(operationStatus);
548 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
549 if (values != null) {
551 for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
552 GraphEdge edge = immutablePair.getValue();
553 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
554 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
555 PropertyData propertyData = immutablePair.getKey();
556 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
557 resourceProps.put(propertyName, propertyDefinition);
562 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
563 return Either.left(resourceProps);
566 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
567 return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId)
569 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
572 public Either<Map<String, PropertyData>, TitanOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId, Map<String, PropertyDefinition> newProperties) {
573 Either<Map<String, PropertyDefinition>, TitanOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
575 Map<String, PropertyDefinition> reallyNewProperties;
576 Map<String, PropertyData> unchangedPropsData;
578 if (oldPropertiesRes.isRight()) {
579 TitanOperationStatus err = oldPropertiesRes.right().value();
580 if (err == TitanOperationStatus.NOT_FOUND) {
581 reallyNewProperties = newProperties;
582 unchangedPropsData = Collections.emptyMap();
585 return Either.right(err);
589 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
590 reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
592 for(Entry<String, PropertyDefinition> oldEntry: oldProperties.entrySet()) {
593 String key = oldEntry.getKey();
594 PropertyDefinition newPropDef = newProperties != null? newProperties.get(key): null;
595 PropertyDefinition oldPropDef = oldEntry.getValue();
597 TitanOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
598 if (status != TitanOperationStatus.OK) {
599 return Either.right(status);
602 unchangedPropsData = oldProperties.entrySet().stream()
603 .collect(Collectors.toMap(Entry::getKey, e-> new PropertyData(e.getValue(), null)));
607 // add other properties
608 return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
612 * @param newProperties
613 * @param oldProperties
616 private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties, Map<String, PropertyDefinition> oldProperties) {
617 return newProperties != null? newProperties.entrySet().stream()
618 .filter(entry -> !oldProperties.containsKey(entry.getKey()))
619 .collect(Collectors.toMap(Entry::getKey, Entry::getValue) ): null;
626 private TitanOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
627 if (!isUpdateAllowed(newPropDef, oldPropDef)) {
628 return TitanOperationStatus.MATCH_NOT_FOUND;
631 if (isUpdateRequired(newPropDef, oldPropDef)) {
632 modifyOldPropByNewOne(newPropDef, oldPropDef);
634 List<PropertyConstraint> constraints = oldPropDef.getConstraints();
635 PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
636 Either<PropertyData, TitanOperationStatus> updateResult = titanGenericDao.updateNode(node, PropertyData.class);
638 if (updateResult.isRight()) {
639 return updateResult.right().value();
643 return TitanOperationStatus.OK;
650 private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
651 if (newPropDef == null) {
652 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
656 // If the property type is missing it's something that we could want to fix
657 if ( oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
658 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
666 * Update only fields which modification is permitted.
670 private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
671 oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
672 oldPropDef.setDescription(newPropDef.getDescription());
673 oldPropDef.setRequired(newPropDef.isRequired());
675 // Type is updated to fix possible null type issue in TITAN DB
676 oldPropDef.setType(newPropDef.getType());
680 private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
681 return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) ||
682 !StringUtils.equals(oldPropDef.getDescription(), newPropDef.getDescription()) ||
683 oldPropDef.isRequired() != newPropDef.isRequired();
687 * Adds newProperties and returns in case of success (left part of Either)
688 * map of all properties i. e. added ones and contained in unchangedPropsData
691 * @param newProperties
692 * @param unchangedPropsData
695 private Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId, Map<String, PropertyDefinition> newProperties, Map<String, PropertyData> unchangedPropsData) {
696 return addPropertiesToElementType(uniqueId, nodeType, newProperties)
699 m.putAll(unchangedPropsData);
705 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
707 Either<Map<String, PropertyDefinition>, TitanOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
709 if (propertiesOfNodeRes.isRight()) {
710 TitanOperationStatus status = propertiesOfNodeRes.right().value();
711 if (status == TitanOperationStatus.NOT_FOUND) {
712 return Either.right(StorageOperationStatus.OK);
714 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
717 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
718 for (PropertyDefinition propertyDefinition : value.values()) {
720 String propertyUid = propertyDefinition.getUniqueId();
721 Either<PropertyData, TitanOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
722 if (deletePropertyRes.isRight()) {
723 log.error("Failed to delete property with id {}", propertyUid);
724 TitanOperationStatus status = deletePropertyRes.right().value();
725 if (status == TitanOperationStatus.NOT_FOUND) {
726 status = TitanOperationStatus.INVALID_ID;
728 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
733 log.debug("The properties deleted from node {} are {}", uniqueId, value);
734 return Either.left(value);
738 * Checks existence of a property with the same name belonging to the same resource
739 * or existence of property with the same name and different type (including derived from hierarchy)
742 * @param propertyName
743 * @param propertyType
746 public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
747 boolean result = false;
748 if (!CollectionUtils.isEmpty(properties)) {
749 for (PropertyDefinition propertyDefinition : properties) {
751 if ( propertyDefinition.getName().equals(propertyName) &&
752 (propertyDefinition.getParentUniqueId().equals(resourceUid) || !propertyDefinition.getType().equals(propertyType)) ) {
761 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType, Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
763 if (rules == null || rules.isEmpty()) {
764 return new ImmutablePair<>(null, true);
767 for (PropertyRule rule : rules) {
768 String value = rule.getValue();
769 Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
770 if (updateResult.isRight()) {
771 Boolean status = updateResult.right().value();
773 return new ImmutablePair<>(value, status);
776 String newValue = null;
777 Object object = updateResult.left().value();
778 if (object != null) {
779 newValue = object.toString();
781 rule.setValue(newValue);
785 return new ImmutablePair<>(null, true);
788 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
790 List<PropertyRule> rules = resourceInstanceProperty.getRules();
792 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
793 rules = new ArrayList<>();
794 rules.add(propertyRule);
796 rules = sortRules(rules);
799 propertyValueData.setRules(rules);
802 private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
803 List<String> path = resourceInstanceProperty.getPath();
804 // FOR BC. Since old Property values on VFC/VF does not have rules on
806 // Update could be done on one level only, thus we can use this
807 // operation to avoid migration.
808 if (path == null || path.isEmpty()) {
809 path = new ArrayList<>();
810 path.add(resourceInstanceId);
812 PropertyRule propertyRule = new PropertyRule();
813 propertyRule.setRule(path);
814 propertyRule.setValue(propertyValueData.getValue());
818 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
820 // TODO: sort the rules by size and binary representation.
821 // (x, y, .+) --> 110 6 priority 1
822 // (x, .+, z) --> 101 5 priority 2
827 public ImmutablePair<TitanOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
829 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
831 Either<List<ComponentInstanceProperty>, TitanOperationStatus> getAllRes = this.getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
832 if (getAllRes.isRight()) {
833 TitanOperationStatus status = getAllRes.right().value();
834 log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
835 return new ImmutablePair<>(status, null);
838 List<ComponentInstanceProperty> list = getAllRes.left().value();
840 for (ComponentInstanceProperty instanceProperty : list) {
841 String propertyUniqueId = instanceProperty.getUniqueId();
842 String valueUniqueUid = instanceProperty.getValueUniqueUid();
843 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
844 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
845 log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
846 return new ImmutablePair<>(TitanOperationStatus.ALREADY_EXIST, valueUniqueUid);
851 return new ImmutablePair<>(TitanOperationStatus.NOT_FOUND, null);
855 public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
857 List<PropertyRule> currentRules = propertyValueData.getRules();
859 List<PropertyRule> rules = resourceInstanceProperty.getRules();
860 // if rules are not supported.
863 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
864 rules = new ArrayList<>();
865 rules.add(propertyRule);
867 if (currentRules != null) {
868 rules = mergeRules(currentRules, rules);
872 // Full mode. all rules are sent in update operation.
873 rules = sortRules(rules);
876 propertyValueData.setRules(rules);
880 private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
882 List<PropertyRule> mergedRules = new ArrayList<>();
884 if (newRules == null || newRules.isEmpty()) {
888 for (PropertyRule rule : currentRules) {
889 PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
890 mergedRules.add(propertyRule);
893 for (PropertyRule rule : newRules) {
894 PropertyRule foundRule = findRuleInList(rule, mergedRules);
895 if (foundRule != null) {
896 foundRule.setValue(rule.getValue());
898 mergedRules.add(rule);
905 private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
907 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
911 PropertyRule foundRule = null;
912 for (PropertyRule propertyRule : rules) {
913 if (rule.getRuleSize() != propertyRule.getRuleSize()) {
916 boolean equals = propertyRule.compareRule(rule);
918 foundRule = propertyRule;
927 * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
929 * @param resourceInstanceUid
932 public Either<List<ComponentInstanceProperty>, TitanOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(String resourceInstanceUid) {
934 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
938 public Either<PropertyValueData, TitanOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
940 Either<ComponentInstanceData, TitanOperationStatus> findResInstanceRes = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
942 if (findResInstanceRes.isRight()) {
943 TitanOperationStatus status = findResInstanceRes.right().value();
944 if (status == TitanOperationStatus.NOT_FOUND) {
945 status = TitanOperationStatus.INVALID_ID;
947 return Either.right(status);
950 Either<PropertyValueData, TitanOperationStatus> findPropertyDefRes = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
952 if (findPropertyDefRes.isRight()) {
953 TitanOperationStatus status = findPropertyDefRes.right().value();
954 if (status == TitanOperationStatus.NOT_FOUND) {
955 status = TitanOperationStatus.INVALID_ID;
957 return Either.right(status);
960 Either<GraphRelation, TitanOperationStatus> relation = titanGenericDao.getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
961 if (relation.isRight()) {
962 // TODO: add error in case of error
963 TitanOperationStatus status = relation.right().value();
964 if (status == TitanOperationStatus.NOT_FOUND) {
965 status = TitanOperationStatus.INVALID_ID;
967 return Either.right(status);
970 Either<PropertyValueData, TitanOperationStatus> deleteNode = titanGenericDao.deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
971 if (deleteNode.isRight()) {
972 return Either.right(deleteNode.right().value());
974 PropertyValueData value = deleteNode.left().value();
975 return Either.left(value);
979 public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid, String resourceInstanceId, boolean inTransaction) {
981 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
985 Either<PropertyValueData, TitanOperationStatus> eitherStatus = this.removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
987 if (eitherStatus.isRight()) {
988 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId, eitherStatus.right().value().name());
989 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(eitherStatus.right().value()));
992 PropertyValueData propertyValueData = eitherStatus.left().value();
994 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
995 propertyValueResult.setUniqueId(resourceInstanceId);
996 propertyValueResult.setValue(propertyValueData.getValue());
998 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
999 result = Either.left(propertyValueResult);
1005 if (!inTransaction) {
1006 if (result == null || result.isRight()) {
1007 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1008 titanGenericDao.rollback();
1010 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1011 titanGenericDao.commit();
1018 public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty) {
1020 String value = propertyValueData.getValue();
1021 String uid = propertyValueData.getUniqueId();
1022 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
1023 instanceProperty.setPath(resourceInstanceProperty.getPath());
1025 return instanceProperty;
1029 public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
1032 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
1033 ObjectCodec oc = json.getCodec();
1034 JsonNode node = oc.readTree(json);
1040 public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
1041 if (propertyDefinition == null) {
1044 boolean isValid = false;
1045 String innerType = null;
1046 String propertyType = propertyDefinition.getType();
1047 ToscaPropertyType type = getType(propertyType);
1048 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
1049 SchemaDefinition def = propertyDefinition.getSchema();
1053 PropertyDataDefinition propDef = def.getProperty();
1054 if (propDef == null) {
1057 innerType = propDef.getType();
1059 String value = propertyDefinition.getDefaultValue();
1061 isValid = isValidValue(type, value, innerType, dataTypes);
1063 log.trace("The given type {} is not a pre defined one.", propertyType);
1065 DataTypeDefinition foundDt = dataTypes.get(propertyType);
1066 if (foundDt != null) {
1067 isValid = isValidComplexValue(foundDt, value, dataTypes);
1075 public boolean isPropertyTypeValid(IComplexDefaultValue property) {
1077 if (property == null) {
1081 if (ToscaPropertyType.isValidType(property.getType()) == null) {
1083 Either<Boolean, TitanOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType());
1085 if (definedInDataTypes.isRight()) {
1088 Boolean isExist = definedInDataTypes.left().value();
1089 return isExist.booleanValue();
1097 public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
1099 if (property == null) {
1100 return new ImmutablePair<>(null, false);
1103 SchemaDefinition schema;
1104 PropertyDataDefinition innerProp;
1105 String innerType = null;
1106 if ((schema = property.getSchema()) != null) {
1107 if ((innerProp = schema.getProperty()) != null) {
1108 innerType = innerProp.getType();
1112 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
1114 if (innerToscaType == null) {
1115 DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
1116 if (dataTypeDefinition == null) {
1117 log.debug("The inner type {} is not a data type.", innerType);
1118 return new ImmutablePair<>(innerType, false);
1120 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
1124 return new ImmutablePair<>(innerType, true);
1127 private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
1128 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
1130 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
1132 return validateAndUpdate.right.booleanValue();
1136 public Either<List<ComponentInstanceProperty>, TitanOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
1138 Either<TitanVertex, TitanOperationStatus> findResInstanceRes = titanGenericDao.getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
1140 if (findResInstanceRes.isRight()) {
1141 TitanOperationStatus status = findResInstanceRes.right().value();
1142 if (status == TitanOperationStatus.NOT_FOUND) {
1143 status = TitanOperationStatus.INVALID_ID;
1145 return Either.right(status);
1148 Either<List<ImmutablePair<TitanVertex, Edge>>, TitanOperationStatus> propertyImplNodes = titanGenericDao.getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
1150 if (propertyImplNodes.isRight()) {
1151 TitanOperationStatus status = propertyImplNodes.right().value();
1152 return Either.right(status);
1155 List<ImmutablePair<TitanVertex, Edge>> list = propertyImplNodes.left().value();
1156 if (list == null || list.isEmpty()) {
1157 return Either.right(TitanOperationStatus.NOT_FOUND);
1160 List<ComponentInstanceProperty> result = new ArrayList<>();
1161 for (ImmutablePair<TitanVertex, Edge> propertyValue : list) {
1162 TitanVertex propertyValueDataVertex = propertyValue.getLeft();
1163 String propertyValueUid = (String) titanGenericDao.getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
1164 String value = (String) titanGenericDao.getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
1166 ImmutablePair<TitanVertex, Edge> propertyDefPair = titanGenericDao.getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
1167 if (propertyDefPair == null) {
1168 return Either.right(TitanOperationStatus.NOT_FOUND);
1171 Map<String, Object> properties = titanGenericDao.getProperties(propertyValueDataVertex);
1172 PropertyValueData propertyValueData = GraphElementFactory.createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
1173 String propertyUniqueId = (String) titanGenericDao.getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
1175 ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
1176 // set property original unique id
1177 resourceInstanceProperty.setUniqueId(propertyUniqueId);
1179 // TODO: esofer add resource id
1180 resourceInstanceProperty.setParentUniqueId(null);
1182 resourceInstanceProperty.setValue(value);
1183 // set property value unique id
1184 resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
1186 resourceInstanceProperty.setRules(propertyValueData.getRules());
1188 result.add(resourceInstanceProperty);
1191 return Either.left(result);
1195 * Find the default value from the list of component instances. Start the search from the second component instance
1197 * @param pathOfComponentInstances
1198 * @param propertyUniqueId
1199 * @param defaultValue
1202 public Either<String, TitanOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances, String propertyUniqueId, String defaultValue) {
1204 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
1206 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
1207 return Either.left(defaultValue);
1210 String result = defaultValue;
1212 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
1213 String compInstanceId = pathOfComponentInstances.get(i);
1215 Either<List<ComponentInstanceProperty>, TitanOperationStatus> propertyValuesResult = this.getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
1217 log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
1219 if (propertyValuesResult.isRight()) {
1220 TitanOperationStatus status = propertyValuesResult.right().value();
1221 if (status != TitanOperationStatus.NOT_FOUND) {
1222 return Either.right(status);
1228 ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
1229 log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
1231 if (foundCompInstanceProperty == null) {
1235 List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i), foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
1237 log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
1238 PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
1239 log.trace("Match rule is {}", matchedRule);
1241 if (matchedRule != null) {
1242 result = matchedRule.getValue();
1248 return Either.left(result);
1252 private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
1254 ComponentInstanceProperty result = null;
1260 for (ComponentInstanceProperty instProperty : list) {
1261 if (instProperty.getUniqueId().equals(propertyUniqueId)) {
1262 result = instProperty;
1270 private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
1272 if (rules != null) {
1276 rules = buildDefaultRule(compInstanceId, ruleSize, value);
1282 private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
1283 List<PropertyRule> rules = componentInstanceProperty.getRules();
1284 if (rules == null) {
1285 rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
1290 private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
1292 List<PropertyRule> rules = new ArrayList<>();
1293 List<String> rule = new ArrayList<>();
1294 rule.add(componentInstanceId);
1295 for (int i = 0; i < size - 1; i++) {
1296 rule.add(PropertyRule.RULE_ANY_MATCH);
1298 PropertyRule propertyRule = new PropertyRule(rule, value);
1299 rules.add(propertyRule);
1305 private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1307 PropertyRule propertyRule = null;
1309 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1311 String firstCompInstance = pathOfInstances.get(level);
1313 if (rules != null) {
1315 for (PropertyRule rule : rules) {
1317 int ruleSize = rule.getRule().size();
1318 // check the length of the rule equals to the length of the
1320 if (ruleSize != pathOfInstances.size() - level) {
1323 // check that the rule starts with correct component instance id
1324 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1328 String secondToken = rule.getToken(2);
1329 if (secondToken != null && (secondToken.equals(PropertyRule.FORCE_ALL) || secondToken.equals(PropertyRule.ALL))) {
1330 propertyRule = rule;
1334 String patternStr = buildStringForMatch(rule.getRule(), 0);
1336 Pattern pattern = Pattern.compile(patternStr);
1338 Matcher matcher = pattern.matcher(stringForMatch);
1340 if (matcher.matches()) {
1341 if (log.isTraceEnabled()) {
1342 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1344 propertyRule = rule;
1351 return propertyRule;
1354 private boolean checkFirstItem(String left, String right) {
1355 if (left != null && left.equals(right)) {
1361 private String buildStringForMatch(List<String> pathOfInstances, int level) {
1362 StringBuilder builder = new StringBuilder();
1364 for (int i = level; i < pathOfInstances.size(); i++) {
1365 builder.append(pathOfInstances.get(i));
1366 if (i < pathOfInstances.size() - 1) {
1367 builder.append("#");
1370 return builder.toString();
1373 public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty, Map<String, ComponentInstanceProperty> instanceIdToValue) {
1375 List<String> pathOfInstances = instanceProperty.getPath();
1377 int size = pathOfInstances.size();
1378 int numberOfMatches = 0;
1379 for (String instanceId : pathOfInstances) {
1380 ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1382 if (componentInstanceProperty != null) {
1384 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1385 // If it is the first level instance, then update valueUniuqeId
1386 // parameter in order to know on update that
1387 // we should update and not create new node on graph.
1389 instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1390 instanceProperty.setRules(rules);
1393 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1396 String value = rule.getValue();
1397 if (numberOfMatches == 1) {
1398 instanceProperty.setValue(value);
1399 if (log.isDebugEnabled()) {
1400 log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(), pathOfInstances, value);
1402 } else if (numberOfMatches == 2) {
1403 // In case of another property value match, then use the
1404 // value to be the default value of the property.
1405 instanceProperty.setDefaultValue(value);
1406 if (log.isDebugEnabled()) {
1407 log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(), pathOfInstances, value);
1420 * Add data type to graph.
1422 * 1. Add data type node
1424 * 2. Add edge between the former node to its parent(if exists)
1426 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1428 * @param dataTypeDefinition
1431 private Either<DataTypeData, TitanOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1433 log.debug("Got data type {}", dataTypeDefinition);
1435 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getName());
1437 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1439 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1440 Either<DataTypeData, TitanOperationStatus> createDataTypeResult = titanGenericDao.createNode(dataTypeData, DataTypeData.class);
1441 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1443 if (createDataTypeResult.isRight()) {
1444 TitanOperationStatus operationStatus = createDataTypeResult.right().value();
1445 log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1446 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1447 return Either.right(operationStatus);
1450 DataTypeData resultCTD = createDataTypeResult.left().value();
1451 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1452 Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(), properties);
1453 if (addPropertiesToDataType.isRight()) {
1454 log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1455 return Either.right(addPropertiesToDataType.right().value());
1458 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1459 if (derivedFrom != null) {
1460 log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1461 UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1463 String deriveFromUid = UniqueIdBuilder.buildDataTypeUid(derivedFrom);
1464 UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1465 Either<GraphRelation, TitanOperationStatus> createRelation = titanGenericDao.createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1466 log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1467 if (createRelation.isRight()) {
1468 return Either.right(createRelation.right().value());
1472 return Either.left(createDataTypeResult.left().value());
1476 private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1478 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1480 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1481 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1482 if (creationDate == null) {
1483 creationDate = System.currentTimeMillis();
1485 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1486 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1488 return dataTypeData;
1492 * add properties to capability type.
1494 * Per property, add a property node and associate it to the capability type
1500 private Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToDataType(String uniqueId, List<PropertyDefinition> properties) {
1502 Map<String, PropertyData> propertiesData = new HashMap<>();
1504 if (properties != null && !properties.isEmpty()) {
1505 for (PropertyDefinition propertyDefinition : properties) {
1506 String propertyName = propertyDefinition.getName();
1508 String propertyType = propertyDefinition.getType();
1509 Either<Boolean, TitanOperationStatus> validPropertyType = isValidPropertyType(propertyType);
1510 if (validPropertyType.isRight()) {
1511 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1512 return Either.right(validPropertyType.right().value());
1514 Boolean isValid = validPropertyType.left().value();
1515 if (isValid == null || !isValid.booleanValue()) {
1516 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1517 return Either.right(TitanOperationStatus.INVALID_TYPE);
1520 Either<PropertyData, TitanOperationStatus> addPropertyToNodeType = this.addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1521 if (addPropertyToNodeType.isRight()) {
1522 TitanOperationStatus operationStatus = addPropertyToNodeType.right().value();
1523 log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1524 BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1525 return Either.right(operationStatus);
1527 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1530 DataTypeData dataTypeData = new DataTypeData();
1531 dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1532 long modificationTime = System.currentTimeMillis();
1533 dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1535 Either<DataTypeData, TitanOperationStatus> updateNode = titanGenericDao.updateNode(dataTypeData, DataTypeData.class);
1536 if (updateNode.isRight()) {
1537 TitanOperationStatus operationStatus = updateNode.right().value();
1538 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1539 BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1540 return Either.right(operationStatus);
1542 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1547 return Either.left(propertiesData);
1552 * Build Data type object from graph by unique id
1557 public Either<DataTypeDefinition, TitanOperationStatus> getDataTypeByUid(String uniqueId) {
1559 Either<DataTypeDefinition, TitanOperationStatus> result = null;
1561 Either<DataTypeData, TitanOperationStatus> dataTypesRes = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1563 if (dataTypesRes.isRight()) {
1564 TitanOperationStatus status = dataTypesRes.right().value();
1565 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1566 return Either.right(status);
1569 DataTypeData ctData = dataTypesRes.left().value();
1570 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1572 TitanOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1573 if (propertiesStatus != TitanOperationStatus.OK) {
1574 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1575 return Either.right(propertiesStatus);
1578 Either<ImmutablePair<DataTypeData, GraphEdge>, TitanOperationStatus> parentNode = titanGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1579 DataTypeData.class);
1580 log.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
1581 if (parentNode.isRight()) {
1582 TitanOperationStatus titanOperationStatus = parentNode.right().value();
1583 if (titanOperationStatus != TitanOperationStatus.NOT_FOUND) {
1584 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, titanOperationStatus);
1585 result = Either.right(titanOperationStatus);
1589 // derived from node was found
1590 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1591 DataTypeData parentCT = immutablePair.getKey();
1593 String parentUniqueId = parentCT.getUniqueId();
1594 Either<DataTypeDefinition, TitanOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1596 if (dataTypeByUid.isRight()) {
1597 return Either.right(dataTypeByUid.right().value());
1600 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1602 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1605 result = Either.left(dataTypeDefinition);
1610 private TitanOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1612 Either<Map<String, PropertyDefinition>, TitanOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1613 if (findPropertiesOfNode.isRight()) {
1614 TitanOperationStatus titanOperationStatus = findPropertiesOfNode.right().value();
1615 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, titanOperationStatus);
1616 if (TitanOperationStatus.NOT_FOUND.equals(titanOperationStatus)) {
1617 return TitanOperationStatus.OK;
1619 return titanOperationStatus;
1622 Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1623 if (properties != null && !properties.isEmpty()) {
1624 List<PropertyDefinition> listOfProps = new ArrayList<>();
1626 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1627 String propName = entry.getKey();
1628 PropertyDefinition propertyDefinition = entry.getValue();
1629 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1630 newPropertyDefinition.setName(propName);
1631 listOfProps.add(newPropertyDefinition);
1633 dataTypeDefinition.setProperties(listOfProps);
1635 return TitanOperationStatus.OK;
1639 private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1641 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1645 Either<DataTypeData, TitanOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1647 if (eitherStatus.isRight()) {
1648 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1649 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1650 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(eitherStatus.right().value()));
1653 DataTypeData capabilityTypeData = eitherStatus.left().value();
1655 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1656 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1657 result = Either.left(dataTypeDefResult);
1661 if (!inTransaction) {
1662 if (result == null || result.isRight()) {
1663 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1664 titanGenericDao.rollback();
1666 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1667 titanGenericDao.commit();
1675 public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1676 return addDataType(dataTypeDefinition, true);
1680 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(String name, boolean inTransaction) {
1682 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1685 String dtUid = UniqueIdBuilder.buildDataTypeUid(name);
1686 Either<DataTypeDefinition, TitanOperationStatus> ctResult = this.getDataTypeByUid(dtUid);
1688 if (ctResult.isRight()) {
1689 TitanOperationStatus status = ctResult.right().value();
1690 if (status != TitanOperationStatus.NOT_FOUND) {
1691 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1693 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(ctResult.right().value()));
1697 result = Either.left(ctResult.left().value());
1701 if (!inTransaction) {
1702 if (result == null || result.isRight()) {
1703 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1704 titanGenericDao.rollback();
1706 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1707 titanGenericDao.commit();
1715 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(String name) {
1716 return getDataTypeByName(name, true);
1720 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByNameWithoutDerived(String name) {
1721 return getDataTypeByNameWithoutDerived(name, true);
1724 private Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByNameWithoutDerived(String name, boolean inTransaction) {
1726 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1729 String uid = UniqueIdBuilder.buildDataTypeUid(name);
1730 Either<DataTypeDefinition, TitanOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1732 if (ctResult.isRight()) {
1733 TitanOperationStatus status = ctResult.right().value();
1734 if (status != TitanOperationStatus.NOT_FOUND) {
1735 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1737 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(ctResult.right().value()));
1741 result = Either.left(ctResult.left().value());
1745 if (!inTransaction) {
1746 if (result == null || result.isRight()) {
1747 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1748 titanGenericDao.rollback();
1750 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1751 titanGenericDao.commit();
1758 public Either<DataTypeDefinition, TitanOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1760 Either<DataTypeData, TitanOperationStatus> dataTypesRes = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1762 if (dataTypesRes.isRight()) {
1763 TitanOperationStatus status = dataTypesRes.right().value();
1764 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1765 return Either.right(status);
1768 DataTypeData ctData = dataTypesRes.left().value();
1769 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1771 TitanOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1772 if (propertiesStatus != TitanOperationStatus.OK) {
1773 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1774 return Either.right(propertiesStatus);
1777 return Either.left(dataTypeDefinition);
1782 * convert between graph Node object to Java object
1784 * @param dataTypeData
1787 protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1788 log.debug("The object returned after create data type is {}", dataTypeData);
1790 return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1793 private Either<Boolean, TitanOperationStatus> isValidPropertyType(String propertyType) {
1795 if (propertyType == null || propertyType.isEmpty()) {
1796 return Either.left(false);
1799 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1800 if (toscaPropertyType == null) {
1801 return isDefinedInDataTypes(propertyType);
1803 return Either.left(true);
1807 public Either<Boolean, TitanOperationStatus> isDefinedInDataTypes(String propertyType) {
1809 String dataTypeUid = UniqueIdBuilder.buildDataTypeUid(propertyType);
1810 Either<DataTypeDefinition, TitanOperationStatus> dataTypeByUid = getDataTypeByUid(dataTypeUid);
1811 if (dataTypeByUid.isRight()) {
1812 TitanOperationStatus status = dataTypeByUid.right().value();
1813 if (status == TitanOperationStatus.NOT_FOUND) {
1814 return Either.left(false);
1816 return Either.right(status);
1819 return Either.left(true);
1823 public Either<Map<String, DataTypeDefinition>, TitanOperationStatus> getAllDataTypes() {
1825 Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
1826 Either<Map<String, DataTypeDefinition>, TitanOperationStatus> result = Either.left(dataTypes);
1828 Either<List<DataTypeData>, TitanOperationStatus> getAllDataTypes = titanGenericDao.getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
1829 if (getAllDataTypes.isRight()) {
1830 TitanOperationStatus status = getAllDataTypes.right().value();
1831 if (status != TitanOperationStatus.NOT_FOUND) {
1832 return Either.right(status);
1838 List<DataTypeData> list = getAllDataTypes.left().value();
1841 log.trace("Number of data types to load is {}" , list.size());
1843 List<String> collect = list.stream().map(p -> p.getDataTypeDataDefinition().getName()).collect(Collectors.toList());
1844 log.trace("The data types to load are {}" , collect);
1846 for (DataTypeData dataTypeData : list) {
1848 log.trace("Going to fetch data type {}. uid is {}", dataTypeData.getDataTypeDataDefinition().getName(), dataTypeData.getUniqueId());
1849 Either<DataTypeDefinition, TitanOperationStatus> dataTypeByUid = this.getAndAddDataTypeByUid(dataTypeData.getUniqueId(), dataTypes);
1850 if (dataTypeByUid.isRight()) {
1851 TitanOperationStatus status = dataTypeByUid.right().value();
1852 if (status == TitanOperationStatus.NOT_FOUND) {
1853 status = TitanOperationStatus.INVALID_ID;
1855 return Either.right(status);
1860 if (log.isTraceEnabled()) {
1861 if (result.isRight()) {
1862 log.trace("After fetching all data types {}" , result);
1864 Map<String, DataTypeDefinition> map = result.left().value();
1866 String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1867 log.trace("After fetching all data types {} " , types);
1876 * Build Data type object from graph by unique id
1881 private Either<DataTypeDefinition, TitanOperationStatus> getAndAddDataTypeByUid(String uniqueId, Map<String, DataTypeDefinition> allDataTypes) {
1883 Either<DataTypeDefinition, TitanOperationStatus> result = null;
1885 if (allDataTypes.containsKey(uniqueId)) {
1886 return Either.left(allDataTypes.get(uniqueId));
1889 Either<DataTypeData, TitanOperationStatus> dataTypesRes = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1891 if (dataTypesRes.isRight()) {
1892 TitanOperationStatus status = dataTypesRes.right().value();
1893 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1894 return Either.right(status);
1897 DataTypeData ctData = dataTypesRes.left().value();
1898 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1900 TitanOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1901 if (propertiesStatus != TitanOperationStatus.OK) {
1902 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1903 return Either.right(propertiesStatus);
1906 allDataTypes.put(dataTypeDefinition.getName(), dataTypeDefinition);
1908 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1909 if (allDataTypes.containsKey(derivedFrom)) {
1910 DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1912 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1914 return Either.left(dataTypeDefinition);
1917 Either<ImmutablePair<DataTypeData, GraphEdge>, TitanOperationStatus> parentNode = titanGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1918 DataTypeData.class);
1919 log.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
1920 if (parentNode.isRight()) {
1921 TitanOperationStatus titanOperationStatus = parentNode.right().value();
1922 if (titanOperationStatus != TitanOperationStatus.NOT_FOUND) {
1923 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, titanOperationStatus);
1924 result = Either.right(titanOperationStatus);
1928 // derived from node was found
1929 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1930 DataTypeData parentCT = immutablePair.getKey();
1932 String parentUniqueId = parentCT.getUniqueId();
1933 Either<DataTypeDefinition, TitanOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1935 if (dataTypeByUid.isRight()) {
1936 return Either.right(dataTypeByUid.right().value());
1939 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1941 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1944 result = Either.left(dataTypeDefinition);
1949 private Either<DataTypeDefinition, TitanOperationStatus> getDataTypeUsingName(String name) {
1950 String uid = UniqueIdBuilder.buildDataTypeUid(name);
1951 return getDataTypeByUid(uid);
1954 public Either<String, TitanOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
1956 String propertyType = propDataDef.getType();
1958 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
1960 return getInnerType(type, propDataDef::getSchema);
1963 public Either<List<DataTypeData>, TitanOperationStatus> getAllDataTypeNodes() {
1964 Either<List<DataTypeData>, TitanOperationStatus> getAllDataTypes = titanGenericDao.getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
1965 if (getAllDataTypes.isRight()) {
1966 TitanOperationStatus status = getAllDataTypes.right().value();
1967 if (status == TitanOperationStatus.NOT_FOUND) {
1968 status = TitanOperationStatus.OK;
1969 return Either.right(status);
1972 return getAllDataTypes;
1975 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType, Map<String, DataTypeDefinition> dataTypes) {
1976 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
1977 ToscaPropertyType type = getType(propertyType);
1982 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
1983 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter.validateAndUpdate(value, dataTypeDefinition, dataTypes);
1984 if (Boolean.FALSE.equals(validateResult.right)) {
1985 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
1986 return Either.right(false);
1988 JsonElement jsonElement = validateResult.left;
1989 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
1990 return Either.left(valueFromJsonElement);
1992 log.trace("before validating property type {}", propertyType);
1993 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
1994 if (!isValidProperty) {
1995 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
1996 return Either.right(false);
1999 Object convertedValue = value;
2000 if (!isEmptyValue(value) && isValidate) {
2001 PropertyValueConverter converter = type.getConverter();
2002 convertedValue = converter.convert(value, innerType, dataTypes);
2004 return Either.left(convertedValue);
2007 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType, Map<String, DataTypeDefinition> dataTypes) {
2008 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
2011 public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType, Class<T> clazz) {
2012 return this.findPropertiesOfNode(nodeType, uniqueId)
2014 .bind(this::handleNotFoundProperties)
2016 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
2019 private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(TitanOperationStatus titanOperationStatus) {
2020 if (titanOperationStatus == TitanOperationStatus.NOT_FOUND) {
2021 return Either.left(new HashMap<>());
2023 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(titanOperationStatus));
2026 private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId, NodeTypeEnum nodeType, Class<T> clazz, Collection<PropertyDefinition> nodeProps) {
2027 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
2028 String currentNodeUid = uniqueId;
2029 Either<T, StorageOperationStatus> derivedFrom;
2030 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
2031 currentNodeUid = derivedFrom.left().value().getUniqueId();
2032 TitanOperationStatus titanOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
2033 if (titanOperationStatus != TitanOperationStatus.OK) {
2034 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
2035 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(titanOperationStatus));
2038 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
2039 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
2042 private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
2043 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
2047 * @Override public PropertyOperation getPropertyOperation() { return this; }
2049 public TitanOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
2050 Either<Map<String, PropertyDefinition>, TitanOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
2051 if (findPropertiesRes.isRight()) {
2052 return findPropertiesRes.right().value();
2054 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
2055 if (properties != null) {
2056 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
2057 propertySetter.accept(propertiesAsList);
2059 return TitanOperationStatus.OK;
2062 Either<Map<String, PropertyDefinition>, TitanOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType){
2063 Either<Map<String, PropertyDefinition>, TitanOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
2064 if (findPropertiesOfNode.isRight()) {
2065 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
2066 if(findPropertiesOfNode.right().value() == TitanOperationStatus.NOT_FOUND)
2067 return Either.left(Maps.newHashMap());
2068 return findPropertiesOfNode;
2070 return findPropertiesOfNode;
2074 * add properties to element type.
2076 * Per property, add a property node and associate it to the element type
2079 * @param propertiesMap
2083 protected Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType, Map<String, PropertyDefinition> propertiesMap) {
2085 Map<String, PropertyData> propertiesData = new HashMap<>();
2087 if (propertiesMap != null) {
2089 for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
2090 String propertyName = propertyDefinitionEntry.getKey();
2092 Either<PropertyData, TitanOperationStatus> addPropertyToNodeType = this.addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
2094 if (addPropertyToNodeType.isRight()) {
2095 TitanOperationStatus operationStatus = addPropertyToNodeType.right().value();
2096 log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName, operationStatus);
2097 return Either.right(operationStatus);
2099 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
2104 return Either.left(propertiesData);
2108 public Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType, List<PropertyDefinition> properties) {
2110 Map<String, PropertyDefinition> propMap;
2111 if (properties == null) {
2114 propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
2116 return addPropertiesToElementType(uniqueId, elementType, propMap);
2120 public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition, DataTypeDefinition oldDataTypeDefinition) {
2121 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
2124 private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition, DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
2126 Either<DataTypeDefinition, StorageOperationStatus> result = null;
2130 List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
2132 List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
2134 String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
2136 String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
2138 String dataTypeName = newDataTypeDefinition.getName();
2140 List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
2141 if (isPropertyOmitted(newProperties, oldProperties, dataTypeName) || isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, propertiesToAdd) || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
2143 log.debug("The new data type {} is invalid.", dataTypeName);
2145 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
2149 if (propertiesToAdd == null || propertiesToAdd.isEmpty()) {
2150 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
2151 result = Either.right(StorageOperationStatus.OK);
2154 Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
2156 if(MapUtils.isNotEmpty(newDescriptions)){
2158 TitanOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(), newDescriptions);
2159 if (updatePropertiesStatus != TitanOperationStatus.OK) {
2160 log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}", oldDataTypeDefinition, updatePropertiesStatus);
2161 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
2162 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updatePropertiesStatus));
2167 Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToDataType = addPropertiesToDataType(oldDataTypeDefinition.getUniqueId(), propertiesToAdd);
2169 if (addPropertiesToDataType.isRight()) {
2170 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition, addPropertiesToDataType.right().value().name());
2171 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
2172 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(addPropertiesToDataType.right().value()));
2176 Either<DataTypeDefinition, TitanOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
2177 if (dataTypeByUid.isRight()) {
2178 TitanOperationStatus status = addPropertiesToDataType.right().value();
2179 log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
2180 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
2181 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
2183 result = Either.left(dataTypeByUid.left().value());
2190 if (!inTransaction) {
2191 if (result == null || result.isRight()) {
2192 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
2193 titanGenericDao.rollback();
2195 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
2196 titanGenericDao.commit();
2203 private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, List<PropertyDefinition> outputPropertiesToAdd) {
2205 if (newProperties != null && oldProperties != null) {
2207 Map<String, PropertyDefinition> newPropsMapper = newProperties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
2208 Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
2210 for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
2212 String propName = newPropertyEntry.getKey();
2213 PropertyDefinition propDef = newPropertyEntry.getValue();
2215 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
2216 if (oldPropertyDefinition == null) {
2217 log.debug("New property {} received in the data type {}", propName, dataTypeName);
2218 outputPropertiesToAdd.add(propDef);
2222 String oldType = oldPropertyDefinition.getType();
2223 String oldEntryType = getEntryType(oldPropertyDefinition);
2225 String newType = propDef.getType();
2226 String newEntryType = getEntryType(propDef);
2228 if (!oldType.equals(newType)) {
2229 log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType, newType);
2233 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
2234 log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName, oldEntryType, newEntryType);
2245 private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
2247 if (oldEntryType == null && newEntryType == null) {
2249 } else if (oldEntryType != null && newEntryType != null) {
2250 return oldEntryType.equals(newEntryType);
2256 private String getEntryType(PropertyDefinition oldPropertyDefinition) {
2257 String entryType = null;
2258 SchemaDefinition schema = oldPropertyDefinition.getSchema();
2259 if (schema != null) {
2260 PropertyDataDefinition schemaProperty = schema.getProperty();
2261 if (schemaProperty != null) {
2262 entryType = schemaProperty.getType();
2268 private boolean isPropertyOmitted(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, String dataTypeName) {
2270 boolean isValid = validateChangeInCaseOfEmptyProperties(newProperties, oldProperties, dataTypeName);
2272 log.debug("At least one property is missing in the new data type {}", dataTypeName);
2276 if (newProperties != null && oldProperties != null) {
2278 List<String> newProps = newProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
2279 List<String> oldProps = oldProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
2281 if (!newProps.containsAll(oldProps)) {
2282 StringJoiner joiner = new StringJoiner(",", "[", "]");
2283 newProps.forEach(joiner::add);
2284 log.debug("Properties {} in data type {} are missing, but they already defined in the existing data type", joiner.toString(), dataTypeName);
2292 private boolean validateChangeInCaseOfEmptyProperties(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, String dataTypeName) {
2294 if (newProperties != null) {
2295 if (newProperties.isEmpty()) {
2296 newProperties = null;
2300 if (oldProperties != null) {
2301 if (oldProperties.isEmpty()) {
2302 oldProperties = null;
2306 if ((newProperties == null && oldProperties == null) || (newProperties != null && oldProperties != null)) {
2313 private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
2315 if (newDerivedFromName != null) {
2316 boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
2318 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName, oldDerivedFromName);
2321 } else if (oldDerivedFromName == null) {
2323 } else {// new=null, old != null
2324 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName, oldDerivedFromName);
2335 public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
2336 Either<TitanGraph, TitanOperationStatus> graphResult = titanGenericDao.getGraph();
2337 if (graphResult.isRight()) {
2338 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(graphResult.right().value()));
2340 Either<TitanVertex, TitanOperationStatus> vertexService = titanGenericDao.getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
2341 if (vertexService.isRight()) {
2342 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
2343 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(vertexService.right().value()));
2345 Vertex vertex = vertexService.left().value();
2347 VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
2348 Integer counter = 0;
2349 if (vertexProperty.isPresent() && vertexProperty.value() != null) {
2350 counter = (Integer) vertexProperty.value();
2354 vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
2356 return Either.left(counter);
2360 public Either<List<PropertyDefinition>, TitanOperationStatus> validatePropertiesUniqueness(Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
2361 Either<List<PropertyDefinition>, TitanOperationStatus> result = Either.left(properties);
2363 for (PropertyDefinition property : properties) {
2364 TitanOperationStatus status = validatePropertyUniqueness(inheritedProperties, property);
2365 if (status != TitanOperationStatus.OK) {
2366 result = Either.right(status);
2375 * Validates uniqueness of examined property by comparing it with properties in propertiesOfType
2376 * and updates if need type and inner type of the property.
2378 private TitanOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2379 String propertyName = property.getName();
2380 String propertyType = property.getType();
2382 TitanOperationStatus result = TitanOperationStatus.OK;
2383 if (inheritedProperties.containsKey(propertyName)) {
2384 PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2385 if (typesMismatch(propertyType, defaultProperty.getType())) {
2386 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2387 result = TitanOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2389 property.setType(defaultProperty.getType());
2390 String innerType = defaultProperty.getSchemaType();
2392 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2393 if (schemaProperty != null) {
2394 schemaProperty.setType(innerType);
2402 private boolean typesMismatch(String type1, String type2) {
2403 return type1 != null && type2 != null && !type2.equals(type1);
2407 public <T extends GraphNode> Either<Map<String, PropertyDefinition>, TitanOperationStatus> getAllTypePropertiesFromAllDerivedFrom(String nextParentUid,
2408 NodeTypeEnum nodeType,
2410 Map<String, PropertyDefinition> allProperies = new HashMap<>();
2411 return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2414 private <T extends GraphNode> Either<Map<String, PropertyDefinition>, TitanOperationStatus> getTypePropertiesFromDerivedFromRecursively(String nextParentUid,
2415 Map<String, PropertyDefinition> allProperies,
2416 NodeTypeEnum nodeType,
2418 TitanOperationStatus error;
2419 Either<List<ImmutablePair<T, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType),
2420 nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2421 if (childrenNodes.isRight()) {
2422 if (childrenNodes.right().value() != TitanOperationStatus.NOT_FOUND) {
2423 error = childrenNodes.right().value();
2424 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid, error);
2425 return Either.right(error);
2428 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.", nextParentUid);
2429 return Either.left(allProperies);
2433 Either<Map<String, PropertyDefinition>, TitanOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2434 if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(TitanOperationStatus.NOT_FOUND)) {
2435 error = allPropertiesOfTypeRes.right().value();
2436 log.error("#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}", nextParentUid, error);
2437 return Either.right(error);
2438 } else if (allPropertiesOfTypeRes.isLeft()) {
2439 if (allProperies.isEmpty()) {
2440 allProperies.putAll(allPropertiesOfTypeRes.left().value());
2442 allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey())).collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2445 return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType, clazz);
2448 private TitanOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2450 if (MapUtils.isNotEmpty(newDescriptions)) {
2451 Either<List<ImmutablePair<TitanVertex, Edge>>, TitanOperationStatus> getDataTypePropertiesRes = titanGenericDao.getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2453 if(getDataTypePropertiesRes.isRight()){
2454 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2455 return getDataTypePropertiesRes.right().value();
2457 getDataTypePropertiesRes.left().value().stream()
2458 .filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2459 .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2462 return TitanOperationStatus.OK;
2465 private TitanVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<TitanVertex, Edge> pair) {
2466 return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2469 private String getPropertyNameFromEdge(ImmutablePair<TitanVertex, Edge> pair) {
2470 return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2473 private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2475 Map<String, PropertyDefinition> newPropertiesMap = newProperties
2477 .collect(Collectors.toMap(PropertyDefinition::getName, p->p));
2479 return oldProperties
2481 .filter(p-> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2482 .collect(Collectors.toMap(PropertyDefinition::getName, p->newPropertiesMap.get(p.getName()).getDescription()));
2485 private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty){
2486 if(StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())){
2489 if(StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())){
2492 if(StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())){
2495 return property.getDescription().equals(otherProperty.getDescription());