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.JsonArray;
28 import com.google.gson.JsonDeserializationContext;
29 import com.google.gson.JsonDeserializer;
30 import com.google.gson.JsonElement;
31 import com.google.gson.JsonObject;
32 import com.google.gson.JsonParseException;
33 import com.google.gson.JsonParser;
34 import com.google.gson.JsonSerializationContext;
35 import com.google.gson.JsonSerializer;
36 import org.janusgraph.core.JanusGraph;
37 import org.janusgraph.core.JanusGraphVertex;
38 import org.janusgraph.core.JanusGraphVertexProperty;
39 import fj.data.Either;
40 import java.io.IOException;
41 import java.lang.reflect.Type;
42 import java.util.ArrayList;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.HashMap;
46 import java.util.List;
48 import java.util.Map.Entry;
50 import java.util.StringJoiner;
51 import java.util.function.Consumer;
52 import java.util.regex.Matcher;
53 import java.util.regex.Pattern;
54 import java.util.stream.Collectors;
55 import org.apache.commons.collections.CollectionUtils;
56 import org.apache.commons.collections.MapUtils;
57 import org.apache.commons.lang3.StringUtils;
58 import org.apache.commons.lang3.tuple.ImmutablePair;
59 import org.apache.tinkerpop.gremlin.structure.Edge;
60 import org.apache.tinkerpop.gremlin.structure.Vertex;
61 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
62 import org.openecomp.sdc.be.config.BeEcompErrorManager;
63 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
64 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
65 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
66 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
67 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
68 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
69 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
70 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
71 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
72 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
73 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
74 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
75 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
76 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
77 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
78 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
79 import org.openecomp.sdc.be.model.DataTypeDefinition;
80 import org.openecomp.sdc.be.model.IComplexDefaultValue;
81 import org.openecomp.sdc.be.model.PropertyConstraint;
82 import org.openecomp.sdc.be.model.PropertyDefinition;
83 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
84 import org.openecomp.sdc.be.model.operations.api.IPropertyOperation;
85 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
86 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
87 import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType;
88 import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint;
89 import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
90 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
91 import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
92 import org.openecomp.sdc.be.model.tosca.constraints.LessThanConstraint;
93 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
94 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
95 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
96 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
97 import org.openecomp.sdc.be.resources.data.DataTypeData;
98 import org.openecomp.sdc.be.resources.data.PropertyData;
99 import org.openecomp.sdc.be.resources.data.PropertyValueData;
100 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
101 import org.openecomp.sdc.be.resources.data.UniqueIdData;
102 import org.openecomp.sdc.common.log.wrappers.Logger;
103 import org.springframework.beans.factory.annotation.Autowired;
104 import org.springframework.stereotype.Component;
107 @Component("property-operation")
108 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
109 private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
110 private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
111 private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
112 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
113 private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS = "Failed to associate resource {} to property {} in graph. status is {}";
114 private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
115 private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
116 private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
117 private DerivedFromOperation derivedFromOperation;
118 private static final String PROPERTY = "Property";
119 private static final String UPDATE_DATA_TYPE = "UpdateDataType";
121 public static void main(String[] args) {
123 List<Pattern> buildFunctionPatterns = buildFunctionPatterns();
125 for (Pattern pattern : buildFunctionPatterns) {
127 String[] strs = { "str_replace", "{ str_replace:", " {str_replace:", " { str_replace:", "{str_replace:" };
128 for (String str : strs) {
129 Matcher m = pattern.matcher(str);
130 System.out.println(pattern.pattern() + " " + str + " " + m.find());
137 public PropertyOperation(HealingJanusGraphGenericDao janusGraphGenericDao, DerivedFromOperation derivedFromOperation) {
138 this.janusGraphGenericDao = janusGraphGenericDao;
139 this.derivedFromOperation = derivedFromOperation;
142 private static Logger log = Logger.getLogger(PropertyOperation.class.getName());
145 * The value of functions is in a json format. Build pattern for each function name
147 * { str_replace: .... } {str_replace: .... } {str_replace: .... } { str_replace: .... }
151 private static List<Pattern> buildFunctionPatterns() {
153 List<Pattern> functionPatterns = new ArrayList<>();
155 String[] functions = { "get_input", "get_property" };
157 for (String function : functions) {
158 Pattern pattern = Pattern.compile("^[ ]*\\{[ ]*" + function + ":");
159 functionPatterns.add(pattern);
162 return functionPatterns;
165 public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
166 log.debug("The object returned after create property is {}", propertyDataResult);
168 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
169 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
170 propertyDefResult.setName(propertyName);
172 return propertyDefResult;
175 public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
178 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
179 JsonParser parser = new JsonParser();
180 JsonObject result = new JsonObject();
181 JsonArray jsonArray = new JsonArray();
182 if (src instanceof InRangeConstraint) {
183 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
184 jsonArray.add(parser.parse(rangeConstraint.getRangeMinValue()));
185 jsonArray.add(parser.parse(rangeConstraint.getRangeMaxValue()));
186 result.add("inRange", jsonArray);
187 } else if (src instanceof GreaterThanConstraint) {
188 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
189 jsonArray.add(parser.parse(greaterThanConstraint.getGreaterThan()));
190 result.add("greaterThan", jsonArray);
191 } else if (src instanceof LessOrEqualConstraint) {
192 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
193 jsonArray.add(parser.parse(lessOrEqualConstraint.getLessOrEqual()));
194 result.add("lessOrEqual", jsonArray);
196 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
204 public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
206 private static final String THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL = "The value of GreaterThanConstraint is null";
209 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
211 PropertyConstraint propertyConstraint = null;
213 Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
215 if (set.size() == 1) {
216 Entry<String, JsonElement> element = set.iterator().next();
217 String key = element.getKey();
218 JsonElement value = element.getValue();
220 ConstraintType constraintType = ConstraintType.getByType(key);
221 if (constraintType == null) {
222 log.warn("ConstraintType was not found for constraint name:{}", key);
224 switch (constraintType) {
228 if (value instanceof JsonArray) {
229 JsonArray rangeArray = (JsonArray) value;
230 if (rangeArray.size() != 2) {
231 log.error("The range constraint content is invalid. value = {}", value);
233 InRangeConstraint rangeConstraint = new InRangeConstraint();
234 String minValue = rangeArray.get(0).getAsString();
236 JsonElement maxElement = rangeArray.get(1);
237 if(maxElement.isJsonNull()){
238 maxValue = String.valueOf(maxElement.getAsJsonNull());
240 maxValue = maxElement.getAsString();
242 rangeConstraint.setRangeMinValue(minValue);
243 rangeConstraint.setRangeMaxValue(maxValue);
244 propertyConstraint = rangeConstraint;
249 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
254 String asString = value.getAsString();
255 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
256 propertyConstraint = new GreaterThanConstraint(asString);
259 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
265 String asString = value.getAsString();
266 log.debug("Before adding value to LessThanConstraint object. value = {}", asString);
267 propertyConstraint = new LessThanConstraint(asString);
270 log.warn("The value of LessThanConstraint is null");
273 case GREATER_OR_EQUAL:
275 String asString = value.getAsString();
276 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
277 propertyConstraint = new GreaterOrEqualConstraint(asString);
280 log.warn("The value of GreaterOrEqualConstraint is null");
286 String asString = value.getAsString();
287 log.debug("Before adding value to LessOrEqualConstraint object. value = {}", asString);
288 propertyConstraint = new LessOrEqualConstraint(asString);
290 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
297 JsonArray rangeArray = (JsonArray) value;
298 if (rangeArray.size() == 0) {
299 log.error("The valid values constraint content is invalid. value = {}", value);
301 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
302 List<String> validValues = new ArrayList<>();
303 for (JsonElement jsonElement : rangeArray) {
304 String item = jsonElement.getAsString();
305 validValues.add(item);
307 vvConstraint.setValidValues(validValues);
308 propertyConstraint = vvConstraint;
315 int asInt = value.getAsInt();
316 log.debug("Before adding value to Min Length object. value = {}", asInt);
317 propertyConstraint = new MinLengthConstraint(asInt);
320 log.warn("The value of MinLengthConstraint is null");
324 log.warn("Key {} is not supported. Ignored.", key);
329 return propertyConstraint;
335 public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
337 Either<PropertyData, JanusGraphOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
338 if (either.isRight()) {
339 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
340 return Either.right(storageStatus);
342 return Either.left(either.left().value());
346 * @param propertyDefinition
350 public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
352 log.trace("Going to validate property type and value. {}", propertyDefinition);
354 String propertyType = propertyDefinition.getType();
355 String value = propertyDefinition.getDefaultValue();
357 ToscaPropertyType type = getType(propertyType);
361 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
362 if (dataTypeDefinition == null) {
363 log.debug("The type {} of property cannot be found.", propertyType);
364 return StorageOperationStatus.INVALID_TYPE;
367 return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
370 String innerType = null;
372 Either<String, JanusGraphOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
373 if (checkInnerType.isRight()) {
374 return StorageOperationStatus.INVALID_TYPE;
376 innerType = checkInnerType.left().value();
378 log.trace("After validating property type {}", propertyType);
380 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
381 if (!isValidProperty) {
382 log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
383 return StorageOperationStatus.INVALID_VALUE;
386 PropertyValueConverter converter = type.getConverter();
388 if (isEmptyValue(value)) {
389 log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
390 propertyDefinition.setDefaultValue(EMPTY_VALUE);
391 } else if (!isEmptyValue(value)) {
392 String convertedValue = converter.convert(value, innerType, dataTypes);
393 propertyDefinition.setDefaultValue(convertedValue);
395 return StorageOperationStatus.OK;
398 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
400 ResourceMetadataData resourceData = new ResourceMetadataData();
401 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
403 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
405 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
406 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
408 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
409 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao
410 .createNode(propertyData, PropertyData.class);
411 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
412 if (createNodeResult.isRight()) {
413 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
414 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
415 return Either.right(operationStatus);
418 Map<String, Object> props = new HashMap<>();
419 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
420 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
421 .createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
422 if (createRelResult.isRight()) {
423 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
424 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
425 return Either.right(operationStatus);
428 return Either.left(createNodeResult.left().value());
432 public JanusGraphOperationStatus addPropertyToGraphByVertex(JanusGraphVertex metadataVertex, String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
434 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
436 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
437 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
439 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
440 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData);
441 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
442 if (createNodeResult.isRight()) {
443 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
444 log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
445 return operationStatus;
448 Map<String, Object> props = new HashMap<>();
449 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
450 JanusGraphVertex propertyVertex = createNodeResult.left().value();
451 JanusGraphOperationStatus
452 createRelResult = janusGraphGenericDao
453 .createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
454 if (!createRelResult.equals(JanusGraphOperationStatus.OK)) {
455 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
456 return createRelResult;
459 return createRelResult;
463 public JanusGraphGenericDao getJanusGraphGenericDao() {
464 return janusGraphGenericDao;
467 public Either<PropertyData, JanusGraphOperationStatus> deletePropertyFromGraph(String propertyId) {
468 log.debug("Before deleting property from graph {}", propertyId);
469 return janusGraphGenericDao
470 .deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
473 public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
475 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
476 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
477 return Either.right(validateAndUpdateProperty);
480 Either<PropertyData, JanusGraphOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
481 if (either.isRight()) {
482 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
483 return Either.right(storageStatus);
485 return Either.left(either.left().value());
488 public Either<PropertyData, JanusGraphOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
489 if (log.isDebugEnabled())
490 log.debug("Before updating property on graph {}", propertyId);
492 // get the original property data
493 Either<PropertyData, JanusGraphOperationStatus> statusProperty = janusGraphGenericDao
494 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
495 if (statusProperty.isRight()) {
496 log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
497 return Either.right(statusProperty.right().value());
499 PropertyData orgPropertyData = statusProperty.left().value();
500 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
502 // create new property data to update
503 PropertyData newPropertyData = new PropertyData();
504 newPropertyData.setPropertyDataDefinition(propertyDefinition);
505 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
507 // update the original property data with new values
508 if (orgPropertyDataDefinition.getDefaultValue() == null) {
509 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
511 if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
512 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
515 if (orgPropertyDataDefinition.getDescription() == null) {
516 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
518 if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
519 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
522 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
523 orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
525 if (newPropertyData.getConstraints() != null) {
526 orgPropertyData.setConstraints(newPropertyData.getConstraints());
528 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
530 return janusGraphGenericDao.updateNode(orgPropertyData, PropertyData.class);
536 * @param janusGraphGenericDao
538 public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
539 this.janusGraphGenericDao = janusGraphGenericDao;
542 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition, NodeTypeEnum nodeType, String uniqueId) {
544 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
546 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
547 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
549 if (log.isDebugEnabled())
550 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
551 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao
552 .createNode(propertyData, PropertyData.class);
553 if (log.isDebugEnabled())
554 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
555 if (createNodeResult.isRight()) {
556 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
557 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
558 return Either.right(operationStatus);
561 Map<String, Object> props = new HashMap<>();
562 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
564 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
565 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
566 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
567 .createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
568 if (createRelResult.isRight()) {
569 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
570 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
571 return Either.right(operationStatus);
574 return Either.left(createNodeResult.left().value());
578 public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
580 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
582 Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
583 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
586 if (childrenNodes.isRight()) {
587 JanusGraphOperationStatus operationStatus = childrenNodes.right().value();
588 return Either.right(operationStatus);
591 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
592 if (values != null) {
594 for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
595 GraphEdge edge = immutablePair.getValue();
596 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
597 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
598 PropertyData propertyData = immutablePair.getKey();
599 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
600 resourceProps.put(propertyName, propertyDefinition);
605 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
606 return Either.left(resourceProps);
609 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
610 return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId)
612 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
615 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId, Map<String, PropertyDefinition> newProperties) {
616 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
618 Map<String, PropertyDefinition> reallyNewProperties;
619 Map<String, PropertyData> unchangedPropsData;
621 if (oldPropertiesRes.isRight()) {
622 JanusGraphOperationStatus err = oldPropertiesRes.right().value();
623 if (err == JanusGraphOperationStatus.NOT_FOUND) {
624 reallyNewProperties = newProperties;
625 unchangedPropsData = Collections.emptyMap();
628 return Either.right(err);
632 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
633 reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
635 for(Entry<String, PropertyDefinition> oldEntry: oldProperties.entrySet()) {
636 String key = oldEntry.getKey();
637 PropertyDefinition newPropDef = newProperties != null? newProperties.get(key): null;
638 PropertyDefinition oldPropDef = oldEntry.getValue();
640 JanusGraphOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
641 if (status != JanusGraphOperationStatus.OK) {
642 return Either.right(status);
645 unchangedPropsData = oldProperties.entrySet().stream()
646 .collect(Collectors.toMap(Entry::getKey, e-> new PropertyData(e.getValue(), null)));
650 // add other properties
651 return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
655 * @param newProperties
656 * @param oldProperties
659 private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties, Map<String, PropertyDefinition> oldProperties) {
660 return newProperties != null? newProperties.entrySet().stream()
661 .filter(entry -> !oldProperties.containsKey(entry.getKey()))
662 .collect(Collectors.toMap(Entry::getKey, Entry::getValue) ): null;
669 private JanusGraphOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
670 if (!isUpdateAllowed(newPropDef, oldPropDef)) {
671 return JanusGraphOperationStatus.MATCH_NOT_FOUND;
674 if (isUpdateRequired(newPropDef, oldPropDef)) {
675 modifyOldPropByNewOne(newPropDef, oldPropDef);
677 List<PropertyConstraint> constraints = oldPropDef.getConstraints();
678 PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
679 Either<PropertyData, JanusGraphOperationStatus> updateResult = janusGraphGenericDao
680 .updateNode(node, PropertyData.class);
682 if (updateResult.isRight()) {
683 return updateResult.right().value();
687 return JanusGraphOperationStatus.OK;
694 private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
695 if (newPropDef == null) {
696 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
700 // If the property type is missing it's something that we could want to fix
701 if ( oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
702 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
710 * Update only fields which modification is permitted.
714 private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
715 oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
716 oldPropDef.setDescription(newPropDef.getDescription());
717 oldPropDef.setRequired(newPropDef.isRequired());
719 // Type is updated to fix possible null type issue in janusGraph DB
720 oldPropDef.setType(newPropDef.getType());
724 private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
725 return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) ||
726 !StringUtils.equals(oldPropDef.getDescription(), newPropDef.getDescription()) ||
727 oldPropDef.isRequired() != newPropDef.isRequired();
731 * Adds newProperties and returns in case of success (left part of Either)
732 * map of all properties i. e. added ones and contained in unchangedPropsData
735 * @param newProperties
736 * @param unchangedPropsData
739 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId, Map<String, PropertyDefinition> newProperties, Map<String, PropertyData> unchangedPropsData) {
740 return addPropertiesToElementType(uniqueId, nodeType, newProperties)
743 m.putAll(unchangedPropsData);
749 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
751 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
753 if (propertiesOfNodeRes.isRight()) {
754 JanusGraphOperationStatus status = propertiesOfNodeRes.right().value();
755 if (status == JanusGraphOperationStatus.NOT_FOUND) {
756 return Either.right(StorageOperationStatus.OK);
758 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
761 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
762 for (PropertyDefinition propertyDefinition : value.values()) {
764 String propertyUid = propertyDefinition.getUniqueId();
765 Either<PropertyData, JanusGraphOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
766 if (deletePropertyRes.isRight()) {
767 log.error("Failed to delete property with id {}", propertyUid);
768 JanusGraphOperationStatus status = deletePropertyRes.right().value();
769 if (status == JanusGraphOperationStatus.NOT_FOUND) {
770 status = JanusGraphOperationStatus.INVALID_ID;
772 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
777 log.debug("The properties deleted from node {} are {}", uniqueId, value);
778 return Either.left(value);
782 * Checks existence of a property with the same name belonging to the same resource
783 * or existence of property with the same name and different type (including derived from hierarchy)
786 * @param propertyName
787 * @param propertyType
790 public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
791 boolean result = false;
792 if (!CollectionUtils.isEmpty(properties)) {
793 for (PropertyDefinition propertyDefinition : properties) {
795 if ( propertyDefinition.getName().equals(propertyName) &&
796 (propertyDefinition.getParentUniqueId().equals(resourceUid) || !propertyDefinition.getType().equals(propertyType)) ) {
805 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType, Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
807 if (rules == null || rules.isEmpty()) {
808 return new ImmutablePair<>(null, true);
811 for (PropertyRule rule : rules) {
812 String value = rule.getValue();
813 Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
814 if (updateResult.isRight()) {
815 Boolean status = updateResult.right().value();
817 return new ImmutablePair<>(value, status);
820 String newValue = null;
821 Object object = updateResult.left().value();
822 if (object != null) {
823 newValue = object.toString();
825 rule.setValue(newValue);
829 return new ImmutablePair<>(null, true);
832 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
834 List<PropertyRule> rules = resourceInstanceProperty.getRules();
836 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
837 rules = new ArrayList<>();
838 rules.add(propertyRule);
840 rules = sortRules(rules);
843 propertyValueData.setRules(rules);
846 private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
847 List<String> path = resourceInstanceProperty.getPath();
848 // FOR BC. Since old Property values on VFC/VF does not have rules on
850 // Update could be done on one level only, thus we can use this
851 // operation to avoid migration.
852 if (path == null || path.isEmpty()) {
853 path = new ArrayList<>();
854 path.add(resourceInstanceId);
856 PropertyRule propertyRule = new PropertyRule();
857 propertyRule.setRule(path);
858 propertyRule.setValue(propertyValueData.getValue());
862 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
864 // TODO: sort the rules by size and binary representation.
865 // (x, y, .+) --> 110 6 priority 1
866 // (x, .+, z) --> 101 5 priority 2
871 public ImmutablePair<JanusGraphOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
873 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
875 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllRes = this.getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
876 if (getAllRes.isRight()) {
877 JanusGraphOperationStatus status = getAllRes.right().value();
878 log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
879 return new ImmutablePair<>(status, null);
882 List<ComponentInstanceProperty> list = getAllRes.left().value();
884 for (ComponentInstanceProperty instanceProperty : list) {
885 String propertyUniqueId = instanceProperty.getUniqueId();
886 String valueUniqueUid = instanceProperty.getValueUniqueUid();
887 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
888 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
889 log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
890 return new ImmutablePair<>(JanusGraphOperationStatus.ALREADY_EXIST, valueUniqueUid);
895 return new ImmutablePair<>(JanusGraphOperationStatus.NOT_FOUND, null);
899 public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
901 List<PropertyRule> currentRules = propertyValueData.getRules();
903 List<PropertyRule> rules = resourceInstanceProperty.getRules();
904 // if rules are not supported.
907 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
908 rules = new ArrayList<>();
909 rules.add(propertyRule);
911 if (currentRules != null) {
912 rules = mergeRules(currentRules, rules);
916 // Full mode. all rules are sent in update operation.
917 rules = sortRules(rules);
920 propertyValueData.setRules(rules);
924 private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
926 List<PropertyRule> mergedRules = new ArrayList<>();
928 if (newRules == null || newRules.isEmpty()) {
932 for (PropertyRule rule : currentRules) {
933 PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
934 mergedRules.add(propertyRule);
937 for (PropertyRule rule : newRules) {
938 PropertyRule foundRule = findRuleInList(rule, mergedRules);
939 if (foundRule != null) {
940 foundRule.setValue(rule.getValue());
942 mergedRules.add(rule);
949 private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
951 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
955 PropertyRule foundRule = null;
956 for (PropertyRule propertyRule : rules) {
957 if (rule.getRuleSize() != propertyRule.getRuleSize()) {
960 boolean equals = propertyRule.compareRule(rule);
962 foundRule = propertyRule;
971 * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
973 * @param resourceInstanceUid
976 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(String resourceInstanceUid) {
978 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
982 public Either<PropertyValueData, JanusGraphOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
984 Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
985 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
987 if (findResInstanceRes.isRight()) {
988 JanusGraphOperationStatus status = findResInstanceRes.right().value();
989 if (status == JanusGraphOperationStatus.NOT_FOUND) {
990 status = JanusGraphOperationStatus.INVALID_ID;
992 return Either.right(status);
995 Either<PropertyValueData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
996 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
998 if (findPropertyDefRes.isRight()) {
999 JanusGraphOperationStatus status = findPropertyDefRes.right().value();
1000 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1001 status = JanusGraphOperationStatus.INVALID_ID;
1003 return Either.right(status);
1006 Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
1007 .getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
1008 if (relation.isRight()) {
1009 // TODO: add error in case of error
1010 JanusGraphOperationStatus status = relation.right().value();
1011 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1012 status = JanusGraphOperationStatus.INVALID_ID;
1014 return Either.right(status);
1017 Either<PropertyValueData, JanusGraphOperationStatus> deleteNode = janusGraphGenericDao
1018 .deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
1019 if (deleteNode.isRight()) {
1020 return Either.right(deleteNode.right().value());
1022 PropertyValueData value = deleteNode.left().value();
1023 return Either.left(value);
1027 public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid, String resourceInstanceId, boolean inTransaction) {
1029 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
1033 Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = this.removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
1035 if (eitherStatus.isRight()) {
1036 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId, eitherStatus.right().value().name());
1037 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1040 PropertyValueData propertyValueData = eitherStatus.left().value();
1042 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
1043 propertyValueResult.setUniqueId(resourceInstanceId);
1044 propertyValueResult.setValue(propertyValueData.getValue());
1046 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
1047 result = Either.left(propertyValueResult);
1053 if (!inTransaction) {
1054 if (result == null || result.isRight()) {
1055 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1056 janusGraphGenericDao.rollback();
1058 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1059 janusGraphGenericDao.commit();
1066 public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty) {
1068 String value = propertyValueData.getValue();
1069 String uid = propertyValueData.getUniqueId();
1070 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
1071 instanceProperty.setPath(resourceInstanceProperty.getPath());
1073 return instanceProperty;
1077 public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
1080 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
1081 ObjectCodec oc = json.getCodec();
1082 JsonNode node = oc.readTree(json);
1088 public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
1089 if (propertyDefinition == null) {
1092 boolean isValid = false;
1093 String innerType = null;
1094 String propertyType = propertyDefinition.getType();
1095 ToscaPropertyType type = getType(propertyType);
1096 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
1097 SchemaDefinition def = propertyDefinition.getSchema();
1101 PropertyDataDefinition propDef = def.getProperty();
1102 if (propDef == null) {
1105 innerType = propDef.getType();
1107 String value = propertyDefinition.getDefaultValue();
1109 isValid = isValidValue(type, value, innerType, dataTypes);
1111 log.trace("The given type {} is not a pre defined one.", propertyType);
1113 DataTypeDefinition foundDt = dataTypes.get(propertyType);
1114 if (foundDt != null) {
1115 isValid = isValidComplexValue(foundDt, value, dataTypes);
1123 public boolean isPropertyTypeValid(IComplexDefaultValue property) {
1125 if (property == null) {
1129 if (ToscaPropertyType.isValidType(property.getType()) == null) {
1131 Either<Boolean, JanusGraphOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType());
1133 if (definedInDataTypes.isRight()) {
1136 Boolean isExist = definedInDataTypes.left().value();
1137 return isExist.booleanValue();
1145 public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
1147 if (property == null) {
1148 return new ImmutablePair<>(null, false);
1151 SchemaDefinition schema;
1152 PropertyDataDefinition innerProp;
1153 String innerType = null;
1154 if ((schema = property.getSchema()) != null) {
1155 if ((innerProp = schema.getProperty()) != null) {
1156 innerType = innerProp.getType();
1160 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
1162 if (innerToscaType == null) {
1163 DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
1164 if (dataTypeDefinition == null) {
1165 log.debug("The inner type {} is not a data type.", innerType);
1166 return new ImmutablePair<>(innerType, false);
1168 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
1172 return new ImmutablePair<>(innerType, true);
1175 private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
1176 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
1178 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
1180 return validateAndUpdate.right.booleanValue();
1184 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
1186 Either<JanusGraphVertex, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
1187 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
1189 if (findResInstanceRes.isRight()) {
1190 JanusGraphOperationStatus status = findResInstanceRes.right().value();
1191 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1192 status = JanusGraphOperationStatus.INVALID_ID;
1194 return Either.right(status);
1197 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> propertyImplNodes = janusGraphGenericDao
1198 .getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
1200 if (propertyImplNodes.isRight()) {
1201 JanusGraphOperationStatus status = propertyImplNodes.right().value();
1202 return Either.right(status);
1205 List<ImmutablePair<JanusGraphVertex, Edge>> list = propertyImplNodes.left().value();
1206 if (list == null || list.isEmpty()) {
1207 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1210 List<ComponentInstanceProperty> result = new ArrayList<>();
1211 for (ImmutablePair<JanusGraphVertex, Edge> propertyValue : list) {
1212 JanusGraphVertex propertyValueDataVertex = propertyValue.getLeft();
1213 String propertyValueUid = (String) janusGraphGenericDao
1214 .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
1215 String value = (String) janusGraphGenericDao
1216 .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
1218 ImmutablePair<JanusGraphVertex, Edge> propertyDefPair = janusGraphGenericDao
1219 .getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
1220 if (propertyDefPair == null) {
1221 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1224 Map<String, Object> properties = janusGraphGenericDao.getProperties(propertyValueDataVertex);
1225 PropertyValueData propertyValueData = GraphElementFactory.createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
1226 String propertyUniqueId = (String) janusGraphGenericDao
1227 .getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
1229 ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
1230 // set property original unique id
1231 resourceInstanceProperty.setUniqueId(propertyUniqueId);
1233 // TODO: esofer add resource id
1234 resourceInstanceProperty.setParentUniqueId(null);
1236 resourceInstanceProperty.setValue(value);
1237 // set property value unique id
1238 resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
1240 resourceInstanceProperty.setRules(propertyValueData.getRules());
1242 result.add(resourceInstanceProperty);
1245 return Either.left(result);
1249 * Find the default value from the list of component instances. Start the search from the second component instance
1251 * @param pathOfComponentInstances
1252 * @param propertyUniqueId
1253 * @param defaultValue
1256 public Either<String, JanusGraphOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances, String propertyUniqueId, String defaultValue) {
1258 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
1260 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
1261 return Either.left(defaultValue);
1264 String result = defaultValue;
1266 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
1267 String compInstanceId = pathOfComponentInstances.get(i);
1269 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> propertyValuesResult = this.getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
1271 log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
1273 if (propertyValuesResult.isRight()) {
1274 JanusGraphOperationStatus status = propertyValuesResult.right().value();
1275 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1276 return Either.right(status);
1282 ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
1283 log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
1285 if (foundCompInstanceProperty == null) {
1289 List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i), foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
1291 log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
1292 PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
1293 log.trace("Match rule is {}", matchedRule);
1295 if (matchedRule != null) {
1296 result = matchedRule.getValue();
1302 return Either.left(result);
1306 private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
1308 ComponentInstanceProperty result = null;
1314 for (ComponentInstanceProperty instProperty : list) {
1315 if (instProperty.getUniqueId().equals(propertyUniqueId)) {
1316 result = instProperty;
1324 private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
1326 if (rules != null) {
1330 rules = buildDefaultRule(compInstanceId, ruleSize, value);
1336 private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
1337 List<PropertyRule> rules = componentInstanceProperty.getRules();
1338 if (rules == null) {
1339 rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
1344 private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
1346 List<PropertyRule> rules = new ArrayList<>();
1347 List<String> rule = new ArrayList<>();
1348 rule.add(componentInstanceId);
1349 for (int i = 0; i < size - 1; i++) {
1350 rule.add(PropertyRule.getRuleAnyMatch());
1352 PropertyRule propertyRule = new PropertyRule(rule, value);
1353 rules.add(propertyRule);
1359 private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1361 PropertyRule propertyRule = null;
1363 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1365 String firstCompInstance = pathOfInstances.get(level);
1367 if (rules != null) {
1369 for (PropertyRule rule : rules) {
1371 int ruleSize = rule.getRule().size();
1372 // check the length of the rule equals to the length of the
1374 if (ruleSize != pathOfInstances.size() - level) {
1377 // check that the rule starts with correct component instance id
1378 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1382 String secondToken = rule.getToken(2);
1383 if (secondToken != null && (secondToken.equals(PropertyRule.getForceAll()) || secondToken.equals(PropertyRule.getALL()))) {
1384 propertyRule = rule;
1388 String patternStr = buildStringForMatch(rule.getRule(), 0);
1390 Pattern pattern = Pattern.compile(patternStr);
1392 Matcher matcher = pattern.matcher(stringForMatch);
1394 if (matcher.matches()) {
1395 if (log.isTraceEnabled()) {
1396 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1398 propertyRule = rule;
1405 return propertyRule;
1408 private boolean checkFirstItem(String left, String right) {
1409 if (left != null && left.equals(right)) {
1415 private String buildStringForMatch(List<String> pathOfInstances, int level) {
1416 StringBuilder builder = new StringBuilder();
1418 for (int i = level; i < pathOfInstances.size(); i++) {
1419 builder.append(pathOfInstances.get(i));
1420 if (i < pathOfInstances.size() - 1) {
1421 builder.append("#");
1424 return builder.toString();
1427 public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty, Map<String, ComponentInstanceProperty> instanceIdToValue) {
1429 List<String> pathOfInstances = instanceProperty.getPath();
1431 int size = pathOfInstances.size();
1432 int numberOfMatches = 0;
1433 for (String instanceId : pathOfInstances) {
1434 ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1436 if (componentInstanceProperty != null) {
1438 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1439 // If it is the first level instance, then update valueUniuqeId
1440 // parameter in order to know on update that
1441 // we should update and not create new node on graph.
1443 instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1444 instanceProperty.setRules(rules);
1447 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1450 String value = rule.getValue();
1451 if (numberOfMatches == 1) {
1452 instanceProperty.setValue(value);
1453 if (log.isDebugEnabled()) {
1454 log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(), pathOfInstances, value);
1456 } else if (numberOfMatches == 2) {
1457 // In case of another property value match, then use the
1458 // value to be the default value of the property.
1459 instanceProperty.setDefaultValue(value);
1460 if (log.isDebugEnabled()) {
1461 log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(), pathOfInstances, value);
1474 * Add data type to graph.
1476 * 1. Add data type node
1478 * 2. Add edge between the former node to its parent(if exists)
1480 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1482 * @param dataTypeDefinition
1485 private Either<DataTypeData, JanusGraphOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1487 log.debug("Got data type {}", dataTypeDefinition);
1489 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getName());
1491 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1493 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1494 Either<DataTypeData, JanusGraphOperationStatus> createDataTypeResult = janusGraphGenericDao
1495 .createNode(dataTypeData, DataTypeData.class);
1496 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1498 if (createDataTypeResult.isRight()) {
1499 JanusGraphOperationStatus operationStatus = createDataTypeResult.right().value();
1500 log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1501 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1502 return Either.right(operationStatus);
1505 DataTypeData resultCTD = createDataTypeResult.left().value();
1506 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1507 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(), properties);
1508 if (addPropertiesToDataType.isRight()) {
1509 log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1510 return Either.right(addPropertiesToDataType.right().value());
1513 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1514 if (derivedFrom != null) {
1515 log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1516 UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1518 String deriveFromUid = UniqueIdBuilder.buildDataTypeUid(derivedFrom);
1519 UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1520 Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
1521 .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1522 log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1523 if (createRelation.isRight()) {
1524 return Either.right(createRelation.right().value());
1528 return Either.left(createDataTypeResult.left().value());
1532 private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1534 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1536 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1537 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1538 if (creationDate == null) {
1539 creationDate = System.currentTimeMillis();
1541 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1542 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1544 return dataTypeData;
1548 * add properties to capability type.
1550 * Per property, add a property node and associate it to the capability type
1556 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType(String uniqueId, List<PropertyDefinition> properties) {
1558 Map<String, PropertyData> propertiesData = new HashMap<>();
1560 if (properties != null && !properties.isEmpty()) {
1561 for (PropertyDefinition propertyDefinition : properties) {
1562 String propertyName = propertyDefinition.getName();
1564 String propertyType = propertyDefinition.getType();
1565 Either<Boolean, JanusGraphOperationStatus> validPropertyType = isValidPropertyType(propertyType);
1566 if (validPropertyType.isRight()) {
1567 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1568 return Either.right(validPropertyType.right().value());
1570 Boolean isValid = validPropertyType.left().value();
1571 if (isValid == null || !isValid.booleanValue()) {
1572 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1573 return Either.right(JanusGraphOperationStatus.INVALID_TYPE);
1576 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this.addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1577 if (addPropertyToNodeType.isRight()) {
1578 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1579 log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1580 BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1581 return Either.right(operationStatus);
1583 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1586 DataTypeData dataTypeData = new DataTypeData();
1587 dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1588 long modificationTime = System.currentTimeMillis();
1589 dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1591 Either<DataTypeData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao
1592 .updateNode(dataTypeData, DataTypeData.class);
1593 if (updateNode.isRight()) {
1594 JanusGraphOperationStatus operationStatus = updateNode.right().value();
1595 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1596 BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1597 return Either.right(operationStatus);
1599 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1604 return Either.left(propertiesData);
1609 * Build Data type object from graph by unique id
1614 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUid(String uniqueId) {
1616 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1618 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1619 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1621 if (dataTypesRes.isRight()) {
1622 JanusGraphOperationStatus status = dataTypesRes.right().value();
1623 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1624 return Either.right(status);
1627 DataTypeData ctData = dataTypesRes.left().value();
1628 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1630 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1631 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1632 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1633 return Either.right(propertiesStatus);
1636 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1637 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1638 DataTypeData.class);
1639 log.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
1640 if (parentNode.isRight()) {
1641 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1642 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1643 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId,
1644 janusGraphOperationStatus);
1645 result = Either.right(janusGraphOperationStatus);
1649 // derived from node was found
1650 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1651 DataTypeData parentCT = immutablePair.getKey();
1653 String parentUniqueId = parentCT.getUniqueId();
1654 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1656 if (dataTypeByUid.isRight()) {
1657 return Either.right(dataTypeByUid.right().value());
1660 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1662 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1665 result = Either.left(dataTypeDefinition);
1670 private JanusGraphOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1672 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1673 if (findPropertiesOfNode.isRight()) {
1674 JanusGraphOperationStatus janusGraphOperationStatus = findPropertiesOfNode.right().value();
1675 log.debug("After looking for properties of vertex {}. status is {}", uniqueId,
1676 janusGraphOperationStatus);
1677 if (JanusGraphOperationStatus.NOT_FOUND.equals(janusGraphOperationStatus)) {
1678 return JanusGraphOperationStatus.OK;
1680 return janusGraphOperationStatus;
1683 Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1684 if (properties != null && !properties.isEmpty()) {
1685 List<PropertyDefinition> listOfProps = new ArrayList<>();
1687 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1688 String propName = entry.getKey();
1689 PropertyDefinition propertyDefinition = entry.getValue();
1690 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1691 newPropertyDefinition.setName(propName);
1692 listOfProps.add(newPropertyDefinition);
1694 dataTypeDefinition.setProperties(listOfProps);
1696 return JanusGraphOperationStatus.OK;
1700 private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1702 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1706 Either<DataTypeData, JanusGraphOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1708 if (eitherStatus.isRight()) {
1709 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1710 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1711 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1714 DataTypeData capabilityTypeData = eitherStatus.left().value();
1716 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1717 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1718 result = Either.left(dataTypeDefResult);
1722 if (!inTransaction) {
1723 if (result == null || result.isRight()) {
1724 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1725 janusGraphGenericDao.rollback();
1727 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1728 janusGraphGenericDao.commit();
1736 public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1737 return addDataType(dataTypeDefinition, true);
1741 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(String name, boolean inTransaction) {
1743 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1746 String dtUid = UniqueIdBuilder.buildDataTypeUid(name);
1747 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUid(dtUid);
1749 if (ctResult.isRight()) {
1750 JanusGraphOperationStatus status = ctResult.right().value();
1751 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1752 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1754 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1758 result = Either.left(ctResult.left().value());
1762 if (!inTransaction) {
1763 if (result == null || result.isRight()) {
1764 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1765 janusGraphGenericDao.rollback();
1767 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1768 janusGraphGenericDao.commit();
1776 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(String name) {
1777 return getDataTypeByName(name, true);
1781 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByNameWithoutDerived(String name) {
1782 return getDataTypeByNameWithoutDerived(name, true);
1785 private Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByNameWithoutDerived(String name, boolean inTransaction) {
1787 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1790 String uid = UniqueIdBuilder.buildDataTypeUid(name);
1791 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1793 if (ctResult.isRight()) {
1794 JanusGraphOperationStatus status = ctResult.right().value();
1795 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1796 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1798 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1802 result = Either.left(ctResult.left().value());
1806 if (!inTransaction) {
1807 if (result == null || result.isRight()) {
1808 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1809 janusGraphGenericDao.rollback();
1811 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1812 janusGraphGenericDao.commit();
1819 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1821 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1822 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1824 if (dataTypesRes.isRight()) {
1825 JanusGraphOperationStatus status = dataTypesRes.right().value();
1826 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1827 return Either.right(status);
1830 DataTypeData ctData = dataTypesRes.left().value();
1831 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1833 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1834 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1835 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1836 return Either.right(propertiesStatus);
1839 return Either.left(dataTypeDefinition);
1844 * convert between graph Node object to Java object
1846 * @param dataTypeData
1849 protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1850 log.debug("The object returned after create data type is {}", dataTypeData);
1852 return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1855 private Either<Boolean, JanusGraphOperationStatus> isValidPropertyType(String propertyType) {
1857 if (propertyType == null || propertyType.isEmpty()) {
1858 return Either.left(false);
1861 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1862 if (toscaPropertyType == null) {
1863 return isDefinedInDataTypes(propertyType);
1865 return Either.left(true);
1869 public Either<Boolean, JanusGraphOperationStatus> isDefinedInDataTypes(String propertyType) {
1871 String dataTypeUid = UniqueIdBuilder.buildDataTypeUid(propertyType);
1872 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(dataTypeUid);
1873 if (dataTypeByUid.isRight()) {
1874 JanusGraphOperationStatus status = dataTypeByUid.right().value();
1875 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1876 return Either.left(false);
1878 return Either.right(status);
1881 return Either.left(true);
1885 public Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> getAllDataTypes() {
1887 Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
1888 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> result = Either.left(dataTypes);
1890 Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypes = janusGraphGenericDao
1891 .getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
1892 if (getAllDataTypes.isRight()) {
1893 JanusGraphOperationStatus status = getAllDataTypes.right().value();
1894 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1895 return Either.right(status);
1901 List<DataTypeData> list = getAllDataTypes.left().value();
1904 log.trace("Number of data types to load is {}" , list.size());
1906 List<String> collect = list.stream().map(p -> p.getDataTypeDataDefinition().getName()).collect(Collectors.toList());
1907 log.trace("The data types to load are {}" , collect);
1909 for (DataTypeData dataTypeData : list) {
1911 log.trace("Going to fetch data type {}. uid is {}", dataTypeData.getDataTypeDataDefinition().getName(), dataTypeData.getUniqueId());
1912 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getAndAddDataTypeByUid(dataTypeData.getUniqueId(), dataTypes);
1913 if (dataTypeByUid.isRight()) {
1914 JanusGraphOperationStatus status = dataTypeByUid.right().value();
1915 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1916 status = JanusGraphOperationStatus.INVALID_ID;
1918 return Either.right(status);
1923 if (log.isTraceEnabled()) {
1924 if (result.isRight()) {
1925 log.trace("After fetching all data types {}" , result);
1927 Map<String, DataTypeDefinition> map = result.left().value();
1929 String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1930 log.trace("After fetching all data types {} " , types);
1939 * Build Data type object from graph by unique id
1944 private Either<DataTypeDefinition, JanusGraphOperationStatus> getAndAddDataTypeByUid(String uniqueId, Map<String, DataTypeDefinition> allDataTypes) {
1946 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1948 if (allDataTypes.containsKey(uniqueId)) {
1949 return Either.left(allDataTypes.get(uniqueId));
1952 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1953 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1955 if (dataTypesRes.isRight()) {
1956 JanusGraphOperationStatus status = dataTypesRes.right().value();
1957 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1958 return Either.right(status);
1961 DataTypeData ctData = dataTypesRes.left().value();
1962 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1964 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1965 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1966 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1967 return Either.right(propertiesStatus);
1970 allDataTypes.put(dataTypeDefinition.getName(), dataTypeDefinition);
1972 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1973 if (allDataTypes.containsKey(derivedFrom)) {
1974 DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1976 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1978 return Either.left(dataTypeDefinition);
1981 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1982 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1983 DataTypeData.class);
1984 log.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
1985 if (parentNode.isRight()) {
1986 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1987 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1988 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId,
1989 janusGraphOperationStatus);
1990 result = Either.right(janusGraphOperationStatus);
1994 // derived from node was found
1995 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1996 DataTypeData parentCT = immutablePair.getKey();
1998 String parentUniqueId = parentCT.getUniqueId();
1999 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
2001 if (dataTypeByUid.isRight()) {
2002 return Either.right(dataTypeByUid.right().value());
2005 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
2007 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
2010 result = Either.left(dataTypeDefinition);
2015 private Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeUsingName(String name) {
2016 String uid = UniqueIdBuilder.buildDataTypeUid(name);
2017 return getDataTypeByUid(uid);
2020 public Either<String, JanusGraphOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
2022 String propertyType = propDataDef.getType();
2024 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
2026 return getInnerType(type, propDataDef::getSchema);
2029 public Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypeNodes() {
2030 Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypes = janusGraphGenericDao
2031 .getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
2032 if (getAllDataTypes.isRight()) {
2033 JanusGraphOperationStatus status = getAllDataTypes.right().value();
2034 if (status == JanusGraphOperationStatus.NOT_FOUND) {
2035 status = JanusGraphOperationStatus.OK;
2036 return Either.right(status);
2039 return getAllDataTypes;
2042 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType, Map<String, DataTypeDefinition> dataTypes) {
2043 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
2044 ToscaPropertyType type = getType(propertyType);
2049 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
2050 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter.validateAndUpdate(value, dataTypeDefinition, dataTypes);
2051 if (Boolean.FALSE.equals(validateResult.right)) {
2052 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
2053 return Either.right(false);
2055 JsonElement jsonElement = validateResult.left;
2056 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
2057 return Either.left(valueFromJsonElement);
2059 log.trace("before validating property type {}", propertyType);
2060 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
2061 if (!isValidProperty) {
2062 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
2063 return Either.right(false);
2066 Object convertedValue = value;
2067 if (!isEmptyValue(value) && isValidate) {
2068 PropertyValueConverter converter = type.getConverter();
2069 convertedValue = converter.convert(value, innerType, dataTypes);
2071 return Either.left(convertedValue);
2074 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType, Map<String, DataTypeDefinition> dataTypes) {
2075 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
2078 public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType, Class<T> clazz) {
2079 return this.findPropertiesOfNode(nodeType, uniqueId)
2081 .bind(this::handleNotFoundProperties)
2083 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
2086 private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(JanusGraphOperationStatus janusGraphOperationStatus) {
2087 if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
2088 return Either.left(new HashMap<>());
2090 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(
2091 janusGraphOperationStatus));
2094 private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId, NodeTypeEnum nodeType, Class<T> clazz, Collection<PropertyDefinition> nodeProps) {
2095 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
2096 String currentNodeUid = uniqueId;
2097 Either<T, StorageOperationStatus> derivedFrom;
2098 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
2099 currentNodeUid = derivedFrom.left().value().getUniqueId();
2100 JanusGraphOperationStatus
2101 janusGraphOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
2102 if (janusGraphOperationStatus != JanusGraphOperationStatus.OK) {
2103 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
2104 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(
2105 janusGraphOperationStatus));
2108 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
2109 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
2112 private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
2113 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
2117 * @Override public PropertyOperation getPropertyOperation() { return this; }
2119 public JanusGraphOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
2120 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
2121 if (findPropertiesRes.isRight()) {
2122 return findPropertiesRes.right().value();
2124 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
2125 if (properties != null) {
2126 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
2127 propertySetter.accept(propertiesAsList);
2129 return JanusGraphOperationStatus.OK;
2132 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType){
2133 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
2134 if (findPropertiesOfNode.isRight()) {
2135 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
2136 if(findPropertiesOfNode.right().value() == JanusGraphOperationStatus.NOT_FOUND)
2137 return Either.left(Maps.newHashMap());
2138 return findPropertiesOfNode;
2140 return findPropertiesOfNode;
2144 * add properties to element type.
2146 * Per property, add a property node and associate it to the element type
2149 * @param propertiesMap
2153 protected Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType, Map<String, PropertyDefinition> propertiesMap) {
2155 Map<String, PropertyData> propertiesData = new HashMap<>();
2157 if (propertiesMap != null) {
2159 for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
2160 String propertyName = propertyDefinitionEntry.getKey();
2162 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this.addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
2164 if (addPropertyToNodeType.isRight()) {
2165 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
2166 log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName, operationStatus);
2167 return Either.right(operationStatus);
2169 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
2174 return Either.left(propertiesData);
2178 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType, List<PropertyDefinition> properties) {
2180 Map<String, PropertyDefinition> propMap;
2181 if (properties == null) {
2184 propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
2186 return addPropertiesToElementType(uniqueId, elementType, propMap);
2190 public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition, DataTypeDefinition oldDataTypeDefinition) {
2191 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
2194 private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition, DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
2196 Either<DataTypeDefinition, StorageOperationStatus> result = null;
2200 List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
2202 List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
2204 String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
2206 String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
2208 String dataTypeName = newDataTypeDefinition.getName();
2210 List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
2211 if (isPropertyOmitted(newProperties, oldProperties, dataTypeName) || isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, propertiesToAdd) || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
2213 log.debug("The new data type {} is invalid.", dataTypeName);
2215 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
2219 if (propertiesToAdd == null || propertiesToAdd.isEmpty()) {
2220 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
2221 result = Either.right(StorageOperationStatus.OK);
2224 Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
2226 if(MapUtils.isNotEmpty(newDescriptions)){
2228 JanusGraphOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(), newDescriptions);
2229 if (updatePropertiesStatus != JanusGraphOperationStatus.OK) {
2230 log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}", oldDataTypeDefinition, updatePropertiesStatus);
2231 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
2232 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatePropertiesStatus));
2237 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(oldDataTypeDefinition.getUniqueId(), propertiesToAdd);
2239 if (addPropertiesToDataType.isRight()) {
2240 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition, addPropertiesToDataType.right().value().name());
2241 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
2242 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToDataType.right().value()));
2246 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
2247 if (dataTypeByUid.isRight()) {
2248 JanusGraphOperationStatus status = addPropertiesToDataType.right().value();
2249 log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
2250 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
2251 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
2253 result = Either.left(dataTypeByUid.left().value());
2260 if (!inTransaction) {
2261 if (result == null || result.isRight()) {
2262 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
2263 janusGraphGenericDao.rollback();
2265 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
2266 janusGraphGenericDao.commit();
2273 private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, List<PropertyDefinition> outputPropertiesToAdd) {
2275 if (newProperties != null && oldProperties != null) {
2277 Map<String, PropertyDefinition> newPropsMapper = newProperties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
2278 Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
2280 for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
2282 String propName = newPropertyEntry.getKey();
2283 PropertyDefinition propDef = newPropertyEntry.getValue();
2285 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
2286 if (oldPropertyDefinition == null) {
2287 log.debug("New property {} received in the data type {}", propName, dataTypeName);
2288 outputPropertiesToAdd.add(propDef);
2292 String oldType = oldPropertyDefinition.getType();
2293 String oldEntryType = getEntryType(oldPropertyDefinition);
2295 String newType = propDef.getType();
2296 String newEntryType = getEntryType(propDef);
2298 if (!oldType.equals(newType)) {
2299 log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType, newType);
2303 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
2304 log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName, oldEntryType, newEntryType);
2315 private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
2317 if (oldEntryType == null && newEntryType == null) {
2319 } else if (oldEntryType != null && newEntryType != null) {
2320 return oldEntryType.equals(newEntryType);
2326 private String getEntryType(PropertyDefinition oldPropertyDefinition) {
2327 String entryType = null;
2328 SchemaDefinition schema = oldPropertyDefinition.getSchema();
2329 if (schema != null) {
2330 PropertyDataDefinition schemaProperty = schema.getProperty();
2331 if (schemaProperty != null) {
2332 entryType = schemaProperty.getType();
2338 private boolean isPropertyOmitted(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, String dataTypeName) {
2340 boolean isValid = validateChangeInCaseOfEmptyProperties(newProperties, oldProperties, dataTypeName);
2342 log.debug("At least one property is missing in the new data type {}", dataTypeName);
2346 if (newProperties != null && oldProperties != null) {
2348 List<String> newProps = newProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
2349 List<String> oldProps = oldProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
2351 if (!newProps.containsAll(oldProps)) {
2352 StringJoiner joiner = new StringJoiner(",", "[", "]");
2353 newProps.forEach(joiner::add);
2354 log.debug("Properties {} in data type {} are missing, but they already defined in the existing data type", joiner.toString(), dataTypeName);
2362 private boolean validateChangeInCaseOfEmptyProperties(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, String dataTypeName) {
2364 if (newProperties != null) {
2365 if (newProperties.isEmpty()) {
2366 newProperties = null;
2370 if (oldProperties != null) {
2371 if (oldProperties.isEmpty()) {
2372 oldProperties = null;
2376 if ((newProperties == null && oldProperties == null) || (newProperties != null && oldProperties != null)) {
2383 private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
2385 if (newDerivedFromName != null) {
2386 boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
2388 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName, oldDerivedFromName);
2391 } else if (oldDerivedFromName == null) {
2393 } else {// new=null, old != null
2394 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName, oldDerivedFromName);
2405 public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
2406 Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
2407 if (graphResult.isRight()) {
2408 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
2410 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
2411 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
2412 if (vertexService.isRight()) {
2413 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
2414 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
2416 Vertex vertex = vertexService.left().value();
2418 VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
2419 Integer counter = 0;
2420 if (vertexProperty.isPresent() && vertexProperty.value() != null) {
2421 counter = (Integer) vertexProperty.value();
2425 vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
2427 return Either.left(counter);
2431 public Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesUniqueness(Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
2432 Either<List<PropertyDefinition>, JanusGraphOperationStatus> result = Either.left(properties);
2434 for (PropertyDefinition property : properties) {
2435 JanusGraphOperationStatus
2436 status = validatePropertyUniqueness(inheritedProperties, property);
2437 if (status != JanusGraphOperationStatus.OK) {
2438 result = Either.right(status);
2447 * Validates uniqueness of examined property by comparing it with properties in propertiesOfType
2448 * and updates if need type and inner type of the property.
2450 private JanusGraphOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2451 String propertyName = property.getName();
2452 String propertyType = property.getType();
2454 JanusGraphOperationStatus result = JanusGraphOperationStatus.OK;
2455 if (inheritedProperties.containsKey(propertyName)) {
2456 PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2457 if (typesMismatch(propertyType, defaultProperty.getType())) {
2458 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2459 result = JanusGraphOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2461 property.setType(defaultProperty.getType());
2462 String innerType = defaultProperty.getSchemaType();
2464 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2465 if (schemaProperty != null) {
2466 schemaProperty.setType(innerType);
2474 private boolean typesMismatch(String type1, String type2) {
2475 return type1 != null && type2 != null && !type2.equals(type1);
2479 public <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllTypePropertiesFromAllDerivedFrom(String nextParentUid,
2480 NodeTypeEnum nodeType,
2482 Map<String, PropertyDefinition> allProperies = new HashMap<>();
2483 return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2486 private <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getTypePropertiesFromDerivedFromRecursively(String nextParentUid,
2487 Map<String, PropertyDefinition> allProperies,
2488 NodeTypeEnum nodeType,
2490 JanusGraphOperationStatus error;
2491 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
2492 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType),
2493 nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2494 if (childrenNodes.isRight()) {
2495 if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
2496 error = childrenNodes.right().value();
2497 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid, error);
2498 return Either.right(error);
2501 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.", nextParentUid);
2502 return Either.left(allProperies);
2506 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2507 if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(
2508 JanusGraphOperationStatus.NOT_FOUND)) {
2509 error = allPropertiesOfTypeRes.right().value();
2510 log.error("#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}", nextParentUid, error);
2511 return Either.right(error);
2512 } else if (allPropertiesOfTypeRes.isLeft()) {
2513 if (allProperies.isEmpty()) {
2514 allProperies.putAll(allPropertiesOfTypeRes.left().value());
2516 allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey())).collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2519 return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType, clazz);
2522 private JanusGraphOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2524 if (MapUtils.isNotEmpty(newDescriptions)) {
2525 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getDataTypePropertiesRes = janusGraphGenericDao
2526 .getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2528 if(getDataTypePropertiesRes.isRight()){
2529 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2530 return getDataTypePropertiesRes.right().value();
2532 getDataTypePropertiesRes.left().value().stream()
2533 .filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2534 .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2537 return JanusGraphOperationStatus.OK;
2540 private JanusGraphVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<JanusGraphVertex, Edge> pair) {
2541 return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2544 private String getPropertyNameFromEdge(ImmutablePair<JanusGraphVertex, Edge> pair) {
2545 return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2548 private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2550 Map<String, PropertyDefinition> newPropertiesMap = newProperties
2552 .collect(Collectors.toMap(PropertyDefinition::getName, p->p));
2554 return oldProperties
2556 .filter(p-> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2557 .collect(Collectors.toMap(PropertyDefinition::getName, p->newPropertiesMap.get(p.getName()).getDescription()));
2560 private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty){
2561 if(StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())){
2564 if(StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())){
2567 if(StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())){
2570 return property.getDescription().equals(otherProperty.getDescription());