Upgrade SDC from Titan to Janus Graph
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / operations / impl / PropertyOperation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.be.model.operations.impl;
22
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;
47 import java.util.Map;
48 import java.util.Map.Entry;
49 import java.util.Set;
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.stereotype.Component;
104
105
106 @Component("property-operation")
107 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
108         private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
109         private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
110         private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
111         private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
112         private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS = "Failed to associate resource {} to property {} in graph. status is {}";
113         private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
114         private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
115         private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
116         private DerivedFromOperation derivedFromOperation;
117     private static final String PROPERTY = "Property";
118     private static final String UPDATE_DATA_TYPE = "UpdateDataType";
119
120         public static void main(String[] args) {
121
122                 List<Pattern> buildFunctionPatterns = buildFunctionPatterns();
123
124                 for (Pattern pattern : buildFunctionPatterns) {
125
126                         String[] strs = { "str_replace", "{ str_replace:", " {str_replace:", " {   str_replace:", "{str_replace:" };
127                         for (String str : strs) {
128                                 Matcher m = pattern.matcher(str);
129                                 System.out.println(pattern.pattern() + " " + str + " " + m.find());
130                         }
131                 }
132
133         }
134
135         public PropertyOperation(HealingJanusGraphGenericDao janusGraphGenericDao, DerivedFromOperation derivedFromOperation) {
136                 this.janusGraphGenericDao = janusGraphGenericDao;
137                 this.derivedFromOperation = derivedFromOperation;
138         }
139
140         private static Logger log = Logger.getLogger(PropertyOperation.class.getName());
141
142         /**
143          * The value of functions is in a json format. Build pattern for each function name
144          * 
145          * { str_replace: .... } {str_replace: .... } {str_replace: .... } { str_replace: .... }
146          * 
147          * @return
148          */
149         private static List<Pattern> buildFunctionPatterns() {
150
151                 List<Pattern> functionPatterns = new ArrayList<>();
152
153                 String[] functions = { "get_input", "get_property" };
154
155                 for (String function : functions) {
156                         Pattern pattern = Pattern.compile("^[ ]*\\{[ ]*" + function + ":");
157                         functionPatterns.add(pattern);
158                 }
159
160                 return functionPatterns;
161         }
162
163         public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
164                 log.debug("The object returned after create property is {}", propertyDataResult);
165
166                 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
167                 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
168                 propertyDefResult.setName(propertyName);
169
170                 return propertyDefResult;
171         }
172
173         public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
174
175                 @Override
176                 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
177                         JsonParser parser = new JsonParser();
178                         JsonObject result = new JsonObject();
179                         JsonArray jsonArray = new JsonArray();
180                         if (src instanceof InRangeConstraint) {
181                                 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
182                                 jsonArray.add(parser.parse(rangeConstraint.getRangeMinValue()));
183                                 jsonArray.add(parser.parse(rangeConstraint.getRangeMaxValue()));
184                                 result.add("inRange", jsonArray);
185                         } else if (src instanceof GreaterThanConstraint) {
186                                 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
187                                 jsonArray.add(parser.parse(greaterThanConstraint.getGreaterThan()));
188                                 result.add("greaterThan", jsonArray);
189                         } else if (src instanceof LessOrEqualConstraint) {
190                                 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
191                                 jsonArray.add(parser.parse(lessOrEqualConstraint.getLessOrEqual()));
192                                 result.add("lessOrEqual", jsonArray);
193                         } else {
194                                 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
195                         }
196
197                         return result;
198                 }
199
200         }
201
202         public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
203
204                 private static final String THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL = "The value of GreaterThanConstraint is null";
205
206                 @Override
207                 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
208
209                         PropertyConstraint propertyConstraint = null;
210
211                         Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
212
213                         if (set.size() == 1) {
214                                 Entry<String, JsonElement> element = set.iterator().next();
215                                 String key = element.getKey();
216                                 JsonElement value = element.getValue();
217
218                                 ConstraintType constraintType = ConstraintType.getByType(key);
219                                 if (constraintType == null) {
220                                         log.warn("ConstraintType was not found for constraint name:{}", key);
221                                 } else {
222                                         switch (constraintType) {
223                                         case IN_RANGE:
224
225                                                 if (value != null) {
226                                                         if (value instanceof JsonArray) {
227                                                                 JsonArray rangeArray = (JsonArray) value;
228                                                                 if (rangeArray.size() != 2) {
229                                                                         log.error("The range constraint content is invalid. value = {}", value);
230                                                                 } else {
231                                                                         InRangeConstraint rangeConstraint = new InRangeConstraint();
232                                                                         String minValue = rangeArray.get(0).getAsString();
233                                                                         String maxValue = rangeArray.get(1).getAsString();
234                                                                         rangeConstraint.setRangeMinValue(minValue);
235                                                                         rangeConstraint.setRangeMaxValue(maxValue);
236                                                                         propertyConstraint = rangeConstraint;
237                                                                 }
238                                                         }
239
240                                                 } else {
241                                                         log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
242                                                 }
243                                                 break;
244                                         case GREATER_THAN:
245                                                 if (value != null) {
246                                                         String asString = value.getAsString();
247                                                         log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
248                                                         propertyConstraint = new GreaterThanConstraint(asString);
249                                                         break;
250                                                 } else {
251                                                         log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
252                                                 }
253                                                 break;
254
255                                         case LESS_THAN:
256                                                 if (value != null) {
257                                                         String asString = value.getAsString();
258                                                         log.debug("Before adding value to LessThanConstraint object. value = {}", asString);
259                                                         propertyConstraint = new LessThanConstraint(asString);
260                                                         break;
261                                                 } else {
262                                                         log.warn("The value of LessThanConstraint is null");
263                                                 }
264                                                 break;
265                                         case GREATER_OR_EQUAL:
266                                                 if (value != null) {
267                                                         String asString = value.getAsString();
268                                                         log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
269                                                         propertyConstraint = new GreaterOrEqualConstraint(asString);
270                                                         break;
271                                                 } else {
272                                                         log.warn("The value of GreaterOrEqualConstraint is null");
273                                                 }
274                                                 break;
275                                         case LESS_OR_EQUAL:
276
277                                                 if (value != null) {
278                                                         String asString = value.getAsString();
279                                                         log.debug("Before adding value to LessOrEqualConstraint object. value = {}", asString);
280                                                         propertyConstraint = new LessOrEqualConstraint(asString);
281                                                 } else {
282                                                         log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
283                                                 }
284                                                 break;
285
286                                         case VALID_VALUES:
287
288                                                 if (value != null) {
289                                                         if (value instanceof JsonArray) {
290                                                                 JsonArray rangeArray = (JsonArray) value;
291                                                                 if (rangeArray.size() == 0) {
292                                                                         log.error("The valid values constraint content is invalid. value = {}", value);
293                                                                 } else {
294                                                                         ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
295                                                                         List<String> validValues = new ArrayList<>();
296                                                                         for (JsonElement jsonElement : rangeArray) {
297                                                                                 String item = jsonElement.getAsString();
298                                                                                 validValues.add(item);
299                                                                         }
300                                                                         vvConstraint.setValidValues(validValues);
301                                                                         propertyConstraint = vvConstraint;
302                                                                 }
303                                                         }
304
305                                                 } else {
306                                                         log.warn("The value of ValidValuesConstraint is null");
307                                                 }
308                                                 break;
309
310                                         case MIN_LENGTH:
311                                                 if (value != null) {
312                                                         int asInt = value.getAsInt();
313                                                         log.debug("Before adding value to Min Length object. value = {}", asInt);
314                                                         propertyConstraint = new MinLengthConstraint(asInt);
315                                                         break;
316                                                 } else {
317                                                         log.warn("The value of MinLengthConstraint is null");
318                                                 }
319                                                 break;
320                                         default:
321                                                 log.warn("Key {} is not supported. Ignored.", key);
322                                         }
323                                 }
324                         }
325
326                         return propertyConstraint;
327                 }
328
329         }
330
331
332         public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
333
334                 Either<PropertyData, JanusGraphOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
335                 if (either.isRight()) {
336                         StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
337                         return Either.right(storageStatus);
338                 }
339                 return Either.left(either.left().value());
340         }
341
342         /**
343          * @param propertyDefinition
344          * @return
345          */
346         @Override
347         public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
348
349                 log.trace("Going to validate property type and value. {}", propertyDefinition);
350
351                 String propertyType = propertyDefinition.getType();
352                 String value = propertyDefinition.getDefaultValue();
353
354                 ToscaPropertyType type = getType(propertyType);
355
356                 if (type == null) {
357
358                         DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
359                         if (dataTypeDefinition == null) {
360                                 log.debug("The type {} of property cannot be found.", propertyType);
361                                 return StorageOperationStatus.INVALID_TYPE;
362                         }
363
364             return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
365
366                 }
367                 String innerType = null;
368
369                 Either<String, JanusGraphOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
370                 if (checkInnerType.isRight()) {
371                         return StorageOperationStatus.INVALID_TYPE;
372                 }
373                 innerType = checkInnerType.left().value();
374
375                 log.trace("After validating property type {}", propertyType);
376
377                 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
378                 if (!isValidProperty) {
379                         log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
380                         return StorageOperationStatus.INVALID_VALUE;
381                 }
382
383                 PropertyValueConverter converter = type.getConverter();
384
385                 if (isEmptyValue(value)) {
386                         log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
387                         propertyDefinition.setDefaultValue(EMPTY_VALUE);
388                 } else if (!isEmptyValue(value)) {
389                         String convertedValue = converter.convert(value, innerType, dataTypes);
390                         propertyDefinition.setDefaultValue(convertedValue);
391                 }
392                 return StorageOperationStatus.OK;
393         }
394
395         public Either<PropertyData, JanusGraphOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
396
397                 ResourceMetadataData resourceData = new ResourceMetadataData();
398                 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
399
400                 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
401
402                 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
403                 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
404
405                 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
406                 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao
407                                 .createNode(propertyData, PropertyData.class);
408                 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
409                 if (createNodeResult.isRight()) {
410                         JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
411                         log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
412                         return Either.right(operationStatus);
413                 }
414
415                 Map<String, Object> props = new HashMap<>();
416                 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
417                 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
418                                 .createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
419                 if (createRelResult.isRight()) {
420                         JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
421                         log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
422                         return Either.right(operationStatus);
423                 }
424
425                 return Either.left(createNodeResult.left().value());
426
427         }
428
429         public JanusGraphOperationStatus addPropertyToGraphByVertex(JanusGraphVertex metadataVertex, String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
430
431                 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
432
433                 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
434                 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
435
436                 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
437                 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData);
438                 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
439                 if (createNodeResult.isRight()) {
440                         JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
441                         log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
442                         return operationStatus;
443                 }
444
445                 Map<String, Object> props = new HashMap<>();
446                 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
447                 JanusGraphVertex propertyVertex = createNodeResult.left().value();
448                 JanusGraphOperationStatus
449                                 createRelResult = janusGraphGenericDao
450                                 .createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
451                 if (!createRelResult.equals(JanusGraphOperationStatus.OK)) {
452                         log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
453                         return createRelResult;
454                 }
455
456                 return createRelResult;
457
458         }
459
460         public JanusGraphGenericDao getJanusGraphGenericDao() {
461                 return janusGraphGenericDao;
462         }
463
464         public Either<PropertyData, JanusGraphOperationStatus> deletePropertyFromGraph(String propertyId) {
465                 log.debug("Before deleting property from graph {}", propertyId);
466                 return janusGraphGenericDao
467                                 .deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
468         }
469
470         public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
471
472                 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
473                 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
474                         return Either.right(validateAndUpdateProperty);
475                 }
476
477                 Either<PropertyData, JanusGraphOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
478                 if (either.isRight()) {
479                         StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
480                         return Either.right(storageStatus);
481                 }
482                 return Either.left(either.left().value());
483         }
484
485         public Either<PropertyData, JanusGraphOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
486                 if (log.isDebugEnabled())
487                         log.debug("Before updating property on graph {}", propertyId);
488
489                 // get the original property data
490                 Either<PropertyData, JanusGraphOperationStatus> statusProperty = janusGraphGenericDao
491                                 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
492                 if (statusProperty.isRight()) {
493                         log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
494                         return Either.right(statusProperty.right().value());
495                 }
496                 PropertyData orgPropertyData = statusProperty.left().value();
497                 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
498
499                 // create new property data to update
500                 PropertyData newPropertyData = new PropertyData();
501                 newPropertyData.setPropertyDataDefinition(propertyDefinition);
502                 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
503
504                 // update the original property data with new values
505                 if (orgPropertyDataDefinition.getDefaultValue() == null) {
506                         orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
507                 } else {
508                         if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
509                                 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
510                         }
511                 }
512                 if (orgPropertyDataDefinition.getDescription() == null) {
513                         orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
514                 } else {
515                         if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
516                                 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
517                         }
518                 }
519                 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
520                         orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
521                 }
522                 if (newPropertyData.getConstraints() != null) {
523                         orgPropertyData.setConstraints(newPropertyData.getConstraints());
524                 }
525                 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
526
527                 return janusGraphGenericDao.updateNode(orgPropertyData, PropertyData.class);
528         }
529
530         /**
531          * FOR TEST ONLY
532          * 
533          * @param janusGraphGenericDao
534          */
535         public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
536                 this.janusGraphGenericDao = janusGraphGenericDao;
537         }
538
539         public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition, NodeTypeEnum nodeType, String uniqueId) {
540
541                 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
542
543                 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
544                 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
545
546                 if (log.isDebugEnabled())
547                         log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
548                 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao
549                                 .createNode(propertyData, PropertyData.class);
550                 if (log.isDebugEnabled())
551                         log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
552                 if (createNodeResult.isRight()) {
553                         JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
554                         log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
555                         return Either.right(operationStatus);
556                 }
557
558                 Map<String, Object> props = new HashMap<>();
559                 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
560
561                 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
562                 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
563                 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
564                                 .createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
565                 if (createRelResult.isRight()) {
566                         JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
567                         log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
568                         return Either.right(operationStatus);
569                 }
570
571                 return Either.left(createNodeResult.left().value());
572
573         }
574
575         public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
576
577                 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
578
579                 Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
580                                 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
581                                 PropertyData.class);
582
583                 if (childrenNodes.isRight()) {
584                         JanusGraphOperationStatus operationStatus = childrenNodes.right().value();
585                         return Either.right(operationStatus);
586                 }
587
588                 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
589                 if (values != null) {
590
591                         for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
592                                 GraphEdge edge = immutablePair.getValue();
593                                 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
594                                 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
595                                 PropertyData propertyData = immutablePair.getKey();
596                                 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
597                                 resourceProps.put(propertyName, propertyDefinition);
598                         }
599
600                 }
601
602                 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
603                 return Either.left(resourceProps);
604         }
605
606     public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
607             return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId)
608                 .right()
609                 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
610     }
611     
612     public Either<Map<String, PropertyData>, JanusGraphOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId, Map<String, PropertyDefinition> newProperties) {
613         Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
614         
615         Map<String, PropertyDefinition> reallyNewProperties;
616         Map<String, PropertyData> unchangedPropsData;
617         
618         if (oldPropertiesRes.isRight()) {
619             JanusGraphOperationStatus err  = oldPropertiesRes.right().value();
620             if (err == JanusGraphOperationStatus.NOT_FOUND) {
621                 reallyNewProperties = newProperties;
622                 unchangedPropsData = Collections.emptyMap();
623             }
624             else {
625                 return Either.right(err);
626             }
627         }
628         else {
629             Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
630             reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
631             
632             for(Entry<String, PropertyDefinition> oldEntry: oldProperties.entrySet()) {
633                 String key = oldEntry.getKey();
634                 PropertyDefinition newPropDef = newProperties != null? newProperties.get(key): null;
635                 PropertyDefinition oldPropDef = oldEntry.getValue();
636
637                 JanusGraphOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
638                 if (status != JanusGraphOperationStatus.OK) {
639                     return Either.right(status);
640                 }
641             }
642             unchangedPropsData = oldProperties.entrySet().stream()
643                                         .collect(Collectors.toMap(Entry::getKey, e-> new PropertyData(e.getValue(), null)));
644         }
645             
646             
647         // add other properties
648         return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
649     }
650
651     /**
652      * @param newProperties
653      * @param oldProperties
654      * @return
655      */
656     private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties, Map<String, PropertyDefinition> oldProperties) {
657         return newProperties != null? newProperties.entrySet().stream()
658                                         .filter(entry -> !oldProperties.containsKey(entry.getKey()))
659                                         .collect(Collectors.toMap(Entry::getKey, Entry::getValue) ): null;
660     }
661
662     /**
663      * @param newPropDef
664      * @param oldPropDef
665      */
666     private JanusGraphOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
667         if (!isUpdateAllowed(newPropDef, oldPropDef)) {
668             return JanusGraphOperationStatus.MATCH_NOT_FOUND;
669         }
670         
671         if (isUpdateRequired(newPropDef, oldPropDef)) {
672             modifyOldPropByNewOne(newPropDef, oldPropDef);
673             
674             List<PropertyConstraint> constraints = oldPropDef.getConstraints();
675             PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
676             Either<PropertyData, JanusGraphOperationStatus> updateResult = janusGraphGenericDao
677                                                                 .updateNode(node, PropertyData.class);
678             
679             if (updateResult.isRight()) {
680                 return updateResult.right().value();
681             }
682         }
683         
684         return JanusGraphOperationStatus.OK;
685     }
686
687     /**
688      * @param newPropDef
689      * @param oldPropDef
690      */
691     private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
692         if (newPropDef == null) {
693             log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
694             return false;
695         }
696         
697         // If the property type is missing it's something that we could want to fix 
698         if ( oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
699             log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
700             return false;
701         }
702         
703         return true;
704     }
705
706     /**
707      * Update only fields which modification is permitted.
708      * @param newPropDef
709      * @param oldPropDef
710      */
711     private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
712         oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
713         oldPropDef.setDescription(newPropDef.getDescription());
714         oldPropDef.setRequired(newPropDef.isRequired());
715
716         // Type is updated to fix possible null type issue in janusGraph DB
717         oldPropDef.setType(newPropDef.getType());
718     }
719
720
721     private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
722         return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) ||
723             !StringUtils.equals(oldPropDef.getDescription(), newPropDef.getDescription()) ||
724             oldPropDef.isRequired() != newPropDef.isRequired();
725     }
726
727     /**
728      * Adds newProperties and returns in case of success (left part of Either) 
729      * map of all properties i. e. added ones and contained in unchangedPropsData
730      * @param nodeType
731      * @param uniqueId
732      * @param newProperties
733      * @param unchangedPropsData
734      * @return
735      */
736     private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId, Map<String, PropertyDefinition> newProperties, Map<String, PropertyData> unchangedPropsData) {
737         return addPropertiesToElementType(uniqueId, nodeType, newProperties)
738                 .left()
739                 .map(m -> { 
740                     m.putAll(unchangedPropsData);
741                     return m;
742                  });
743     }
744
745
746         public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
747
748                 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
749
750                 if (propertiesOfNodeRes.isRight()) {
751                         JanusGraphOperationStatus status = propertiesOfNodeRes.right().value();
752                         if (status == JanusGraphOperationStatus.NOT_FOUND) {
753                                 return Either.right(StorageOperationStatus.OK);
754                         }
755                         return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
756                 }
757
758                 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
759                 for (PropertyDefinition propertyDefinition : value.values()) {
760
761                         String propertyUid = propertyDefinition.getUniqueId();
762                         Either<PropertyData, JanusGraphOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
763                         if (deletePropertyRes.isRight()) {
764                                 log.error("Failed to delete property with id {}", propertyUid);
765                                 JanusGraphOperationStatus status = deletePropertyRes.right().value();
766                                 if (status == JanusGraphOperationStatus.NOT_FOUND) {
767                                         status = JanusGraphOperationStatus.INVALID_ID;
768                                 }
769                                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
770                         }
771
772                 }
773
774                 log.debug("The properties deleted from node {} are {}", uniqueId, value);
775                 return Either.left(value);
776         }
777
778 /**
779  * Checks existence of a property with the same name belonging to the same resource
780  * or existence of property with the same name and different type (including derived from hierarchy)
781  * @param properties
782  * @param resourceUid
783  * @param propertyName
784  * @param propertyType
785  * @return
786  */
787         public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
788                 boolean result = false;
789                 if (!CollectionUtils.isEmpty(properties)) {
790                         for (PropertyDefinition propertyDefinition : properties) {
791         
792                                 if ( propertyDefinition.getName().equals(propertyName) &&
793                                                 (propertyDefinition.getParentUniqueId().equals(resourceUid) || !propertyDefinition.getType().equals(propertyType)) ) {
794                                         result = true;
795                                         break;
796                                 }
797                         }
798                 }
799                 return result;
800         }
801
802         public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType, Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
803
804                 if (rules == null || rules.isEmpty()) {
805                         return new ImmutablePair<>(null, true);
806                 }
807
808                 for (PropertyRule rule : rules) {
809                         String value = rule.getValue();
810                         Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
811                         if (updateResult.isRight()) {
812                                 Boolean status = updateResult.right().value();
813                                 if (!status) {
814                                         return new ImmutablePair<>(value, status);
815                                 }
816                         } else {
817                                 String newValue = null;
818                                 Object object = updateResult.left().value();
819                                 if (object != null) {
820                                         newValue = object.toString();
821                                 }
822                                 rule.setValue(newValue);
823                         }
824                 }
825
826                 return new ImmutablePair<>(null, true);
827         }
828
829         public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
830
831                 List<PropertyRule> rules = resourceInstanceProperty.getRules();
832                 if (rules == null) {
833                         PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
834                         rules = new ArrayList<>();
835                         rules.add(propertyRule);
836                 } else {
837                         rules = sortRules(rules);
838                 }
839
840                 propertyValueData.setRules(rules);
841         }
842
843         private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
844                 List<String> path = resourceInstanceProperty.getPath();
845                 // FOR BC. Since old Property values on VFC/VF does not have rules on
846                 // graph.
847                 // Update could be done on one level only, thus we can use this
848                 // operation to avoid migration.
849                 if (path == null || path.isEmpty()) {
850                         path = new ArrayList<>();
851                         path.add(resourceInstanceId);
852                 }
853                 PropertyRule propertyRule = new PropertyRule();
854                 propertyRule.setRule(path);
855                 propertyRule.setValue(propertyValueData.getValue());
856                 return propertyRule;
857         }
858
859         private List<PropertyRule> sortRules(List<PropertyRule> rules) {
860
861                 // TODO: sort the rules by size and binary representation.
862                 // (x, y, .+) --> 110 6 priority 1
863                 // (x, .+, z) --> 101 5 priority 2
864
865                 return rules;
866         }
867
868         public ImmutablePair<JanusGraphOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
869
870                 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
871
872                 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllRes = this.getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
873                 if (getAllRes.isRight()) {
874                         JanusGraphOperationStatus status = getAllRes.right().value();
875                         log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
876                         return new ImmutablePair<>(status, null);
877                 }
878
879                 List<ComponentInstanceProperty> list = getAllRes.left().value();
880                 if (list != null) {
881                         for (ComponentInstanceProperty instanceProperty : list) {
882                                 String propertyUniqueId = instanceProperty.getUniqueId();
883                                 String valueUniqueUid = instanceProperty.getValueUniqueUid();
884                                 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
885                                 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
886                                         log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
887                                         return new ImmutablePair<>(JanusGraphOperationStatus.ALREADY_EXIST, valueUniqueUid);
888                                 }
889                         }
890                 }
891
892                 return new ImmutablePair<>(JanusGraphOperationStatus.NOT_FOUND, null);
893         }
894
895
896         public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
897
898                 List<PropertyRule> currentRules = propertyValueData.getRules();
899
900                 List<PropertyRule> rules = resourceInstanceProperty.getRules();
901                 // if rules are not supported.
902                 if (rules == null) {
903
904                         PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
905                         rules = new ArrayList<>();
906                         rules.add(propertyRule);
907
908                         if (currentRules != null) {
909                                 rules = mergeRules(currentRules, rules);
910                         }
911
912                 } else {
913                         // Full mode. all rules are sent in update operation.
914                         rules = sortRules(rules);
915                 }
916
917                 propertyValueData.setRules(rules);
918
919         }
920
921         private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
922
923                 List<PropertyRule> mergedRules = new ArrayList<>();
924
925                 if (newRules == null || newRules.isEmpty()) {
926                         return currentRules;
927                 }
928
929                 for (PropertyRule rule : currentRules) {
930                         PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
931                         mergedRules.add(propertyRule);
932                 }
933
934                 for (PropertyRule rule : newRules) {
935                         PropertyRule foundRule = findRuleInList(rule, mergedRules);
936                         if (foundRule != null) {
937                                 foundRule.setValue(rule.getValue());
938                         } else {
939                                 mergedRules.add(rule);
940                         }
941                 }
942
943                 return mergedRules;
944         }
945
946         private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
947
948                 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
949                         return null;
950                 }
951
952                 PropertyRule foundRule = null;
953                 for (PropertyRule propertyRule : rules) {
954                         if (rule.getRuleSize() != propertyRule.getRuleSize()) {
955                                 continue;
956                         }
957                         boolean equals = propertyRule.compareRule(rule);
958                         if (equals) {
959                                 foundRule = propertyRule;
960                                 break;
961                         }
962                 }
963
964                 return foundRule;
965         }
966
967         /**
968          * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
969          * 
970          * @param resourceInstanceUid
971          * @return
972          */
973         public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(String resourceInstanceUid) {
974
975                 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
976
977         }
978
979         public Either<PropertyValueData, JanusGraphOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
980
981                 Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
982                                 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
983
984                 if (findResInstanceRes.isRight()) {
985                         JanusGraphOperationStatus status = findResInstanceRes.right().value();
986                         if (status == JanusGraphOperationStatus.NOT_FOUND) {
987                                 status = JanusGraphOperationStatus.INVALID_ID;
988                         }
989                         return Either.right(status);
990                 }
991
992                 Either<PropertyValueData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
993                                 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
994
995                 if (findPropertyDefRes.isRight()) {
996                         JanusGraphOperationStatus status = findPropertyDefRes.right().value();
997                         if (status == JanusGraphOperationStatus.NOT_FOUND) {
998                                 status = JanusGraphOperationStatus.INVALID_ID;
999                         }
1000                         return Either.right(status);
1001                 }
1002
1003                 Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
1004                                 .getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
1005                 if (relation.isRight()) {
1006                         // TODO: add error in case of error
1007                         JanusGraphOperationStatus status = relation.right().value();
1008                         if (status == JanusGraphOperationStatus.NOT_FOUND) {
1009                                 status = JanusGraphOperationStatus.INVALID_ID;
1010                         }
1011                         return Either.right(status);
1012                 }
1013
1014                 Either<PropertyValueData, JanusGraphOperationStatus> deleteNode = janusGraphGenericDao
1015                                 .deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
1016                 if (deleteNode.isRight()) {
1017                         return Either.right(deleteNode.right().value());
1018                 }
1019                 PropertyValueData value = deleteNode.left().value();
1020                 return Either.left(value);
1021
1022         }
1023
1024         public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid, String resourceInstanceId, boolean inTransaction) {
1025
1026                 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
1027
1028                 try {
1029
1030                         Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = this.removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
1031
1032                         if (eitherStatus.isRight()) {
1033                                 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId, eitherStatus.right().value().name());
1034                                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1035                                 return result;
1036                         } else {
1037                                 PropertyValueData propertyValueData = eitherStatus.left().value();
1038
1039                                 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
1040                                 propertyValueResult.setUniqueId(resourceInstanceId);
1041                                 propertyValueResult.setValue(propertyValueData.getValue());
1042
1043                                 log.debug("The returned ResourceInstanceProperty is  {}", propertyValueResult);
1044                                 result = Either.left(propertyValueResult);
1045                                 return result;
1046                         }
1047                 }
1048
1049                 finally {
1050                         if (!inTransaction) {
1051                                 if (result == null || result.isRight()) {
1052                                         log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1053                                         janusGraphGenericDao.rollback();
1054                                 } else {
1055                                         log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1056                                         janusGraphGenericDao.commit();
1057                                 }
1058                         }
1059                 }
1060
1061         }
1062
1063         public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty) {
1064
1065                 String value = propertyValueData.getValue();
1066                 String uid = propertyValueData.getUniqueId();
1067                 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
1068                 instanceProperty.setPath(resourceInstanceProperty.getPath());
1069
1070                 return instanceProperty;
1071         }
1072
1073
1074         public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
1075
1076                 @Override
1077                 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
1078                         ObjectCodec oc = json.getCodec();
1079                         JsonNode node = oc.readTree(json);
1080                         return null;
1081                 }
1082         }
1083
1084         @Override
1085         public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
1086                 if (propertyDefinition == null) {
1087                         return false;
1088                 }
1089                 boolean isValid = false;
1090                 String innerType = null;
1091                 String propertyType = propertyDefinition.getType();
1092                 ToscaPropertyType type = getType(propertyType);
1093                 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
1094                         SchemaDefinition def = propertyDefinition.getSchema();
1095                         if (def == null) {
1096                                 return false;
1097                         }
1098                         PropertyDataDefinition propDef = def.getProperty();
1099                         if (propDef == null) {
1100                                 return false;
1101                         }
1102                         innerType = propDef.getType();
1103                 }
1104                 String value = propertyDefinition.getDefaultValue();
1105                 if (type != null) {
1106                         isValid = isValidValue(type, value, innerType, dataTypes);
1107                 } else {
1108                         log.trace("The given type {} is not a pre defined one.", propertyType);
1109
1110                         DataTypeDefinition foundDt = dataTypes.get(propertyType);
1111                         if (foundDt != null) {
1112                                 isValid = isValidComplexValue(foundDt, value, dataTypes);
1113                         } else {
1114                                 isValid = false;
1115                         }
1116                 }
1117                 return isValid;
1118         }
1119
1120         public boolean isPropertyTypeValid(IComplexDefaultValue property) {
1121
1122                 if (property == null) {
1123                         return false;
1124                 }
1125
1126                 if (ToscaPropertyType.isValidType(property.getType()) == null) {
1127
1128                         Either<Boolean, JanusGraphOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType());
1129
1130                         if (definedInDataTypes.isRight()) {
1131                                 return false;
1132                         } else {
1133                                 Boolean isExist = definedInDataTypes.left().value();
1134                                 return isExist.booleanValue();
1135                         }
1136
1137                 }
1138                 return true;
1139         }
1140
1141         @Override
1142         public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
1143
1144                 if (property == null) {
1145                         return new ImmutablePair<>(null, false);
1146                 }
1147
1148                 SchemaDefinition schema;
1149                 PropertyDataDefinition innerProp;
1150                 String innerType = null;
1151                 if ((schema = property.getSchema()) != null) {
1152                         if ((innerProp = schema.getProperty()) != null) {
1153                                 innerType = innerProp.getType();
1154                         }
1155                 }
1156
1157                 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
1158
1159                 if (innerToscaType == null) {
1160                         DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
1161                         if (dataTypeDefinition == null) {
1162                                 log.debug("The inner type {} is not a data type.", innerType);
1163                                 return new ImmutablePair<>(innerType, false);
1164                         } else {
1165                                 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
1166                         }
1167                 }
1168
1169                 return new ImmutablePair<>(innerType, true);
1170         }
1171
1172         private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
1173                 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
1174
1175                 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
1176
1177                 return validateAndUpdate.right.booleanValue();
1178
1179         }
1180
1181         public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
1182
1183                 Either<JanusGraphVertex, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
1184                                 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
1185
1186                 if (findResInstanceRes.isRight()) {
1187                         JanusGraphOperationStatus status = findResInstanceRes.right().value();
1188                         if (status == JanusGraphOperationStatus.NOT_FOUND) {
1189                                 status = JanusGraphOperationStatus.INVALID_ID;
1190                         }
1191                         return Either.right(status);
1192                 }
1193
1194                 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> propertyImplNodes = janusGraphGenericDao
1195                                 .getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
1196
1197                 if (propertyImplNodes.isRight()) {
1198                         JanusGraphOperationStatus status = propertyImplNodes.right().value();
1199                         return Either.right(status);
1200                 }
1201
1202                 List<ImmutablePair<JanusGraphVertex, Edge>> list = propertyImplNodes.left().value();
1203                 if (list == null || list.isEmpty()) {
1204                         return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1205                 }
1206
1207                 List<ComponentInstanceProperty> result = new ArrayList<>();
1208                 for (ImmutablePair<JanusGraphVertex, Edge> propertyValue : list) {
1209                         JanusGraphVertex propertyValueDataVertex = propertyValue.getLeft();
1210                         String propertyValueUid = (String) janusGraphGenericDao
1211                                         .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
1212                         String value = (String) janusGraphGenericDao
1213                                         .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
1214
1215                         ImmutablePair<JanusGraphVertex, Edge> propertyDefPair = janusGraphGenericDao
1216                                         .getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
1217                         if (propertyDefPair == null) {
1218                                 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
1219                         }
1220
1221                         Map<String, Object> properties = janusGraphGenericDao.getProperties(propertyValueDataVertex);
1222                         PropertyValueData propertyValueData = GraphElementFactory.createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
1223                         String propertyUniqueId = (String) janusGraphGenericDao
1224                                         .getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
1225
1226                         ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
1227                         // set property original unique id
1228                         resourceInstanceProperty.setUniqueId(propertyUniqueId);
1229                         // set resource id
1230                         // TODO: esofer add resource id
1231                         resourceInstanceProperty.setParentUniqueId(null);
1232                         // set value
1233                         resourceInstanceProperty.setValue(value);
1234                         // set property value unique id
1235                         resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
1236                         // set rules
1237                         resourceInstanceProperty.setRules(propertyValueData.getRules());
1238
1239                         result.add(resourceInstanceProperty);
1240                 }
1241
1242                 return Either.left(result);
1243         }
1244
1245         /**
1246          * Find the default value from the list of component instances. Start the search from the second component instance
1247          * 
1248          * @param pathOfComponentInstances
1249          * @param propertyUniqueId
1250          * @param defaultValue
1251          * @return
1252          */
1253         public Either<String, JanusGraphOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances, String propertyUniqueId, String defaultValue) {
1254
1255                 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
1256
1257                 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
1258                         return Either.left(defaultValue);
1259                 }
1260
1261                 String result = defaultValue;
1262
1263                 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
1264                         String compInstanceId = pathOfComponentInstances.get(i);
1265
1266                         Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> propertyValuesResult = this.getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
1267
1268                         log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
1269
1270                         if (propertyValuesResult.isRight()) {
1271                                 JanusGraphOperationStatus status = propertyValuesResult.right().value();
1272                                 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1273                                         return Either.right(status);
1274                                 } else {
1275                                         continue;
1276                                 }
1277                         }
1278
1279                         ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
1280                         log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
1281
1282                         if (foundCompInstanceProperty == null) {
1283                                 continue;
1284                         }
1285
1286                         List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i), foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
1287
1288                         log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
1289                         PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
1290                         log.trace("Match rule is {}", matchedRule);
1291
1292                         if (matchedRule != null) {
1293                                 result = matchedRule.getValue();
1294                                 break;
1295                         }
1296
1297                 }
1298
1299                 return Either.left(result);
1300
1301         }
1302
1303         private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
1304
1305                 ComponentInstanceProperty result = null;
1306
1307                 if (list == null) {
1308                         return null;
1309                 }
1310
1311                 for (ComponentInstanceProperty instProperty : list) {
1312                         if (instProperty.getUniqueId().equals(propertyUniqueId)) {
1313                                 result = instProperty;
1314                                 break;
1315                         }
1316                 }
1317
1318                 return result;
1319         }
1320
1321         private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
1322
1323                 if (rules != null) {
1324                         return rules;
1325                 }
1326
1327                 rules = buildDefaultRule(compInstanceId, ruleSize, value);
1328
1329                 return rules;
1330
1331         }
1332
1333         private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
1334                 List<PropertyRule> rules = componentInstanceProperty.getRules();
1335                 if (rules == null) {
1336                         rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
1337                 }
1338                 return rules;
1339         }
1340
1341         private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
1342
1343                 List<PropertyRule> rules = new ArrayList<>();
1344                 List<String> rule = new ArrayList<>();
1345                 rule.add(componentInstanceId);
1346                 for (int i = 0; i < size - 1; i++) {
1347                         rule.add(PropertyRule.RULE_ANY_MATCH);
1348                 }
1349                 PropertyRule propertyRule = new PropertyRule(rule, value);
1350                 rules.add(propertyRule);
1351
1352                 return rules;
1353
1354         }
1355
1356         private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1357
1358                 PropertyRule propertyRule = null;
1359
1360                 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1361
1362                 String firstCompInstance = pathOfInstances.get(level);
1363
1364                 if (rules != null) {
1365
1366                         for (PropertyRule rule : rules) {
1367
1368                                 int ruleSize = rule.getRule().size();
1369                                 // check the length of the rule equals to the length of the
1370                                 // instances path.
1371                                 if (ruleSize != pathOfInstances.size() - level) {
1372                                         continue;
1373                                 }
1374                                 // check that the rule starts with correct component instance id
1375                                 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1376                                         continue;
1377                                 }
1378
1379                                 String secondToken = rule.getToken(2);
1380                                 if (secondToken != null && (secondToken.equals(PropertyRule.FORCE_ALL) || secondToken.equals(PropertyRule.ALL))) {
1381                                         propertyRule = rule;
1382                                         break;
1383                                 }
1384
1385                                 String patternStr = buildStringForMatch(rule.getRule(), 0);
1386
1387                                 Pattern pattern = Pattern.compile(patternStr);
1388
1389                                 Matcher matcher = pattern.matcher(stringForMatch);
1390
1391                                 if (matcher.matches()) {
1392                                         if (log.isTraceEnabled()) {
1393                                                 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1394                                         }
1395                                         propertyRule = rule;
1396                                         break;
1397                                 }
1398                         }
1399
1400                 }
1401
1402                 return propertyRule;
1403         }
1404
1405         private boolean checkFirstItem(String left, String right) {
1406                 if (left != null && left.equals(right)) {
1407                         return true;
1408                 }
1409                 return false;
1410         }
1411
1412         private String buildStringForMatch(List<String> pathOfInstances, int level) {
1413                 StringBuilder builder = new StringBuilder();
1414
1415                 for (int i = level; i < pathOfInstances.size(); i++) {
1416                         builder.append(pathOfInstances.get(i));
1417                         if (i < pathOfInstances.size() - 1) {
1418                                 builder.append("#");
1419                         }
1420                 }
1421                 return builder.toString();
1422         }
1423
1424         public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty, Map<String, ComponentInstanceProperty> instanceIdToValue) {
1425
1426                 List<String> pathOfInstances = instanceProperty.getPath();
1427                 int level = 0;
1428                 int size = pathOfInstances.size();
1429                 int numberOfMatches = 0;
1430                 for (String instanceId : pathOfInstances) {
1431                         ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1432
1433                         if (componentInstanceProperty != null) {
1434
1435                                 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1436                                 // If it is the first level instance, then update valueUniuqeId
1437                                 // parameter in order to know on update that
1438                                 // we should update and not create new node on graph.
1439                                 if (level == 0) {
1440                                         instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1441                                         instanceProperty.setRules(rules);
1442                                 }
1443
1444                                 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1445                                 if (rule != null) {
1446                                         numberOfMatches++;
1447                                         String value = rule.getValue();
1448                                         if (numberOfMatches == 1) {
1449                                                 instanceProperty.setValue(value);
1450                                                 if (log.isDebugEnabled()) {
1451                                                         log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(), pathOfInstances, value);
1452                                                 }
1453                                         } else if (numberOfMatches == 2) {
1454                                                 // In case of another property value match, then use the
1455                                                 // value to be the default value of the property.
1456                                                 instanceProperty.setDefaultValue(value);
1457                                                 if (log.isDebugEnabled()) {
1458                                                         log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(), pathOfInstances, value);
1459                                                 }
1460                                                 break;
1461                                         }
1462                                 }
1463                         }
1464                         level++;
1465                 }
1466
1467         }
1468
1469         /**
1470          * 
1471          * Add data type to graph.
1472          * 
1473          * 1. Add data type node
1474          * 
1475          * 2. Add edge between the former node to its parent(if exists)
1476          * 
1477          * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1478          * 
1479          * @param dataTypeDefinition
1480          * @return
1481          */
1482         private Either<DataTypeData, JanusGraphOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1483
1484                 log.debug("Got data type {}", dataTypeDefinition);
1485
1486                 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getName());
1487
1488                 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1489
1490                 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1491                 Either<DataTypeData, JanusGraphOperationStatus> createDataTypeResult = janusGraphGenericDao
1492                                 .createNode(dataTypeData, DataTypeData.class);
1493                 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1494
1495                 if (createDataTypeResult.isRight()) {
1496                         JanusGraphOperationStatus operationStatus = createDataTypeResult.right().value();
1497                         log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1498                         BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1499                         return Either.right(operationStatus);
1500                 }
1501
1502                 DataTypeData resultCTD = createDataTypeResult.left().value();
1503                 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1504                 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(), properties);
1505                 if (addPropertiesToDataType.isRight()) {
1506                         log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1507                         return Either.right(addPropertiesToDataType.right().value());
1508                 }
1509
1510                 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1511                 if (derivedFrom != null) {
1512                         log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1513                         UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1514
1515                         String deriveFromUid = UniqueIdBuilder.buildDataTypeUid(derivedFrom);
1516                         UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1517                         Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
1518                                         .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1519                         log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1520                         if (createRelation.isRight()) {
1521                                 return Either.right(createRelation.right().value());
1522                         }
1523                 }
1524
1525                 return Either.left(createDataTypeResult.left().value());
1526
1527         }
1528
1529         private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1530
1531                 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1532
1533                 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1534                 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1535                 if (creationDate == null) {
1536                         creationDate = System.currentTimeMillis();
1537                 }
1538                 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1539                 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1540
1541                 return dataTypeData;
1542         }
1543
1544         /**
1545          * add properties to capability type.
1546          * 
1547          * Per property, add a property node and associate it to the capability type
1548          * 
1549          * @param uniqueId
1550          * @param properties
1551          * @return
1552          */
1553         private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType(String uniqueId, List<PropertyDefinition> properties) {
1554
1555                 Map<String, PropertyData> propertiesData = new HashMap<>();
1556
1557                 if (properties != null && !properties.isEmpty()) {
1558                         for (PropertyDefinition propertyDefinition : properties) {
1559                                 String propertyName = propertyDefinition.getName();
1560
1561                                 String propertyType = propertyDefinition.getType();
1562                                 Either<Boolean, JanusGraphOperationStatus> validPropertyType = isValidPropertyType(propertyType);
1563                                 if (validPropertyType.isRight()) {
1564                                         log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1565                                         return Either.right(validPropertyType.right().value());
1566                                 }
1567                                 Boolean isValid = validPropertyType.left().value();
1568                                 if (isValid == null || !isValid.booleanValue()) {
1569                                         log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1570                                         return Either.right(JanusGraphOperationStatus.INVALID_TYPE);
1571                                 }
1572
1573                                 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this.addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1574                                 if (addPropertyToNodeType.isRight()) {
1575                                         JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1576                                         log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1577                                         BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1578                                         return Either.right(operationStatus);
1579                                 }
1580                                 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1581                         }
1582
1583                         DataTypeData dataTypeData = new DataTypeData();
1584                         dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1585                         long modificationTime = System.currentTimeMillis();
1586                         dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1587
1588                         Either<DataTypeData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao
1589                                         .updateNode(dataTypeData, DataTypeData.class);
1590                         if (updateNode.isRight()) {
1591                                 JanusGraphOperationStatus operationStatus = updateNode.right().value();
1592                                 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1593                                 BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1594                                 return Either.right(operationStatus);
1595                         } else {
1596                                 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1597                         }
1598
1599                 }
1600
1601                 return Either.left(propertiesData);
1602
1603         }
1604
1605         /**
1606          * Build Data type object from graph by unique id
1607          * 
1608          * @param uniqueId
1609          * @return
1610          */
1611         public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUid(String uniqueId) {
1612
1613                 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1614
1615                 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1616                                 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1617
1618                 if (dataTypesRes.isRight()) {
1619                         JanusGraphOperationStatus status = dataTypesRes.right().value();
1620                         log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1621                         return Either.right(status);
1622                 }
1623
1624                 DataTypeData ctData = dataTypesRes.left().value();
1625                 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1626
1627                 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1628                 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1629                         log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1630                         return Either.right(propertiesStatus);
1631                 }
1632
1633                 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1634                                 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1635                                 DataTypeData.class);
1636                 log.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
1637                 if (parentNode.isRight()) {
1638                         JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1639                         if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1640                                 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId,
1641                                                 janusGraphOperationStatus);
1642                                 result = Either.right(janusGraphOperationStatus);
1643                                 return result;
1644                         }
1645                 } else {
1646                         // derived from node was found
1647                         ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1648                         DataTypeData parentCT = immutablePair.getKey();
1649
1650                         String parentUniqueId = parentCT.getUniqueId();
1651                         Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1652
1653                         if (dataTypeByUid.isRight()) {
1654                                 return Either.right(dataTypeByUid.right().value());
1655                         }
1656
1657                         DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1658
1659                         dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1660
1661                 }
1662                 result = Either.left(dataTypeDefinition);
1663
1664                 return result;
1665         }
1666
1667         private JanusGraphOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1668
1669                 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1670                 if (findPropertiesOfNode.isRight()) {
1671                         JanusGraphOperationStatus janusGraphOperationStatus = findPropertiesOfNode.right().value();
1672                         log.debug("After looking for properties of vertex {}. status is {}", uniqueId,
1673                                         janusGraphOperationStatus);
1674                         if (JanusGraphOperationStatus.NOT_FOUND.equals(janusGraphOperationStatus)) {
1675                                 return JanusGraphOperationStatus.OK;
1676                         } else {
1677                                 return janusGraphOperationStatus;
1678                         }
1679                 } else {
1680                         Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1681                         if (properties != null && !properties.isEmpty()) {
1682                                 List<PropertyDefinition> listOfProps = new ArrayList<>();
1683
1684                                 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1685                                         String propName = entry.getKey();
1686                                         PropertyDefinition propertyDefinition = entry.getValue();
1687                                         PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1688                                         newPropertyDefinition.setName(propName);
1689                                         listOfProps.add(newPropertyDefinition);
1690                                 }
1691                                 dataTypeDefinition.setProperties(listOfProps);
1692                         }
1693                         return JanusGraphOperationStatus.OK;
1694                 }
1695         }
1696
1697         private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1698
1699                 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1700
1701                 try {
1702
1703                         Either<DataTypeData, JanusGraphOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1704
1705                         if (eitherStatus.isRight()) {
1706                                 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1707                                 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1708                                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1709                                 return result;
1710                         } else {
1711                                 DataTypeData capabilityTypeData = eitherStatus.left().value();
1712
1713                                 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1714                                 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1715                                 result = Either.left(dataTypeDefResult);
1716                                 return result;
1717                         }
1718                 } finally {
1719                         if (!inTransaction) {
1720                                 if (result == null || result.isRight()) {
1721                                         log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1722                                         janusGraphGenericDao.rollback();
1723                                 } else {
1724                                         log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1725                                         janusGraphGenericDao.commit();
1726                                 }
1727                         }
1728                 }
1729
1730         }
1731
1732         @Override
1733         public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1734                 return addDataType(dataTypeDefinition, true);
1735         }
1736
1737         @Override
1738         public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(String name, boolean inTransaction) {
1739
1740                 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1741                 try {
1742
1743                         String dtUid = UniqueIdBuilder.buildDataTypeUid(name);
1744                         Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUid(dtUid);
1745
1746                         if (ctResult.isRight()) {
1747                                 JanusGraphOperationStatus status = ctResult.right().value();
1748                                 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1749                                         log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1750                                 }
1751                                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1752                                 return result;
1753                         }
1754
1755                         result = Either.left(ctResult.left().value());
1756
1757                         return result;
1758                 } finally {
1759                         if (!inTransaction) {
1760                                 if (result == null || result.isRight()) {
1761                                         log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1762                                         janusGraphGenericDao.rollback();
1763                                 } else {
1764                                         log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1765                                         janusGraphGenericDao.commit();
1766                                 }
1767                         }
1768                 }
1769
1770         }
1771
1772         @Override
1773         public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(String name) {
1774                 return getDataTypeByName(name, true);
1775         }
1776
1777         @Override
1778         public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByNameWithoutDerived(String name) {
1779                 return getDataTypeByNameWithoutDerived(name, true);
1780         }
1781
1782         private Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByNameWithoutDerived(String name, boolean inTransaction) {
1783
1784                 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1785                 try {
1786
1787                         String uid = UniqueIdBuilder.buildDataTypeUid(name);
1788                         Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1789
1790                         if (ctResult.isRight()) {
1791                                 JanusGraphOperationStatus status = ctResult.right().value();
1792                                 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1793                                         log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1794                                 }
1795                                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1796                                 return result;
1797                         }
1798
1799                         result = Either.left(ctResult.left().value());
1800
1801                         return result;
1802                 } finally {
1803                         if (!inTransaction) {
1804                                 if (result == null || result.isRight()) {
1805                                         log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1806                                         janusGraphGenericDao.rollback();
1807                                 } else {
1808                                         log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1809                                         janusGraphGenericDao.commit();
1810                                 }
1811                         }
1812                 }
1813
1814         }
1815
1816         public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1817
1818                 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1819                                 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1820
1821                 if (dataTypesRes.isRight()) {
1822                         JanusGraphOperationStatus status = dataTypesRes.right().value();
1823                         log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1824                         return Either.right(status);
1825                 }
1826
1827                 DataTypeData ctData = dataTypesRes.left().value();
1828                 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1829
1830                 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1831                 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1832                         log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1833                         return Either.right(propertiesStatus);
1834                 }
1835
1836                 return Either.left(dataTypeDefinition);
1837         }
1838
1839         /**
1840          * 
1841          * convert between graph Node object to Java object
1842          * 
1843          * @param dataTypeData
1844          * @return
1845          */
1846         protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1847                 log.debug("The object returned after create data type is {}", dataTypeData);
1848
1849         return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1850         }
1851
1852         private Either<Boolean, JanusGraphOperationStatus> isValidPropertyType(String propertyType) {
1853
1854                 if (propertyType == null || propertyType.isEmpty()) {
1855                         return Either.left(false);
1856                 }
1857
1858                 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1859                 if (toscaPropertyType == null) {
1860             return isDefinedInDataTypes(propertyType);
1861                 } else {
1862                         return Either.left(true);
1863                 }
1864         }
1865
1866         public Either<Boolean, JanusGraphOperationStatus> isDefinedInDataTypes(String propertyType) {
1867
1868                 String dataTypeUid = UniqueIdBuilder.buildDataTypeUid(propertyType);
1869                 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(dataTypeUid);
1870                 if (dataTypeByUid.isRight()) {
1871                         JanusGraphOperationStatus status = dataTypeByUid.right().value();
1872                         if (status == JanusGraphOperationStatus.NOT_FOUND) {
1873                                 return Either.left(false);
1874                         }
1875                         return Either.right(status);
1876                 }
1877
1878                 return Either.left(true);
1879
1880         }
1881
1882         public Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> getAllDataTypes() {
1883
1884                 Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
1885                 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> result = Either.left(dataTypes);
1886
1887                 Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypes = janusGraphGenericDao
1888                                 .getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
1889                 if (getAllDataTypes.isRight()) {
1890                         JanusGraphOperationStatus status = getAllDataTypes.right().value();
1891                         if (status != JanusGraphOperationStatus.NOT_FOUND) {
1892                                 return Either.right(status);
1893                         } else {
1894                                 return result;
1895                         }
1896                 }
1897
1898                 List<DataTypeData> list = getAllDataTypes.left().value();
1899                 if (list != null) {
1900
1901                         log.trace("Number of data types to load is {}" , list.size());
1902
1903                         List<String> collect = list.stream().map(p -> p.getDataTypeDataDefinition().getName()).collect(Collectors.toList());
1904                         log.trace("The data types to load are {}" , collect);
1905
1906                         for (DataTypeData dataTypeData : list) {
1907
1908                                 log.trace("Going to fetch data type {}. uid is {}", dataTypeData.getDataTypeDataDefinition().getName(), dataTypeData.getUniqueId());
1909                                 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getAndAddDataTypeByUid(dataTypeData.getUniqueId(), dataTypes);
1910                                 if (dataTypeByUid.isRight()) {
1911                                         JanusGraphOperationStatus status = dataTypeByUid.right().value();
1912                                         if (status == JanusGraphOperationStatus.NOT_FOUND) {
1913                                                 status = JanusGraphOperationStatus.INVALID_ID;
1914                                         }
1915                                         return Either.right(status);
1916                                 }
1917                         }
1918                 }
1919
1920                 if (log.isTraceEnabled()) {
1921                         if (result.isRight()) {
1922                                 log.trace("After fetching all data types {}" , result);
1923                         } else {
1924                                 Map<String, DataTypeDefinition> map = result.left().value();
1925                                 if (map != null) {
1926                                         String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1927                                         log.trace("After fetching all data types {} " , types);
1928                                 }
1929                         }
1930                 }
1931
1932                 return result;
1933         }
1934
1935         /**
1936          * Build Data type object from graph by unique id
1937          * 
1938          * @param uniqueId
1939          * @return
1940          */
1941         private Either<DataTypeDefinition, JanusGraphOperationStatus> getAndAddDataTypeByUid(String uniqueId, Map<String, DataTypeDefinition> allDataTypes) {
1942
1943                 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1944
1945                 if (allDataTypes.containsKey(uniqueId)) {
1946                         return Either.left(allDataTypes.get(uniqueId));
1947                 }
1948
1949                 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1950                                 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1951
1952                 if (dataTypesRes.isRight()) {
1953                         JanusGraphOperationStatus status = dataTypesRes.right().value();
1954                         log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1955                         return Either.right(status);
1956                 }
1957
1958                 DataTypeData ctData = dataTypesRes.left().value();
1959                 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1960
1961                 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1962                 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1963                         log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1964                         return Either.right(propertiesStatus);
1965                 }
1966
1967                 allDataTypes.put(dataTypeDefinition.getName(), dataTypeDefinition);
1968
1969                 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1970                 if (allDataTypes.containsKey(derivedFrom)) {
1971                         DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1972
1973                         dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1974
1975                         return Either.left(dataTypeDefinition);
1976                 }
1977
1978                 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1979                                 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1980                                 DataTypeData.class);
1981                 log.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
1982                 if (parentNode.isRight()) {
1983                         JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1984                         if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1985                                 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId,
1986                                                 janusGraphOperationStatus);
1987                                 result = Either.right(janusGraphOperationStatus);
1988                                 return result;
1989                         }
1990                 } else {
1991                         // derived from node was found
1992                         ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1993                         DataTypeData parentCT = immutablePair.getKey();
1994
1995                         String parentUniqueId = parentCT.getUniqueId();
1996                         Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1997
1998                         if (dataTypeByUid.isRight()) {
1999                                 return Either.right(dataTypeByUid.right().value());
2000                         }
2001
2002                         DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
2003
2004                         dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
2005
2006                 }
2007                 result = Either.left(dataTypeDefinition);
2008
2009                 return result;
2010         }
2011
2012         private Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeUsingName(String name) {
2013                 String uid = UniqueIdBuilder.buildDataTypeUid(name);
2014                 return getDataTypeByUid(uid);
2015         }
2016
2017         public Either<String, JanusGraphOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
2018
2019                 String propertyType = propDataDef.getType();
2020
2021                 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
2022
2023                 return getInnerType(type, propDataDef::getSchema);
2024         }
2025
2026         public Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypeNodes() {
2027                 Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypes = janusGraphGenericDao
2028                                 .getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
2029                 if (getAllDataTypes.isRight()) {
2030                         JanusGraphOperationStatus status = getAllDataTypes.right().value();
2031                         if (status == JanusGraphOperationStatus.NOT_FOUND) {
2032                                 status = JanusGraphOperationStatus.OK;
2033                                 return Either.right(status);
2034                         }
2035                 }
2036                 return getAllDataTypes;
2037         }
2038
2039         public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType, Map<String, DataTypeDefinition> dataTypes) {
2040                 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
2041                 ToscaPropertyType type = getType(propertyType);
2042
2043                 if (isValidate) {
2044
2045                         if (type == null) {
2046                                 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
2047                                 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter.validateAndUpdate(value, dataTypeDefinition, dataTypes);
2048                                 if (Boolean.FALSE.equals(validateResult.right)) {
2049                                         log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
2050                                         return Either.right(false);
2051                                 }
2052                                 JsonElement jsonElement = validateResult.left;
2053                                 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
2054                                 return Either.left(valueFromJsonElement);
2055                         }
2056                         log.trace("before validating property type {}", propertyType);
2057                         boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
2058                         if (!isValidProperty) {
2059                                 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
2060                                 return Either.right(false);
2061                         }
2062                 }
2063                 Object convertedValue = value;
2064                 if (!isEmptyValue(value) && isValidate) {
2065                         PropertyValueConverter converter = type.getConverter();
2066                         convertedValue = converter.convert(value, innerType, dataTypes);
2067                 }
2068                 return Either.left(convertedValue);
2069         }
2070
2071         public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType, Map<String, DataTypeDefinition> dataTypes) {
2072                 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
2073         }
2074
2075         public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType, Class<T> clazz) {
2076                 return this.findPropertiesOfNode(nodeType, uniqueId)
2077                                 .right()
2078                                 .bind(this::handleNotFoundProperties)
2079                                 .left()
2080                                 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
2081         }
2082
2083         private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(JanusGraphOperationStatus janusGraphOperationStatus) {
2084                 if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
2085                         return Either.left(new HashMap<>());
2086                 }
2087                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(
2088                                 janusGraphOperationStatus));
2089         }
2090
2091         private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId, NodeTypeEnum nodeType, Class<T> clazz, Collection<PropertyDefinition> nodeProps) {
2092                 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
2093                 String currentNodeUid = uniqueId;
2094                 Either<T, StorageOperationStatus> derivedFrom;
2095                 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
2096                         currentNodeUid = derivedFrom.left().value().getUniqueId();
2097                         JanusGraphOperationStatus
2098                                         janusGraphOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
2099                         if (janusGraphOperationStatus != JanusGraphOperationStatus.OK) {
2100                                 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
2101                                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(
2102                                                 janusGraphOperationStatus));
2103                         }
2104                 }
2105                 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
2106                 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
2107         }
2108
2109         private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
2110                 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
2111         }
2112
2113         /*
2114          * @Override public PropertyOperation getPropertyOperation() { return this; }
2115          */
2116     public JanusGraphOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
2117                 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
2118                 if (findPropertiesRes.isRight()) {
2119                         return findPropertiesRes.right().value();
2120                 }
2121                 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
2122                 if (properties != null) {
2123                 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
2124                         propertySetter.accept(propertiesAsList);
2125                 }
2126                 return JanusGraphOperationStatus.OK;
2127         }
2128
2129         Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType){
2130                 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
2131                 if (findPropertiesOfNode.isRight()) {
2132                         log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
2133                         if(findPropertiesOfNode.right().value() == JanusGraphOperationStatus.NOT_FOUND)
2134                                 return Either.left(Maps.newHashMap());
2135                         return findPropertiesOfNode;
2136                 }
2137                 return findPropertiesOfNode;
2138                 }
2139         
2140         /**
2141          * add properties to element type.
2142          * 
2143          * Per property, add a property node and associate it to the element type
2144          * 
2145          * @param uniqueId
2146          * @param propertiesMap
2147          *            
2148          * @return
2149          */
2150         protected Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType, Map<String, PropertyDefinition> propertiesMap) {
2151
2152                 Map<String, PropertyData> propertiesData = new HashMap<>();
2153
2154                 if (propertiesMap != null) {
2155
2156                         for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
2157                                 String propertyName = propertyDefinitionEntry.getKey();
2158
2159                                 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this.addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
2160
2161                                 if (addPropertyToNodeType.isRight()) {
2162                                         JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
2163                                         log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName, operationStatus);
2164                                         return Either.right(operationStatus);
2165                                 }
2166                                 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
2167
2168                         }
2169                 }
2170
2171                 return Either.left(propertiesData);
2172
2173         }
2174
2175         public Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType, List<PropertyDefinition> properties) {
2176
2177                 Map<String, PropertyDefinition> propMap;
2178                 if (properties == null) {
2179                         propMap = null;
2180                 } else {
2181                         propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
2182                 }
2183                 return addPropertiesToElementType(uniqueId, elementType, propMap);
2184         }
2185
2186         @Override
2187         public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition, DataTypeDefinition oldDataTypeDefinition) {
2188                 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
2189         }
2190
2191         private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition, DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
2192
2193                 Either<DataTypeDefinition, StorageOperationStatus> result = null;
2194
2195                 try {
2196
2197                         List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
2198
2199                         List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
2200
2201                         String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
2202
2203                         String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
2204
2205                         String dataTypeName = newDataTypeDefinition.getName();
2206
2207                         List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
2208                         if (isPropertyOmitted(newProperties, oldProperties, dataTypeName) || isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, propertiesToAdd) || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
2209
2210                                 log.debug("The new data type {} is invalid.", dataTypeName);
2211
2212                                 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
2213                                 return result;
2214                         }
2215
2216                         if (propertiesToAdd == null || propertiesToAdd.isEmpty()) {
2217                                 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
2218                                 result = Either.right(StorageOperationStatus.OK);
2219                                 return result;
2220                         }
2221             Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
2222
2223             if(MapUtils.isNotEmpty(newDescriptions)){
2224
2225                 JanusGraphOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(), newDescriptions);
2226                 if (updatePropertiesStatus != JanusGraphOperationStatus.OK) {
2227                     log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}", oldDataTypeDefinition, updatePropertiesStatus);
2228                     BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
2229                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatePropertiesStatus));
2230                     return result;
2231                 }
2232             }
2233
2234                         Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(oldDataTypeDefinition.getUniqueId(), propertiesToAdd);
2235
2236                         if (addPropertiesToDataType.isRight()) {
2237                                 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition, addPropertiesToDataType.right().value().name());
2238                                 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
2239                                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToDataType.right().value()));
2240                                 return result;
2241                         } else {
2242
2243                                 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
2244                                 if (dataTypeByUid.isRight()) {
2245                                         JanusGraphOperationStatus status = addPropertiesToDataType.right().value();
2246                                         log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
2247                                         BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
2248                                         result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
2249                                 } else {
2250                                         result = Either.left(dataTypeByUid.left().value());
2251                                 }
2252                         }
2253
2254                         return result;
2255
2256                 } finally {
2257                         if (!inTransaction) {
2258                                 if (result == null || result.isRight()) {
2259                                         log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
2260                                         janusGraphGenericDao.rollback();
2261                                 } else {
2262                                         log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
2263                                         janusGraphGenericDao.commit();
2264                                 }
2265                         }
2266                 }
2267
2268         }
2269
2270         private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, List<PropertyDefinition> outputPropertiesToAdd) {
2271
2272                 if (newProperties != null && oldProperties != null) {
2273
2274                         Map<String, PropertyDefinition> newPropsMapper = newProperties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
2275                         Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
2276
2277                         for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
2278
2279                                 String propName = newPropertyEntry.getKey();
2280                                 PropertyDefinition propDef = newPropertyEntry.getValue();
2281
2282                                 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
2283                                 if (oldPropertyDefinition == null) {
2284                                         log.debug("New property {} received in the data type {}", propName, dataTypeName);
2285                                         outputPropertiesToAdd.add(propDef);
2286                                         continue;
2287                                 }
2288
2289                                 String oldType = oldPropertyDefinition.getType();
2290                                 String oldEntryType = getEntryType(oldPropertyDefinition);
2291
2292                                 String newType = propDef.getType();
2293                                 String newEntryType = getEntryType(propDef);
2294
2295                                 if (!oldType.equals(newType)) {
2296                                         log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType, newType);
2297                                         return true;
2298                                 }
2299
2300                                 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
2301                                         log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName, oldEntryType, newEntryType);
2302                                         return true;
2303                                 }
2304
2305                         }
2306
2307                 }
2308
2309                 return false;
2310         }
2311
2312         private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
2313
2314                 if (oldEntryType == null && newEntryType == null) {
2315                         return true;
2316                 } else if (oldEntryType != null && newEntryType != null) {
2317                         return oldEntryType.equals(newEntryType);
2318                 } else {
2319                         return false;
2320                 }
2321         }
2322
2323         private String getEntryType(PropertyDefinition oldPropertyDefinition) {
2324                 String entryType = null;
2325                 SchemaDefinition schema = oldPropertyDefinition.getSchema();
2326                 if (schema != null) {
2327                         PropertyDataDefinition schemaProperty = schema.getProperty();
2328                         if (schemaProperty != null) {
2329                                 entryType = schemaProperty.getType();
2330                         }
2331                 }
2332                 return entryType;
2333         }
2334
2335         private boolean isPropertyOmitted(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, String dataTypeName) {
2336
2337                 boolean isValid = validateChangeInCaseOfEmptyProperties(newProperties, oldProperties, dataTypeName);
2338                 if (!isValid) {
2339                         log.debug("At least one property is missing in the new data type {}", dataTypeName);
2340                         return false;
2341                 }
2342
2343                 if (newProperties != null && oldProperties != null) {
2344
2345                         List<String> newProps = newProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
2346                         List<String> oldProps = oldProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
2347
2348                         if (!newProps.containsAll(oldProps)) {
2349                                 StringJoiner joiner = new StringJoiner(",", "[", "]");
2350                                 newProps.forEach(joiner::add);
2351                                 log.debug("Properties {} in data type {} are missing, but they already defined in the existing data type", joiner.toString(), dataTypeName);
2352                                 return true;
2353                         }
2354
2355                 }
2356                 return false;
2357         }
2358
2359         private boolean validateChangeInCaseOfEmptyProperties(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, String dataTypeName) {
2360
2361                 if (newProperties != null) {
2362                         if (newProperties.isEmpty()) {
2363                                 newProperties = null;
2364                         }
2365                 }
2366
2367                 if (oldProperties != null) {
2368                         if (oldProperties.isEmpty()) {
2369                                 oldProperties = null;
2370                         }
2371                 }
2372
2373                 if ((newProperties == null && oldProperties == null) || (newProperties != null && oldProperties != null)) {
2374                         return true;
2375                 }
2376
2377                 return false;
2378         }
2379
2380         private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
2381
2382                 if (newDerivedFromName != null) {
2383                         boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
2384                         if (!isEqual) {
2385                                 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName, oldDerivedFromName);
2386                         }
2387                         return !isEqual;
2388                 } else if (oldDerivedFromName == null) {
2389                         return false;
2390                 } else {// new=null, old != null
2391                         log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName, oldDerivedFromName);
2392                         return true;
2393                 }
2394
2395         }
2396
2397         /**
2398          * @param instanceId
2399          * @param nodeType
2400          * @return
2401          */
2402         public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
2403             Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
2404             if (graphResult.isRight()) {
2405                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
2406             }
2407             Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
2408                                         .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
2409             if (vertexService.isRight()) {
2410                 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
2411                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
2412             }
2413             Vertex vertex = vertexService.left().value();
2414             
2415             VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
2416             Integer counter = 0;
2417             if (vertexProperty.isPresent() && vertexProperty.value() != null) {
2418                 counter = (Integer) vertexProperty.value();
2419             }
2420             
2421             counter++;
2422             vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
2423             
2424             return Either.left(counter);
2425         }
2426
2427
2428         public Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesUniqueness(Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
2429         Either<List<PropertyDefinition>, JanusGraphOperationStatus> result = Either.left(properties);
2430
2431         for (PropertyDefinition property : properties) {
2432             JanusGraphOperationStatus
2433                                                                 status = validatePropertyUniqueness(inheritedProperties, property);
2434             if (status != JanusGraphOperationStatus.OK) {
2435                 result = Either.right(status);
2436                 break;
2437             }
2438         }
2439
2440         return result;
2441     }
2442
2443     /**
2444      * Validates uniqueness of examined property by comparing it with properties in propertiesOfType
2445      * and updates if need type and inner type of the property.
2446      */
2447     private JanusGraphOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2448         String propertyName = property.getName();
2449         String propertyType = property.getType();
2450
2451         JanusGraphOperationStatus result = JanusGraphOperationStatus.OK;
2452         if (inheritedProperties.containsKey(propertyName)) {
2453             PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2454             if (typesMismatch(propertyType, defaultProperty.getType())) {
2455                 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2456                 result = JanusGraphOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2457             } else {
2458                 property.setType(defaultProperty.getType());
2459                 String innerType = defaultProperty.getSchemaType();
2460
2461                 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2462                 if (schemaProperty != null) {
2463                     schemaProperty.setType(innerType);
2464                 }
2465             }
2466         }
2467
2468         return result;
2469     }
2470
2471     private boolean typesMismatch(String type1, String type2) {
2472         return type1 != null && type2 != null && !type2.equals(type1);
2473     }
2474
2475
2476     public <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllTypePropertiesFromAllDerivedFrom(String nextParentUid,
2477                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          NodeTypeEnum nodeType,
2478                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Class<T> clazz) {
2479         Map<String, PropertyDefinition> allProperies = new HashMap<>();
2480         return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2481     }
2482
2483     private <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getTypePropertiesFromDerivedFromRecursively(String nextParentUid,
2484                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Map<String, PropertyDefinition> allProperies,
2485                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  NodeTypeEnum nodeType,
2486                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Class<T> clazz) {
2487         JanusGraphOperationStatus error;
2488         Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
2489                                                 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType),
2490                                                                                                 nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2491         if (childrenNodes.isRight()) {
2492             if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
2493                 error = childrenNodes.right().value();
2494                 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid, error);
2495                 return Either.right(error);
2496             }
2497             else {
2498                 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.", nextParentUid);
2499                 return Either.left(allProperies);
2500             }
2501         } else {
2502
2503             Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2504             if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(
2505                                                                 JanusGraphOperationStatus.NOT_FOUND)) {
2506                 error = allPropertiesOfTypeRes.right().value();
2507                 log.error("#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}", nextParentUid, error);
2508                 return Either.right(error);
2509             } else if (allPropertiesOfTypeRes.isLeft()) {
2510                 if (allProperies.isEmpty()) {
2511                     allProperies.putAll(allPropertiesOfTypeRes.left().value());
2512                 } else {
2513                     allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey())).collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2514                 }
2515             }
2516             return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType, clazz);
2517         }
2518     }
2519     private JanusGraphOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2520
2521         if (MapUtils.isNotEmpty(newDescriptions)) {
2522             Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getDataTypePropertiesRes = janusGraphGenericDao
2523                                                                 .getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2524
2525             if(getDataTypePropertiesRes.isRight()){
2526                 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2527                 return getDataTypePropertiesRes.right().value();
2528             }
2529             getDataTypePropertiesRes.left().value().stream()
2530                     .filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2531                     .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2532
2533         }
2534         return JanusGraphOperationStatus.OK;
2535     }
2536
2537     private JanusGraphVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<JanusGraphVertex, Edge> pair) {
2538         return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2539     }
2540
2541     private String getPropertyNameFromEdge(ImmutablePair<JanusGraphVertex, Edge> pair) {
2542         return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2543     }
2544
2545     private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2546
2547         Map<String, PropertyDefinition> newPropertiesMap = newProperties
2548                 .stream()
2549                 .collect(Collectors.toMap(PropertyDefinition::getName, p->p));
2550
2551         return oldProperties
2552                 .stream()
2553                 .filter(p-> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2554                 .collect(Collectors.toMap(PropertyDefinition::getName, p->newPropertiesMap.get(p.getName()).getDescription()));
2555     }
2556
2557     private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty){
2558         if(StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())){
2559             return true;
2560         }
2561         if(StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())){
2562             return false;
2563         }
2564         if(StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())){
2565             return false;
2566         }
2567         return property.getDescription().equals(otherProperty.getDescription());
2568     }
2569 }