Reformat catalog-model
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / operations / impl / ComponentInstanceOperation.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 package org.openecomp.sdc.be.model.operations.impl;
21
22 import fj.F;
23 import fj.data.Either;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.UUID;
27 import java.util.function.Supplier;
28 import org.apache.commons.lang3.tuple.ImmutablePair;
29 import org.apache.tinkerpop.gremlin.structure.Vertex;
30 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
31 import org.janusgraph.core.JanusGraph;
32 import org.janusgraph.core.JanusGraphVertex;
33 import org.openecomp.sdc.be.config.BeEcompErrorManager;
34 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
35 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
36 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
37 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
38 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
39 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
40 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
41 import org.openecomp.sdc.be.dao.neo4j.GraphEdgePropertiesDictionary;
42 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
43 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
44 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
45 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
46 import org.openecomp.sdc.be.model.ComponentInstance;
47 import org.openecomp.sdc.be.model.ComponentInstanceInput;
48 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
49 import org.openecomp.sdc.be.model.DataTypeDefinition;
50 import org.openecomp.sdc.be.model.IComponentInstanceConnectedElement;
51 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
52 import org.openecomp.sdc.be.model.operations.api.IInputsOperation;
53 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
54 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
55 import org.openecomp.sdc.be.resources.data.AttributeData;
56 import org.openecomp.sdc.be.resources.data.AttributeValueData;
57 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
58 import org.openecomp.sdc.be.resources.data.InputValueData;
59 import org.openecomp.sdc.be.resources.data.InputsData;
60 import org.openecomp.sdc.common.datastructure.Wrapper;
61 import org.openecomp.sdc.common.log.wrappers.Logger;
62 import org.springframework.beans.factory.annotation.Autowired;
63
64 @org.springframework.stereotype.Component("component-instance-operation")
65 public class ComponentInstanceOperation extends AbstractOperation {
66
67     private static final Logger log = Logger.getLogger(ComponentInstanceOperation.class.getName());
68     @Autowired
69     PropertyOperation propertyOperation;
70     @Autowired
71     private IInputsOperation inputOperation;
72     @Autowired
73     private ApplicationDataTypeCache dataTypeCache;
74
75     public ComponentInstanceOperation() {
76         super();
77     }
78
79     /**
80      * FOR TEST ONLY
81      *
82      * @param janusGraphGenericDao
83      */
84     public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
85         this.janusGraphGenericDao = janusGraphGenericDao;
86     }
87
88     public Either<Integer, StorageOperationStatus> increaseAndGetResourceInstanceSpecificCounter(String resourceInstanceId,
89                                                                                                  GraphPropertiesDictionary counterType,
90                                                                                                  boolean inTransaction) {
91         Either<Integer, StorageOperationStatus> result = null;
92         try {
93             Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
94             if (graphResult.isRight()) {
95                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
96                 return result;
97             }
98             Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
99                 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId);
100             if (vertexService.isRight()) {
101                 log.debug("failed to fetch vertex of resource instance for id = {}", resourceInstanceId);
102                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
103             }
104             Vertex vertex = vertexService.left().value();
105             VertexProperty<Object> vertexProperty = vertex.property(counterType.getProperty());
106             Integer counter = 0;
107             if (vertexProperty.isPresent()) {
108                 if (vertexProperty.value() != null) {
109                     counter = (Integer) vertexProperty.value();
110                 }
111             }
112             counter++;
113             vertex.property(counterType.getProperty(), counter);
114             result = Either.left(counter);
115             return result;
116         } finally {
117             if (!inTransaction) {
118                 if (result == null || result.isRight()) {
119                     log.error("increaseAndGetResourceInstanceSpecificCounter operation : Going to execute rollback on graph.");
120                     janusGraphGenericDao.rollback();
121                 } else {
122                     log.debug("increaseAndGetResourceInstanceSpecificCounter operation : Going to execute commit on graph.");
123                     janusGraphGenericDao.commit();
124                 }
125             }
126         }
127     }
128
129     private void connectAttValueDataToComponentInstanceData(Wrapper<JanusGraphOperationStatus> errorWrapper, ComponentInstanceData compIns,
130                                                             AttributeValueData attValueData) {
131         Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
132             .createRelation(compIns, attValueData, GraphEdgeLabels.ATTRIBUTE_VALUE, null);
133         if (createRelResult.isRight()) {
134             JanusGraphOperationStatus operationStatus = createRelResult.right().value();
135             errorWrapper.setInnerElement(operationStatus);
136             BeEcompErrorManager.getInstance().logInternalFlowError("connectAttValueDataToComponentInstanceData",
137                 "Failed to associate resource instance " + compIns.getUniqueId() + " attribute value " + attValueData.getUniqueId()
138                     + " in graph. status is " + operationStatus, ErrorSeverity.ERROR);
139         }
140     }
141
142     private void connectAttValueDataToAttData(Wrapper<JanusGraphOperationStatus> errorWrapper, AttributeData attData,
143                                               AttributeValueData attValueData) {
144         Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
145             .createRelation(attValueData, attData, GraphEdgeLabels.ATTRIBUTE_IMPL, null);
146         if (createRelResult.isRight()) {
147             JanusGraphOperationStatus operationStatus = createRelResult.right().value();
148             BeEcompErrorManager.getInstance().logInternalFlowError("connectAttValueDataToAttData",
149                 "Failed to associate attribute value " + attValueData.getUniqueId() + " to attribute " + attData.getUniqueId()
150                     + " in graph. status is " + operationStatus, ErrorSeverity.ERROR);
151             errorWrapper.setInnerElement(operationStatus);
152         }
153     }
154
155     private void createAttributeValueDataNode(ComponentInstanceProperty attributeInstanceProperty, Integer index,
156                                               Wrapper<JanusGraphOperationStatus> errorWrapper, ComponentInstanceData resourceInstanceData,
157                                               Wrapper<AttributeValueData> attValueDataWrapper) {
158         String valueUniqueUid = attributeInstanceProperty.getValueUniqueUid();
159         if (valueUniqueUid == null) {
160             String attValueDatauniqueId = UniqueIdBuilder.buildResourceInstanceAttributeValueUid(resourceInstanceData.getUniqueId(), index);
161             AttributeValueData attributeValueData = buildAttributeValueDataFromComponentInstanceAttribute(attributeInstanceProperty,
162                 attValueDatauniqueId);
163             log.debug("Before adding attribute value to graph {}", attributeValueData);
164             Either<AttributeValueData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao
165                 .createNode(attributeValueData, AttributeValueData.class);
166             log.debug("After adding attribute value to graph {}", attributeValueData);
167             if (createNodeResult.isRight()) {
168                 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
169                 errorWrapper.setInnerElement(operationStatus);
170             } else {
171                 attValueDataWrapper.setInnerElement(createNodeResult.left().value());
172             }
173         } else {
174             BeEcompErrorManager.getInstance()
175                 .logInternalFlowError("CreateAttributeValueDataNode", "attribute value already exists.", ErrorSeverity.ERROR);
176             errorWrapper.setInnerElement(JanusGraphOperationStatus.ALREADY_EXIST);
177         }
178     }
179
180     private AttributeValueData buildAttributeValueDataFromComponentInstanceAttribute(ComponentInstanceProperty resourceInstanceAttribute,
181                                                                                      String uniqueId) {
182         AttributeValueData attributeValueData = new AttributeValueData();
183         attributeValueData.setUniqueId(uniqueId);
184         attributeValueData.setHidden(resourceInstanceAttribute.isHidden());
185         attributeValueData.setValue(resourceInstanceAttribute.getValue());
186         attributeValueData.setType(resourceInstanceAttribute.getType());
187         long currentTimeMillis = System.currentTimeMillis();
188         attributeValueData.setCreationTime(currentTimeMillis);
189         attributeValueData.setModificationTime(currentTimeMillis);
190         return attributeValueData;
191     }
192
193     /**
194      * update value of attribute on resource instance
195      *
196      * @param resourceInstanceAttribute
197      * @param resourceInstanceId
198      * @return
199      */
200     private Either<AttributeValueData, JanusGraphOperationStatus> updateAttributeOfResourceInstance(
201         ComponentInstanceProperty resourceInstanceAttribute, String resourceInstanceId) {
202         Wrapper<JanusGraphOperationStatus> errorWrapper = new Wrapper<>();
203         UpdateDataContainer<AttributeData, AttributeValueData> updateDataContainer = new UpdateDataContainer<>(GraphEdgeLabels.ATTRIBUTE_IMPL,
204             (() -> AttributeData.class), (() -> AttributeValueData.class), NodeTypeEnum.Attribute, NodeTypeEnum.AttributeValue);
205         preUpdateElementOfResourceInstanceValidations(updateDataContainer, resourceInstanceAttribute, resourceInstanceId, errorWrapper);
206         if (errorWrapper.isEmpty()) {
207             AttributeValueData attributeValueData = updateDataContainer.getValueDataWrapper().getInnerElement();
208             attributeValueData.setHidden(resourceInstanceAttribute.isHidden());
209             attributeValueData.setValue(resourceInstanceAttribute.getValue());
210             return janusGraphGenericDao.updateNode(attributeValueData, AttributeValueData.class);
211         } else {
212             return Either.right(errorWrapper.getInnerElement());
213         }
214     }
215
216     private Either<AttributeValueData, JanusGraphOperationStatus> addAttributeToResourceInstance(ComponentInstanceProperty attributeInstanceProperty,
217                                                                                                  String resourceInstanceId, Integer index) {
218         Wrapper<JanusGraphOperationStatus> errorWrapper = new Wrapper<>();
219         Wrapper<ComponentInstanceData> compInsWrapper = new Wrapper<>();
220         Wrapper<AttributeData> attDataWrapper = new Wrapper<>();
221         Wrapper<AttributeValueData> attValueDataWrapper = new Wrapper<>();
222         // Verify RI Exist
223         validateRIExist(resourceInstanceId, compInsWrapper, errorWrapper);
224         if (errorWrapper.isEmpty()) {
225             // Verify Attribute Exist
226             validateElementExistInGraph(attributeInstanceProperty.getUniqueId(), NodeTypeEnum.Attribute, () -> AttributeData.class, attDataWrapper,
227                 errorWrapper);
228         }
229         if (errorWrapper.isEmpty()) {
230             // Create AttributeValueData that is connected to RI
231             createAttributeValueDataNode(attributeInstanceProperty, index, errorWrapper, compInsWrapper.getInnerElement(), attValueDataWrapper);
232         }
233         if (errorWrapper.isEmpty()) {
234             // Connect AttributeValueData (Att on RI) to AttData (Att on
235
236             // Resource)
237             connectAttValueDataToAttData(errorWrapper, attDataWrapper.getInnerElement(), attValueDataWrapper.getInnerElement());
238         }
239         if (errorWrapper.isEmpty()) {
240             // Connect AttributeValueData to RI
241             connectAttValueDataToComponentInstanceData(errorWrapper, compInsWrapper.getInnerElement(), attValueDataWrapper.getInnerElement());
242         }
243         if (errorWrapper.isEmpty()) {
244             return Either.left(attValueDataWrapper.getInnerElement());
245         } else {
246             return Either.right(errorWrapper.getInnerElement());
247         }
248     }
249
250     private <SomeData extends GraphNode, SomeValueData extends GraphNode> void preUpdateElementOfResourceInstanceValidations(
251         UpdateDataContainer<SomeData, SomeValueData> updateDataContainer, IComponentInstanceConnectedElement resourceInstanceProerty,
252         String resourceInstanceId, Wrapper<JanusGraphOperationStatus> errorWrapper) {
253         if (errorWrapper.isEmpty()) {
254             // Verify VFC instance Exist
255             validateRIExist(resourceInstanceId, errorWrapper);
256         }
257         if (errorWrapper.isEmpty()) {
258             // Example: Verify Property connected to VFC exist
259             validateElementConnectedToComponentExist(updateDataContainer, resourceInstanceProerty, errorWrapper);
260         }
261         if (errorWrapper.isEmpty()) {
262             // Example: Verify PropertyValue connected to VFC Instance exist
263             validateElementConnectedToComponentInstanceExist(updateDataContainer, resourceInstanceProerty, errorWrapper);
264         }
265         if (errorWrapper.isEmpty()) {
266             // Example: Verify PropertyValue connected Property
267             validateElementConnectedToInstance(updateDataContainer, resourceInstanceProerty, errorWrapper);
268         }
269     }
270
271     private <SomeData extends GraphNode, SomeValueData extends GraphNode> void validateElementConnectedToInstance(
272         UpdateDataContainer<SomeData, SomeValueData> updateDataContainer, IComponentInstanceConnectedElement resourceInstanceProerty,
273         Wrapper<JanusGraphOperationStatus> errorWrapper) {
274         Either<ImmutablePair<SomeData, GraphEdge>, JanusGraphOperationStatus> child = janusGraphGenericDao
275             .getChild(UniqueIdBuilder.getKeyByNodeType(updateDataContainer.getNodeTypeValue()), resourceInstanceProerty.getValueUniqueUid(),
276                 updateDataContainer.getGraphEdge(), updateDataContainer.getNodeType(), updateDataContainer.getSomeDataClassGen().get());
277         if (child.isRight()) {
278             JanusGraphOperationStatus status = child.right().value();
279             if (status == JanusGraphOperationStatus.NOT_FOUND) {
280                 status = JanusGraphOperationStatus.INVALID_ID;
281             }
282             errorWrapper.setInnerElement(status);
283         } else {
284             updateDataContainer.getDataWrapper().setInnerElement(child.left().value().left);
285         }
286     }
287
288     private <SomeValueData extends GraphNode, SomeData extends GraphNode> void validateElementConnectedToComponentInstanceExist(
289         UpdateDataContainer<SomeData, SomeValueData> updateDataContainer, IComponentInstanceConnectedElement resourceInstanceProerty,
290         Wrapper<JanusGraphOperationStatus> errorWrapper) {
291         String valueUniqueUid = resourceInstanceProerty.getValueUniqueUid();
292         if (valueUniqueUid == null) {
293             errorWrapper.setInnerElement(JanusGraphOperationStatus.INVALID_ID);
294         } else {
295             Either<SomeValueData, JanusGraphOperationStatus> findPropertyValueRes = janusGraphGenericDao
296                 .getNode(UniqueIdBuilder.getKeyByNodeType(updateDataContainer.getNodeTypeValue()), valueUniqueUid,
297                     updateDataContainer.getSomeValueDataClassGen().get());
298             if (findPropertyValueRes.isRight()) {
299                 JanusGraphOperationStatus status = findPropertyValueRes.right().value();
300                 if (status == JanusGraphOperationStatus.NOT_FOUND) {
301                     status = JanusGraphOperationStatus.INVALID_ID;
302                 }
303                 errorWrapper.setInnerElement(status);
304             } else {
305                 updateDataContainer.getValueDataWrapper().setInnerElement(findPropertyValueRes.left().value());
306             }
307         }
308     }
309
310     private <SomeData extends GraphNode, SomeValueData extends GraphNode> void validateElementConnectedToComponentExist(
311         UpdateDataContainer<SomeData, SomeValueData> updateDataContainer, IComponentInstanceConnectedElement resourceInstanceElementConnected,
312         Wrapper<JanusGraphOperationStatus> errorWrapper) {
313         String uniqueId = resourceInstanceElementConnected.getUniqueId();
314         Either<SomeData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
315             .getNode(UniqueIdBuilder.getKeyByNodeType(updateDataContainer.getNodeType()), uniqueId, updateDataContainer.getSomeDataClassGen().get());
316         if (findPropertyDefRes.isRight()) {
317             JanusGraphOperationStatus status = findPropertyDefRes.right().value();
318             errorWrapper.setInnerElement(status);
319         }
320     }
321
322     private void validateRIExist(String resourceInstanceId, Wrapper<JanusGraphOperationStatus> errorWrapper) {
323         validateRIExist(resourceInstanceId, null, errorWrapper);
324     }
325
326     private void validateRIExist(String resourceInstanceId, Wrapper<ComponentInstanceData> compInsDataWrapper,
327                                  Wrapper<JanusGraphOperationStatus> errorWrapper) {
328         validateElementExistInGraph(resourceInstanceId, NodeTypeEnum.ResourceInstance, () -> ComponentInstanceData.class, compInsDataWrapper,
329             errorWrapper);
330     }
331
332     public <ElementData extends GraphNode> void validateElementExistInGraph(String elementUniqueId, NodeTypeEnum elementNodeType,
333                                                                             Supplier<Class<ElementData>> elementClassGen,
334                                                                             Wrapper<ElementData> elementDataWrapper,
335                                                                             Wrapper<JanusGraphOperationStatus> errorWrapper) {
336         Either<ElementData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
337             .getNode(UniqueIdBuilder.getKeyByNodeType(elementNodeType), elementUniqueId, elementClassGen.get());
338         if (findResInstanceRes.isRight()) {
339             JanusGraphOperationStatus status = findResInstanceRes.right().value();
340             if (status == JanusGraphOperationStatus.NOT_FOUND) {
341                 status = JanusGraphOperationStatus.INVALID_ID;
342             }
343             errorWrapper.setInnerElement(status);
344         } else {
345             if (elementDataWrapper != null) {
346                 elementDataWrapper.setInnerElement(findResInstanceRes.left().value());
347             }
348         }
349     }
350
351     /**
352      * add property to resource instance
353      *
354      * @param resourceInstanceId
355      * @param index
356      * @return
357      */
358     private Either<InputValueData, JanusGraphOperationStatus> addInputToResourceInstance(ComponentInstanceInput resourceInstanceInput,
359                                                                                          String resourceInstanceId, Integer index) {
360         Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
361             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
362         if (findResInstanceRes.isRight()) {
363             JanusGraphOperationStatus status = findResInstanceRes.right().value();
364             if (status == JanusGraphOperationStatus.NOT_FOUND) {
365                 status = JanusGraphOperationStatus.INVALID_ID;
366             }
367             return Either.right(status);
368         }
369         String propertyId = resourceInstanceInput.getUniqueId();
370         Either<InputsData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
371             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Input), propertyId, InputsData.class);
372         if (findPropertyDefRes.isRight()) {
373             JanusGraphOperationStatus status = findPropertyDefRes.right().value();
374             if (status == JanusGraphOperationStatus.NOT_FOUND) {
375                 status = JanusGraphOperationStatus.INVALID_ID;
376             }
377             return Either.right(status);
378         }
379         String valueUniqueUid = resourceInstanceInput.getValueUniqueUid();
380         if (valueUniqueUid == null) {
381             InputsData propertyData = findPropertyDefRes.left().value();
382             ComponentInstanceData resourceInstanceData = findResInstanceRes.left().value();
383             ImmutablePair<JanusGraphOperationStatus, String> isInputValueExists = inputOperation.findInputValue(resourceInstanceId, propertyId);
384             if (isInputValueExists.getLeft() == JanusGraphOperationStatus.ALREADY_EXIST) {
385                 log.debug("The property {} already added to the resource instance {}", propertyId, resourceInstanceId);
386                 resourceInstanceInput.setValueUniqueUid(isInputValueExists.getRight());
387             }
388             if (isInputValueExists.getLeft() != JanusGraphOperationStatus.NOT_FOUND) {
389                 log.debug("After finding input value of {} on componenet instance {}", propertyId, resourceInstanceId);
390                 return Either.right(isInputValueExists.getLeft());
391             }
392             String innerType = null;
393             PropertyDataDefinition propDataDef = propertyData.getPropertyDataDefinition();
394             String propertyType = propDataDef.getType();
395             String value = resourceInstanceInput.getValue();
396             ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
397             if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
398                 SchemaDefinition def = propDataDef.getSchema();
399                 if (def == null) {
400                     log.debug("Schema doesn't exists for property of type {}", type);
401                     return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
402                 }
403                 PropertyDataDefinition propDef = def.getProperty();
404                 if (propDef == null) {
405                     log.debug("Property in Schema Definition inside property of type {} doesn't exist", type);
406                     return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
407                 }
408                 innerType = propDef.getType();
409             }
410             log.debug("Before validateAndUpdatePropertyValue");
411             Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes = dataTypeCache.getAll();
412             if (allDataTypes.isRight()) {
413                 JanusGraphOperationStatus status = allDataTypes.right().value();
414                 BeEcompErrorManager.getInstance().logInternalFlowError("UpdatePropertyValueOnComponentInstance",
415                     "Failed to update property value on instance. Status is " + status, ErrorSeverity.ERROR);
416                 return Either.right(status);
417             }
418             String uniqueId = UniqueIdBuilder.buildResourceInstanceInputValueUid(resourceInstanceData.getUniqueId(), index);
419             InputValueData propertyValueData = new InputValueData();
420             propertyValueData.setUniqueId(uniqueId);
421             propertyValueData.setValue(value);
422             log.debug("Before validateAndUpdateRules");
423             ImmutablePair<String, Boolean> pair = propertyOperation
424                 .validateAndUpdateRules(propertyType, resourceInstanceInput.getRules(), innerType, allDataTypes.left().value(), true);
425             log.debug("After validateAndUpdateRules. pair = {} ", pair);
426             if (pair.getRight() != null && !pair.getRight()) {
427                 BeEcompErrorManager.getInstance()
428                     .logBeInvalidValueError("Add property value", pair.getLeft(), resourceInstanceInput.getName(), propertyType);
429                 return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
430             }
431             log.debug("Before adding property value to graph {}", propertyValueData);
432             Either<InputValueData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao
433                 .createNode(propertyValueData, InputValueData.class);
434             log.debug("After adding property value to graph {}", propertyValueData);
435             if (createNodeResult.isRight()) {
436                 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
437                 return Either.right(operationStatus);
438             }
439             Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
440                 .createRelation(propertyValueData, propertyData, GraphEdgeLabels.INPUT_IMPL, null);
441             if (createRelResult.isRight()) {
442                 JanusGraphOperationStatus operationStatus = createRelResult.right().value();
443                 log.error("Failed to associate property value {} to property {} in graph. status is {}", uniqueId, propertyId, operationStatus);
444                 return Either.right(operationStatus);
445             }
446             Map<String, Object> properties1 = new HashMap<>();
447             properties1.put(GraphEdgePropertiesDictionary.NAME.getProperty(), resourceInstanceData.getComponentInstDataDefinition().getName());
448             properties1
449                 .put(GraphEdgePropertiesDictionary.OWNER_ID.getProperty(), resourceInstanceData.getComponentInstDataDefinition().getUniqueId());
450             createRelResult = janusGraphGenericDao.createRelation(resourceInstanceData, propertyValueData, GraphEdgeLabels.INPUT_VALUE, properties1);
451             if (createRelResult.isRight()) {
452                 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
453                 log.error("Failed to associate resource instance {} property value {} in graph. status is {}", resourceInstanceId, uniqueId,
454                     operationStatus);
455                 return Either.right(operationStatus);
456             }
457             return Either.left(createNodeResult.left().value());
458         } else {
459             log.error("property value already exists.");
460             return Either.right(JanusGraphOperationStatus.ALREADY_EXIST);
461         }
462     }
463
464     public Either<ComponentInstanceProperty, StorageOperationStatus> addAttributeValueToResourceInstance(
465         ComponentInstanceProperty resourceInstanceAttribute, String resourceInstanceId, Integer index, boolean inTransaction) {
466         Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
467         try {
468             Either<AttributeValueData, JanusGraphOperationStatus> eitherStatus = this
469                 .addAttributeToResourceInstance(resourceInstanceAttribute, resourceInstanceId, index);
470             if (eitherStatus.isRight()) {
471                 log.error("Failed to add attribute value {} to resource instance {} in Graph. status is {}", resourceInstanceAttribute,
472                     resourceInstanceId, eitherStatus.right().value().name());
473                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
474                 return result;
475             } else {
476                 AttributeValueData attributeValueData = eitherStatus.left().value();
477                 ComponentInstanceProperty attributeValueResult = buildResourceInstanceAttribute(attributeValueData, resourceInstanceAttribute);
478                 log.debug("The returned ResourceInstanceAttribute is {}", attributeValueResult);
479                 result = Either.left(attributeValueResult);
480                 return result;
481             }
482         } finally {
483             handleTransactionCommitRollback(inTransaction, result);
484         }
485     }
486
487     private ComponentInstanceProperty buildResourceInstanceAttribute(AttributeValueData attributeValueData,
488                                                                      ComponentInstanceProperty resourceInstanceAttribute) {
489         Boolean hidden = attributeValueData.isHidden();
490         String uid = attributeValueData.getUniqueId();
491         return new ComponentInstanceProperty(hidden, resourceInstanceAttribute, uid);
492     }
493
494     public Either<ComponentInstanceProperty, StorageOperationStatus> updateAttributeValueInResourceInstance(
495         ComponentInstanceProperty resourceInstanceAttribute, String resourceInstanceId, boolean inTransaction) {
496         //TODO This null could bubble up. Shouldn't we set a default value (such as Either.left(StorageOperationStatus.GENERAL_ERROR)) ?
497         Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
498         try {
499             result = updateAttributeOfResourceInstance(resourceInstanceAttribute, resourceInstanceId)
500                 .bimap(buildResourceInstanceAttribute(resourceInstanceAttribute),
501                     handleFailedAttributeAdditionError(resourceInstanceAttribute, resourceInstanceId));
502         } finally {
503             handleTransactionCommitRollback(inTransaction, result);
504         }
505         return result;
506     }
507
508     private F<JanusGraphOperationStatus, StorageOperationStatus> handleFailedAttributeAdditionError(
509         ComponentInstanceProperty resourceInstanceAttribute, String resourceInstanceId) {
510         return status -> {
511             log.error("Failed to add attribute value {} to resource instance {} in Graph. status is {}", resourceInstanceAttribute,
512                 resourceInstanceId, status.name());
513             return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
514         };
515     }
516
517     private F<AttributeValueData, ComponentInstanceProperty> buildResourceInstanceAttribute(ComponentInstanceProperty resourceInstanceAttribute) {
518         return attributeValueData -> {
519             ComponentInstanceProperty attributeValueResult = buildResourceInstanceAttribute(attributeValueData, resourceInstanceAttribute);
520             log.debug("The returned ResourceInstanceAttribute is {}", attributeValueResult);
521             return attributeValueResult;
522         };
523     }
524
525     public Either<ComponentInstanceInput, StorageOperationStatus> addInputValueToResourceInstance(ComponentInstanceInput resourceInstanceInput,
526                                                                                                   String resourceInstanceId, Integer index,
527                                                                                                   boolean inTransaction) {
528         /// #RULES SUPPORT
529
530         /// Ignore rules received from client till support
531         resourceInstanceInput.setRules(null);
532         ///
533
534         ///
535         Either<ComponentInstanceInput, StorageOperationStatus> result = null;
536         try {
537             Either<InputValueData, JanusGraphOperationStatus> eitherStatus = addInputToResourceInstance(resourceInstanceInput, resourceInstanceId,
538                 index);
539             if (eitherStatus.isRight()) {
540                 log.error("Failed to add input value {} to resource instance {} in Graph. status is {}", resourceInstanceInput, resourceInstanceId,
541                     eitherStatus.right().value().name());
542                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
543                 return result;
544             } else {
545                 InputValueData propertyValueData = eitherStatus.left().value();
546                 ComponentInstanceInput propertyValueResult = inputOperation.buildResourceInstanceInput(propertyValueData, resourceInstanceInput);
547                 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
548                 Either<String, JanusGraphOperationStatus> findDefaultValue = propertyOperation
549                     .findDefaultValueFromSecondPosition(resourceInstanceInput.getPath(), resourceInstanceInput.getUniqueId(),
550                         resourceInstanceInput.getDefaultValue());
551                 if (findDefaultValue.isRight()) {
552                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(findDefaultValue.right().value()));
553                     return result;
554                 }
555                 String defaultValue = findDefaultValue.left().value();
556                 propertyValueResult.setDefaultValue(defaultValue);
557                 log.debug("The returned default value in ResourceInstanceProperty is {}", defaultValue);
558                 result = Either.left(propertyValueResult);
559                 return result;
560             }
561         } finally {
562             if (!inTransaction) {
563                 if (result == null || result.isRight()) {
564                     log.error("Going to execute rollback on graph.");
565                     janusGraphGenericDao.rollback();
566                 } else {
567                     log.debug("Going to execute commit on graph.");
568                     janusGraphGenericDao.commit();
569                 }
570             }
571         }
572     }
573
574     public Either<ComponentInstanceInput, StorageOperationStatus> updateInputValueInResourceInstance(ComponentInstanceInput input,
575                                                                                                      String resourceInstanceId, boolean b) {
576         return null;
577     }
578
579     public StorageOperationStatus updateCustomizationUUID(String componentInstanceId) {
580         Either<JanusGraphVertex, JanusGraphOperationStatus> vertexByProperty = janusGraphGenericDao
581             .getVertexByProperty(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), componentInstanceId);
582         if (vertexByProperty.isRight()) {
583             log.debug("Failed to fetch component instance by id {} error {}", componentInstanceId, vertexByProperty.right().value());
584             return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexByProperty.right().value());
585         }
586         UUID uuid = UUID.randomUUID();
587         JanusGraphVertex ciVertex = vertexByProperty.left().value();
588         ciVertex.property(GraphPropertiesDictionary.CUSTOMIZATION_UUID.getProperty(), uuid.toString());
589         return StorageOperationStatus.OK;
590     }
591
592     public Either<ComponentInstanceData, StorageOperationStatus> updateComponentInstanceModificationTimeAndCustomizationUuidOnGraph(
593         ComponentInstance componentInstance, NodeTypeEnum componentInstanceType, Long modificationTime, boolean inTransaction) {
594         log.debug("Going to update modification time of component instance {}. ", componentInstance.getName());
595         Either<ComponentInstanceData, StorageOperationStatus> result = null;
596         try {
597             ComponentInstanceData componentData = new ComponentInstanceData(componentInstance, componentInstance.getGroupInstances().size());
598             componentData.getComponentInstDataDefinition().setModificationTime(modificationTime);
599             componentData.getComponentInstDataDefinition().setCustomizationUUID(UUID.randomUUID().toString());
600             Either<ComponentInstanceData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao
601                 .updateNode(componentData, ComponentInstanceData.class);
602             if (updateNode.isRight()) {
603                 log.error("Failed to update resource {}. status is {}", componentInstance.getUniqueId(), updateNode.right().value());
604                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updateNode.right().value()));
605             } else {
606                 result = Either.left(updateNode.left().value());
607             }
608         } catch (Exception e) {
609             log.error("Exception occured during  update modification date of compomemt instance{}. The message is {}. ", componentInstance.getName(),
610                 e.getMessage(), e);
611             result = Either.right(StorageOperationStatus.GENERAL_ERROR);
612         } finally {
613             if (!inTransaction) {
614                 if (result == null || result.isRight()) {
615                     log.error("Going to execute rollback on graph.");
616                     janusGraphGenericDao.rollback();
617                 } else {
618                     log.debug("Going to execute commit on graph.");
619                     janusGraphGenericDao.commit();
620                 }
621             }
622         }
623         return result;
624     }
625
626     private static final class UpdateDataContainer<SomeData, SomeValueData> {
627
628         final Wrapper<SomeValueData> valueDataWrapper;
629         final Wrapper<SomeData> dataWrapper;
630         final GraphEdgeLabels graphEdge;
631         final Supplier<Class<SomeData>> someDataClassGen;
632         final Supplier<Class<SomeValueData>> someValueDataClassGen;
633         final NodeTypeEnum nodeType;
634         final NodeTypeEnum nodeTypeValue;
635
636         private UpdateDataContainer(GraphEdgeLabels graphEdge, Supplier<Class<SomeData>> someDataClassGen,
637                                     Supplier<Class<SomeValueData>> someValueDataClassGen, NodeTypeEnum nodeType, NodeTypeEnum nodeTypeValue) {
638             super();
639             this.valueDataWrapper = new Wrapper<>();
640             this.dataWrapper = new Wrapper<>();
641             this.graphEdge = graphEdge;
642             this.someDataClassGen = someDataClassGen;
643             this.someValueDataClassGen = someValueDataClassGen;
644             this.nodeType = nodeType;
645             this.nodeTypeValue = nodeTypeValue;
646         }
647
648         public Wrapper<SomeValueData> getValueDataWrapper() {
649             return valueDataWrapper;
650         }
651
652         public Wrapper<SomeData> getDataWrapper() {
653             return dataWrapper;
654         }
655
656         public GraphEdgeLabels getGraphEdge() {
657             return graphEdge;
658         }
659
660         public Supplier<Class<SomeData>> getSomeDataClassGen() {
661             return someDataClassGen;
662         }
663
664         public Supplier<Class<SomeValueData>> getSomeValueDataClassGen() {
665             return someValueDataClassGen;
666         }
667
668         public NodeTypeEnum getNodeType() {
669             return nodeType;
670         }
671
672         public NodeTypeEnum getNodeTypeValue() {
673             return nodeTypeValue;
674         }
675     }
676 }