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