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