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