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