2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.openecomp.sdc.be.model.operations.impl;
22 import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR;
24 import java.io.IOException;
25 import java.lang.reflect.Type;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.List;
32 import java.util.Map.Entry;
34 import java.util.StringJoiner;
35 import java.util.function.Consumer;
36 import java.util.regex.Matcher;
37 import java.util.regex.Pattern;
38 import java.util.stream.Collectors;
39 import org.apache.commons.collections.CollectionUtils;
40 import org.apache.commons.collections.MapUtils;
41 import org.apache.commons.lang3.StringUtils;
42 import org.apache.commons.lang3.tuple.ImmutablePair;
43 import org.apache.tinkerpop.gremlin.structure.Edge;
44 import org.apache.tinkerpop.gremlin.structure.Vertex;
45 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
46 import org.janusgraph.core.JanusGraph;
47 import org.janusgraph.core.JanusGraphVertex;
48 import org.janusgraph.core.JanusGraphVertexProperty;
49 import org.openecomp.sdc.be.config.BeEcompErrorManager;
50 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
51 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
52 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
53 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
54 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
55 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
56 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
57 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
58 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
59 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
60 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
61 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
62 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
63 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
64 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
65 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
66 import org.openecomp.sdc.be.model.DataTypeDefinition;
67 import org.openecomp.sdc.be.model.IComplexDefaultValue;
68 import org.openecomp.sdc.be.model.PropertyConstraint;
69 import org.openecomp.sdc.be.model.PropertyDefinition;
70 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
71 import org.openecomp.sdc.be.model.operations.api.IPropertyOperation;
72 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
73 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
74 import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType;
75 import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint;
76 import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
77 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
78 import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
79 import org.openecomp.sdc.be.model.tosca.constraints.LessThanConstraint;
80 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
81 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
82 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
83 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
84 import org.openecomp.sdc.be.resources.data.DataTypeData;
85 import org.openecomp.sdc.be.resources.data.PropertyData;
86 import org.openecomp.sdc.be.resources.data.PropertyValueData;
87 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
88 import org.openecomp.sdc.be.resources.data.UniqueIdData;
89 import org.openecomp.sdc.common.log.wrappers.Logger;
90 import org.springframework.beans.factory.annotation.Autowired;
91 import org.springframework.stereotype.Component;
92 import com.fasterxml.jackson.core.ObjectCodec;
93 import com.fasterxml.jackson.databind.DeserializationContext;
94 import com.fasterxml.jackson.databind.JsonNode;
95 import com.google.common.collect.Maps;
96 import com.google.gson.JsonArray;
97 import com.google.gson.JsonDeserializationContext;
98 import com.google.gson.JsonDeserializer;
99 import com.google.gson.JsonElement;
100 import com.google.gson.JsonObject;
101 import com.google.gson.JsonParseException;
102 import com.google.gson.JsonParser;
103 import com.google.gson.JsonSerializationContext;
104 import com.google.gson.JsonSerializer;
105 import fj.data.Either;
107 @Component("property-operation")
108 public class PropertyOperation extends AbstractOperation implements IPropertyOperation {
110 private static final String AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS = "After retrieving DERIVED_FROM node of {}. status is {}";
111 private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
112 private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph. status is {}";
113 private static final String GOING_TO_EXECUTE_COMMIT_ON_GRAPH = "Going to execute commit on graph.";
114 private static final String GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH = "Going to execute rollback on graph.";
115 private static final String FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS = "Failed to associate resource {} to property {} in graph. status is {}";
116 private static final String AFTER_ADDING_PROPERTY_TO_GRAPH = "After adding property to graph {}";
117 private static final String BEFORE_ADDING_PROPERTY_TO_GRAPH = "Before adding property to graph {}";
118 private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
119 private static final String PROPERTY = "Property";
120 private static final String UPDATE_DATA_TYPE = "UpdateDataType";
121 private static Logger log = Logger.getLogger(PropertyOperation.class.getName());
122 private DerivedFromOperation derivedFromOperation;
125 public PropertyOperation(HealingJanusGraphGenericDao janusGraphGenericDao, DerivedFromOperation derivedFromOperation) {
126 this.janusGraphGenericDao = janusGraphGenericDao;
127 this.derivedFromOperation = derivedFromOperation;
130 public PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) {
131 log.debug("The object returned after create property is {}", propertyDataResult);
132 PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition());
133 propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints()));
134 propertyDefResult.setName(propertyName);
135 return propertyDefResult;
138 public Either<PropertyData, StorageOperationStatus> addProperty(String propertyName, PropertyDefinition propertyDefinition, String resourceId) {
139 Either<PropertyData, JanusGraphOperationStatus> either = addPropertyToGraph(propertyName, propertyDefinition, resourceId);
140 if (either.isRight()) {
141 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
142 return Either.right(storageStatus);
144 return Either.left(either.left().value());
148 * @param propertyDefinition
152 public StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
153 log.trace("Going to validate property type and value. {}", propertyDefinition);
154 String propertyType = propertyDefinition.getType();
155 String value = propertyDefinition.getDefaultValue();
156 ToscaPropertyType type = getType(propertyType);
158 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
159 if (dataTypeDefinition == null) {
160 log.debug("The type {} of property cannot be found.", propertyType);
161 return StorageOperationStatus.INVALID_TYPE;
163 return validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes);
165 String innerType = null;
166 Either<String, JanusGraphOperationStatus> checkInnerType = getInnerType(type, propertyDefinition::getSchema);
167 if (checkInnerType.isRight()) {
168 return StorageOperationStatus.INVALID_TYPE;
170 innerType = checkInnerType.left().value();
171 log.trace("After validating property type {}", propertyType);
172 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
173 if (!isValidProperty) {
174 log.info(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
175 return StorageOperationStatus.INVALID_VALUE;
177 PropertyValueConverter converter = type.getConverter();
178 if (isEmptyValue(value)) {
179 log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE);
180 propertyDefinition.setDefaultValue(EMPTY_VALUE);
181 } else if (!isEmptyValue(value)) {
182 String convertedValue = converter.convert(value, innerType, dataTypes);
183 propertyDefinition.setDefaultValue(convertedValue);
185 return StorageOperationStatus.OK;
188 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToGraph(String propertyName, PropertyDefinition propertyDefinition,
190 ResourceMetadataData resourceData = new ResourceMetadataData();
191 resourceData.getMetadataDataDefinition().setUniqueId(resourceId);
192 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
193 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
194 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
195 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
196 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
197 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
198 if (createNodeResult.isRight()) {
199 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
200 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
201 return Either.right(operationStatus);
203 Map<String, Object> props = new HashMap<>();
204 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
205 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
206 .createRelation(resourceData, propertyData, GraphEdgeLabels.PROPERTY, props);
207 if (createRelResult.isRight()) {
208 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
209 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, operationStatus);
210 return Either.right(operationStatus);
212 return Either.left(createNodeResult.left().value());
215 public JanusGraphOperationStatus addPropertyToGraphByVertex(JanusGraphVertex metadataVertex, String propertyName,
216 PropertyDefinition propertyDefinition, String resourceId) {
217 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
218 propertyDefinition.setUniqueId(UniqueIdBuilder.buildComponentPropertyUniqueId(resourceId, propertyName));
219 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
220 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
221 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData);
222 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
223 if (createNodeResult.isRight()) {
224 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
225 log.error("Failed to add property {} to graph. status is ", propertyName, operationStatus);
226 return operationStatus;
228 Map<String, Object> props = new HashMap<>();
229 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
230 JanusGraphVertex propertyVertex = createNodeResult.left().value();
231 JanusGraphOperationStatus createRelResult = janusGraphGenericDao.createEdge(metadataVertex, propertyVertex, GraphEdgeLabels.PROPERTY, props);
232 if (!createRelResult.equals(JanusGraphOperationStatus.OK)) {
233 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, resourceId, propertyName, createRelResult);
234 return createRelResult;
236 return createRelResult;
239 public JanusGraphGenericDao getJanusGraphGenericDao() {
240 return janusGraphGenericDao;
246 * @param janusGraphGenericDao
248 public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
249 this.janusGraphGenericDao = janusGraphGenericDao;
252 public Either<PropertyData, JanusGraphOperationStatus> deletePropertyFromGraph(String propertyId) {
253 log.debug("Before deleting property from graph {}", propertyId);
254 return janusGraphGenericDao.deleteNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
257 public Either<PropertyData, StorageOperationStatus> updateProperty(String propertyId, PropertyDefinition newPropertyDefinition,
258 Map<String, DataTypeDefinition> dataTypes) {
259 StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes);
260 if (validateAndUpdateProperty != StorageOperationStatus.OK) {
261 return Either.right(validateAndUpdateProperty);
263 Either<PropertyData, JanusGraphOperationStatus> either = updatePropertyFromGraph(propertyId, newPropertyDefinition);
264 if (either.isRight()) {
265 StorageOperationStatus storageStatus = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(either.right().value());
266 return Either.right(storageStatus);
268 return Either.left(either.left().value());
271 public Either<PropertyData, JanusGraphOperationStatus> updatePropertyFromGraph(String propertyId, PropertyDefinition propertyDefinition) {
272 if (log.isDebugEnabled()) {
273 log.debug("Before updating property on graph {}", propertyId);
275 // get the original property data
276 Either<PropertyData, JanusGraphOperationStatus> statusProperty = janusGraphGenericDao
277 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
278 if (statusProperty.isRight()) {
279 log.debug("Problem while get property with id {}. Reason - {}", propertyId, statusProperty.right().value().name());
280 return Either.right(statusProperty.right().value());
282 PropertyData orgPropertyData = statusProperty.left().value();
283 PropertyDataDefinition orgPropertyDataDefinition = orgPropertyData.getPropertyDataDefinition();
284 // create new property data to update
285 PropertyData newPropertyData = new PropertyData();
286 newPropertyData.setPropertyDataDefinition(propertyDefinition);
287 PropertyDataDefinition newPropertyDataDefinition = newPropertyData.getPropertyDataDefinition();
288 // update the original property data with new values
289 if (orgPropertyDataDefinition.getDefaultValue() == null) {
290 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
292 if (!orgPropertyDataDefinition.getDefaultValue().equals(newPropertyDataDefinition.getDefaultValue())) {
293 orgPropertyDataDefinition.setDefaultValue(newPropertyDataDefinition.getDefaultValue());
296 if (orgPropertyDataDefinition.getDescription() == null) {
297 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
299 if (!orgPropertyDataDefinition.getDescription().equals(newPropertyDataDefinition.getDescription())) {
300 orgPropertyDataDefinition.setDescription(newPropertyDataDefinition.getDescription());
303 if (!orgPropertyDataDefinition.getType().equals(newPropertyDataDefinition.getType())) {
304 orgPropertyDataDefinition.setType(newPropertyDataDefinition.getType());
306 if (newPropertyData.getConstraints() != null) {
307 orgPropertyData.setConstraints(newPropertyData.getConstraints());
309 orgPropertyDataDefinition.setSchema(newPropertyDataDefinition.getSchema());
310 return janusGraphGenericDao.updateNode(orgPropertyData, PropertyData.class);
313 public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition,
314 NodeTypeEnum nodeType, String uniqueId) {
315 List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
316 propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
317 PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
318 if (log.isDebugEnabled()) {
319 log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
321 Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
322 if (log.isDebugEnabled()) {
323 log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
325 if (createNodeResult.isRight()) {
326 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
327 log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
328 return Either.right(operationStatus);
330 Map<String, Object> props = new HashMap<>();
331 props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
332 UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
333 log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
334 Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
335 .createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
336 if (createRelResult.isRight()) {
337 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
338 log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
339 return Either.right(operationStatus);
341 return Either.left(createNodeResult.left().value());
344 public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
345 Map<String, PropertyDefinition> resourceProps = new HashMap<>();
346 Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
347 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), uniqueId, GraphEdgeLabels.PROPERTY, NodeTypeEnum.Property,
349 if (childrenNodes.isRight()) {
350 JanusGraphOperationStatus operationStatus = childrenNodes.right().value();
351 return Either.right(operationStatus);
353 List<ImmutablePair<PropertyData, GraphEdge>> values = childrenNodes.left().value();
354 if (values != null) {
355 for (ImmutablePair<PropertyData, GraphEdge> immutablePair : values) {
356 GraphEdge edge = immutablePair.getValue();
357 String propertyName = (String) edge.getProperties().get(GraphPropertiesDictionary.NAME.getProperty());
358 log.debug("Property {} is associated to node {}", propertyName, uniqueId);
359 PropertyData propertyData = immutablePair.getKey();
360 PropertyDefinition propertyDefinition = this.convertPropertyDataToPropertyDefinition(propertyData, propertyName, uniqueId);
361 resourceProps.put(propertyName, propertyDefinition);
364 log.debug("The properties associated to node {} are {}", uniqueId, resourceProps);
365 return Either.left(resourceProps);
368 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deletePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId) {
369 return deleteAllPropertiesAssociatedToNode(nodeType, uniqueId).right()
370 .bind(err -> err == StorageOperationStatus.OK ? Either.left(Collections.emptyMap()) : Either.right(err));
373 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> mergePropertiesAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
374 Map<String, PropertyDefinition> newProperties) {
375 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
376 Map<String, PropertyDefinition> reallyNewProperties;
377 Map<String, PropertyData> unchangedPropsData;
378 if (oldPropertiesRes.isRight()) {
379 JanusGraphOperationStatus err = oldPropertiesRes.right().value();
380 if (err == JanusGraphOperationStatus.NOT_FOUND) {
381 reallyNewProperties = newProperties;
382 unchangedPropsData = Collections.emptyMap();
384 return Either.right(err);
387 Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
388 reallyNewProperties = collectReallyNewProperties(newProperties, oldProperties);
389 for (Entry<String, PropertyDefinition> oldEntry : oldProperties.entrySet()) {
390 String key = oldEntry.getKey();
391 PropertyDefinition newPropDef = newProperties != null ? newProperties.get(key) : null;
392 PropertyDefinition oldPropDef = oldEntry.getValue();
393 JanusGraphOperationStatus status = updateOldProperty(newPropDef, oldPropDef);
394 if (status != JanusGraphOperationStatus.OK) {
395 return Either.right(status);
398 unchangedPropsData = oldProperties.entrySet().stream()
399 .collect(Collectors.toMap(Entry::getKey, e -> new PropertyData(e.getValue(), null)));
401 // add other properties
402 return addPropertiesToElementType(nodeType, uniqueId, reallyNewProperties, unchangedPropsData);
406 * @param newProperties
407 * @param oldProperties
410 private Map<String, PropertyDefinition> collectReallyNewProperties(Map<String, PropertyDefinition> newProperties,
411 Map<String, PropertyDefinition> oldProperties) {
412 return newProperties != null ? newProperties.entrySet().stream().filter(entry -> !oldProperties.containsKey(entry.getKey()))
413 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)) : null;
420 private JanusGraphOperationStatus updateOldProperty(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
421 if (!isUpdateAllowed(newPropDef, oldPropDef)) {
422 return JanusGraphOperationStatus.MATCH_NOT_FOUND;
424 if (isUpdateRequired(newPropDef, oldPropDef)) {
425 modifyOldPropByNewOne(newPropDef, oldPropDef);
426 List<PropertyConstraint> constraints = oldPropDef.getConstraints();
427 PropertyData node = new PropertyData(oldPropDef, convertConstraintsToString(constraints));
428 Either<PropertyData, JanusGraphOperationStatus> updateResult = janusGraphGenericDao.updateNode(node, PropertyData.class);
429 if (updateResult.isRight()) {
430 return updateResult.right().value();
433 return JanusGraphOperationStatus.OK;
440 private boolean isUpdateAllowed(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
441 if (newPropDef == null) {
442 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to delete the property with id {}", oldPropDef.getUniqueId());
445 // If the property type is missing it's something that we could want to fix
446 if (oldPropDef.getType() != null && !oldPropDef.getType().equals(newPropDef.getType())) {
447 log.error("#mergePropertiesAssociatedToNode - Failed due attempt to change type of the property with id {}", oldPropDef.getUniqueId());
454 * Update only fields which modification is permitted.
459 private void modifyOldPropByNewOne(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
460 oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
461 oldPropDef.setDescription(newPropDef.getDescription());
462 oldPropDef.setRequired(newPropDef.isRequired());
463 // Type is updated to fix possible null type issue in janusGraph DB
464 oldPropDef.setType(newPropDef.getType());
467 private boolean isUpdateRequired(PropertyDefinition newPropDef, PropertyDefinition oldPropDef) {
468 return !StringUtils.equals(oldPropDef.getDefaultValue(), newPropDef.getDefaultValue()) || !StringUtils
469 .equals(oldPropDef.getDescription(), newPropDef.getDescription()) || oldPropDef.isRequired() != newPropDef.isRequired();
473 * Adds newProperties and returns in case of success (left part of Either) map of all properties i. e. added ones and contained in
478 * @param newProperties
479 * @param unchangedPropsData
482 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(NodeTypeEnum nodeType, String uniqueId,
483 Map<String, PropertyDefinition> newProperties,
484 Map<String, PropertyData> unchangedPropsData) {
485 return addPropertiesToElementType(uniqueId, nodeType, newProperties).left().map(m -> {
486 m.putAll(unchangedPropsData);
491 public Either<Map<String, PropertyDefinition>, StorageOperationStatus> deleteAllPropertiesAssociatedToNode(NodeTypeEnum nodeType,
493 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesOfNodeRes = findPropertiesOfNode(nodeType, uniqueId);
494 if (propertiesOfNodeRes.isRight()) {
495 JanusGraphOperationStatus status = propertiesOfNodeRes.right().value();
496 if (status == JanusGraphOperationStatus.NOT_FOUND) {
497 return Either.right(StorageOperationStatus.OK);
499 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
501 Map<String, PropertyDefinition> value = propertiesOfNodeRes.left().value();
502 for (PropertyDefinition propertyDefinition : value.values()) {
503 String propertyUid = propertyDefinition.getUniqueId();
504 Either<PropertyData, JanusGraphOperationStatus> deletePropertyRes = deletePropertyFromGraph(propertyUid);
505 if (deletePropertyRes.isRight()) {
506 log.error("Failed to delete property with id {}", propertyUid);
507 JanusGraphOperationStatus status = deletePropertyRes.right().value();
508 if (status == JanusGraphOperationStatus.NOT_FOUND) {
509 status = JanusGraphOperationStatus.INVALID_ID;
511 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
514 log.debug("The properties deleted from node {} are {}", uniqueId, value);
515 return Either.left(value);
519 * Checks existence of a property with the same name belonging to the same resource or existence of property with the same name and different type
520 * (including derived from hierarchy)
524 * @param propertyName
525 * @param propertyType
528 public boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
529 boolean result = false;
530 if (!CollectionUtils.isEmpty(properties)) {
531 for (PropertyDefinition propertyDefinition : properties) {
532 if (propertyDefinition.getName().equals(propertyName) && (propertyDefinition.getParentUniqueId().equals(resourceUid)
533 || !propertyDefinition.getType().equals(propertyType))) {
542 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType,
543 Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
544 if (rules == null || rules.isEmpty()) {
545 return new ImmutablePair<>(null, true);
547 for (PropertyRule rule : rules) {
548 String value = rule.getValue();
549 Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
550 if (updateResult.isRight()) {
551 Boolean status = updateResult.right().value();
553 return new ImmutablePair<>(value, status);
556 String newValue = null;
557 Object object = updateResult.left().value();
558 if (object != null) {
559 newValue = object.toString();
561 rule.setValue(newValue);
564 return new ImmutablePair<>(null, true);
567 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
568 String resourceInstanceId) {
569 List<PropertyRule> rules = resourceInstanceProperty.getRules();
571 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
572 rules = new ArrayList<>();
573 rules.add(propertyRule);
575 rules = sortRules(rules);
577 propertyValueData.setRules(rules);
580 private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
581 String resourceInstanceId) {
582 List<String> path = resourceInstanceProperty.getPath();
583 // FOR BC. Since old Property values on VFC/VF does not have rules on
587 // Update could be done on one level only, thus we can use this
589 // operation to avoid migration.
590 if (path == null || path.isEmpty()) {
591 path = new ArrayList<>();
592 path.add(resourceInstanceId);
594 PropertyRule propertyRule = new PropertyRule();
595 propertyRule.setRule(path);
596 propertyRule.setValue(propertyValueData.getValue());
600 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
601 // TODO: sort the rules by size and binary representation.
603 // (x, y, .+) --> 110 6 priority 1
605 // (x, .+, z) --> 101 5 priority 2
609 public ImmutablePair<JanusGraphOperationStatus, String> findPropertyValue(String resourceInstanceId, String propertyId) {
610 log.debug("Going to check whether the property {} already added to resource instance {}", propertyId, resourceInstanceId);
611 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllRes = this
612 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceId);
613 if (getAllRes.isRight()) {
614 JanusGraphOperationStatus status = getAllRes.right().value();
615 log.trace("After fetching all properties of resource instance {}. Status is {}", resourceInstanceId, status);
616 return new ImmutablePair<>(status, null);
618 List<ComponentInstanceProperty> list = getAllRes.left().value();
620 for (ComponentInstanceProperty instanceProperty : list) {
621 String propertyUniqueId = instanceProperty.getUniqueId();
622 String valueUniqueUid = instanceProperty.getValueUniqueUid();
623 log.trace("Go over property {} under resource instance {}. valueUniqueId = {}", propertyUniqueId, resourceInstanceId, valueUniqueUid);
624 if (propertyId.equals(propertyUniqueId) && valueUniqueUid != null) {
625 log.debug("The property {} already created under resource instance {}", propertyId, resourceInstanceId);
626 return new ImmutablePair<>(JanusGraphOperationStatus.ALREADY_EXIST, valueUniqueUid);
630 return new ImmutablePair<>(JanusGraphOperationStatus.NOT_FOUND, null);
633 public void updateRulesInPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty,
634 String resourceInstanceId) {
635 List<PropertyRule> currentRules = propertyValueData.getRules();
636 List<PropertyRule> rules = resourceInstanceProperty.getRules();
637 // if rules are not supported.
639 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
640 rules = new ArrayList<>();
641 rules.add(propertyRule);
642 if (currentRules != null) {
643 rules = mergeRules(currentRules, rules);
646 // Full mode. all rules are sent in update operation.
647 rules = sortRules(rules);
649 propertyValueData.setRules(rules);
652 private List<PropertyRule> mergeRules(List<PropertyRule> currentRules, List<PropertyRule> newRules) {
653 List<PropertyRule> mergedRules = new ArrayList<>();
654 if (newRules == null || newRules.isEmpty()) {
657 for (PropertyRule rule : currentRules) {
658 PropertyRule propertyRule = new PropertyRule(rule.getRule(), rule.getValue());
659 mergedRules.add(propertyRule);
661 for (PropertyRule rule : newRules) {
662 PropertyRule foundRule = findRuleInList(rule, mergedRules);
663 if (foundRule != null) {
664 foundRule.setValue(rule.getValue());
666 mergedRules.add(rule);
672 private PropertyRule findRuleInList(PropertyRule rule, List<PropertyRule> rules) {
673 if (rules == null || rules.isEmpty() || rule.getRule() == null || rule.getRule().isEmpty()) {
676 PropertyRule foundRule = null;
677 for (PropertyRule propertyRule : rules) {
678 if (rule.getRuleSize() != propertyRule.getRuleSize()) {
681 boolean equals = propertyRule.compareRule(rule);
683 foundRule = propertyRule;
691 * return all properties associated to resource instance. The result does contains the property unique id but not its type, default value...
693 * @param resourceInstanceUid
696 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
697 String resourceInstanceUid) {
698 return getAllPropertiesOfResourceInstanceOnlyPropertyDefId(resourceInstanceUid, NodeTypeEnum.ResourceInstance);
701 public Either<PropertyValueData, JanusGraphOperationStatus> removePropertyOfResourceInstance(String propertyValueUid, String resourceInstanceId) {
702 Either<ComponentInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
703 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceInstance), resourceInstanceId, ComponentInstanceData.class);
704 if (findResInstanceRes.isRight()) {
705 JanusGraphOperationStatus status = findResInstanceRes.right().value();
706 if (status == JanusGraphOperationStatus.NOT_FOUND) {
707 status = JanusGraphOperationStatus.INVALID_ID;
709 return Either.right(status);
711 Either<PropertyValueData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
712 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueUid, PropertyValueData.class);
713 if (findPropertyDefRes.isRight()) {
714 JanusGraphOperationStatus status = findPropertyDefRes.right().value();
715 if (status == JanusGraphOperationStatus.NOT_FOUND) {
716 status = JanusGraphOperationStatus.INVALID_ID;
718 return Either.right(status);
720 Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
721 .getRelation(findResInstanceRes.left().value(), findPropertyDefRes.left().value(), GraphEdgeLabels.PROPERTY_VALUE);
722 if (relation.isRight()) {
723 // TODO: add error in case of error
724 JanusGraphOperationStatus status = relation.right().value();
725 if (status == JanusGraphOperationStatus.NOT_FOUND) {
726 status = JanusGraphOperationStatus.INVALID_ID;
728 return Either.right(status);
730 Either<PropertyValueData, JanusGraphOperationStatus> deleteNode = janusGraphGenericDao
731 .deleteNode(findPropertyDefRes.left().value(), PropertyValueData.class);
732 if (deleteNode.isRight()) {
733 return Either.right(deleteNode.right().value());
735 PropertyValueData value = deleteNode.left().value();
736 return Either.left(value);
739 public Either<ComponentInstanceProperty, StorageOperationStatus> removePropertyValueFromResourceInstance(String propertyValueUid,
740 String resourceInstanceId,
741 boolean inTransaction) {
742 Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
744 Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = this
745 .removePropertyOfResourceInstance(propertyValueUid, resourceInstanceId);
746 if (eitherStatus.isRight()) {
747 log.error("Failed to remove property value {} from resource instance {} in Graph. status is {}", propertyValueUid, resourceInstanceId,
748 eitherStatus.right().value().name());
749 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
752 PropertyValueData propertyValueData = eitherStatus.left().value();
753 ComponentInstanceProperty propertyValueResult = new ComponentInstanceProperty();
754 propertyValueResult.setUniqueId(resourceInstanceId);
755 propertyValueResult.setValue(propertyValueData.getValue());
756 log.debug("The returned ResourceInstanceProperty is {}", propertyValueResult);
757 result = Either.left(propertyValueResult);
761 if (!inTransaction) {
762 if (result == null || result.isRight()) {
763 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
764 janusGraphGenericDao.rollback();
766 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
767 janusGraphGenericDao.commit();
773 public ComponentInstanceProperty buildResourceInstanceProperty(PropertyValueData propertyValueData,
774 ComponentInstanceProperty resourceInstanceProperty) {
775 String value = propertyValueData.getValue();
776 String uid = propertyValueData.getUniqueId();
777 ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(resourceInstanceProperty, value, uid);
778 instanceProperty.setPath(resourceInstanceProperty.getPath());
779 return instanceProperty;
783 public boolean isPropertyDefaultValueValid(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) {
784 if (propertyDefinition == null) {
787 String innerType = null;
788 String propertyType = propertyDefinition.getType();
789 ToscaPropertyType type = getType(propertyType);
790 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
791 SchemaDefinition def = propertyDefinition.getSchema();
795 PropertyDataDefinition propDef = def.getProperty();
796 if (propDef == null) {
799 innerType = propDef.getType();
801 String value = propertyDefinition.getDefaultValue();
803 return isValidValue(type, value, innerType, dataTypes);
805 log.trace("The given type {} is not a pre defined one.", propertyType);
806 DataTypeDefinition foundDt = dataTypes.get(propertyType);
807 if (foundDt != null) {
808 return isValidComplexValue(foundDt, value, dataTypes);
815 public boolean isPropertyTypeValid(final IComplexDefaultValue property, final String model) {
816 if (property == null) {
819 if (ToscaPropertyType.isValidType(property.getType()) == null) {
820 Either<Boolean, JanusGraphOperationStatus> definedInDataTypes = isDefinedInDataTypes(property.getType(), model);
821 if (definedInDataTypes.isRight()) {
824 Boolean isExist = definedInDataTypes.left().value();
825 return isExist.booleanValue();
832 public ImmutablePair<String, Boolean> isPropertyInnerTypeValid(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
833 if (property == null) {
834 return new ImmutablePair<>(null, false);
836 SchemaDefinition schema;
837 PropertyDataDefinition innerProp;
838 String innerType = null;
839 if ((schema = property.getSchema()) != null) {
840 if ((innerProp = schema.getProperty()) != null) {
841 innerType = innerProp.getType();
844 ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
845 if (innerToscaType == null) {
846 DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType);
847 if (dataTypeDefinition == null) {
848 log.debug("The inner type {} is not a data type.", innerType);
849 return new ImmutablePair<>(innerType, false);
851 log.debug("The inner type {} is a data type. Data type definition is {}", innerType, dataTypeDefinition);
854 return new ImmutablePair<>(innerType, true);
857 private boolean isValidComplexValue(DataTypeDefinition foundDt, String value, Map<String, DataTypeDefinition> dataTypes) {
858 ImmutablePair<JsonElement, Boolean> validateAndUpdate = dataTypeValidatorConverter.validateAndUpdate(value, foundDt, dataTypes);
859 log.trace("The result after validating complex value of type {} is {}", foundDt.getName(), validateAndUpdate);
860 return validateAndUpdate.right.booleanValue();
863 public Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getAllPropertiesOfResourceInstanceOnlyPropertyDefId(
864 String resourceInstanceUid, NodeTypeEnum instanceNodeType) {
865 Either<JanusGraphVertex, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
866 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid);
867 if (findResInstanceRes.isRight()) {
868 JanusGraphOperationStatus status = findResInstanceRes.right().value();
869 if (status == JanusGraphOperationStatus.NOT_FOUND) {
870 status = JanusGraphOperationStatus.INVALID_ID;
872 return Either.right(status);
874 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> propertyImplNodes = janusGraphGenericDao
875 .getChildrenVertecies(UniqueIdBuilder.getKeyByNodeType(instanceNodeType), resourceInstanceUid, GraphEdgeLabels.PROPERTY_VALUE);
876 if (propertyImplNodes.isRight()) {
877 JanusGraphOperationStatus status = propertyImplNodes.right().value();
878 return Either.right(status);
880 List<ImmutablePair<JanusGraphVertex, Edge>> list = propertyImplNodes.left().value();
881 if (list == null || list.isEmpty()) {
882 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
884 List<ComponentInstanceProperty> result = new ArrayList<>();
885 for (ImmutablePair<JanusGraphVertex, Edge> propertyValue : list) {
886 JanusGraphVertex propertyValueDataVertex = propertyValue.getLeft();
887 String propertyValueUid = (String) janusGraphGenericDao
888 .getProperty(propertyValueDataVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
889 String value = (String) janusGraphGenericDao.getProperty(propertyValueDataVertex, GraphPropertiesDictionary.VALUE.getProperty());
890 ImmutablePair<JanusGraphVertex, Edge> propertyDefPair = janusGraphGenericDao
891 .getChildVertex(propertyValueDataVertex, GraphEdgeLabels.PROPERTY_IMPL);
892 if (propertyDefPair == null) {
893 return Either.right(JanusGraphOperationStatus.NOT_FOUND);
895 Map<String, Object> properties = janusGraphGenericDao.getProperties(propertyValueDataVertex);
896 PropertyValueData propertyValueData = GraphElementFactory
897 .createElement(NodeTypeEnum.PropertyValue.getName(), GraphElementTypeEnum.Node, properties, PropertyValueData.class);
898 String propertyUniqueId = (String) janusGraphGenericDao
899 .getProperty(propertyDefPair.left, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
900 ComponentInstanceProperty resourceInstanceProperty = new ComponentInstanceProperty();
901 // set property original unique id
902 resourceInstanceProperty.setUniqueId(propertyUniqueId);
905 // TODO: esofer add resource id
906 resourceInstanceProperty.setParentUniqueId(null);
908 resourceInstanceProperty.setValue(value);
909 // set property value unique id
910 resourceInstanceProperty.setValueUniqueUid(propertyValueUid);
912 resourceInstanceProperty.setRules(propertyValueData.getRules());
913 result.add(resourceInstanceProperty);
915 return Either.left(result);
919 * Find the default value from the list of component instances. Start the search from the second component instance
921 * @param pathOfComponentInstances
922 * @param propertyUniqueId
923 * @param defaultValue
926 public Either<String, JanusGraphOperationStatus> findDefaultValueFromSecondPosition(List<String> pathOfComponentInstances,
927 String propertyUniqueId, String defaultValue) {
928 log.trace("In find default value: path= {} propertyUniqId={} defaultValue= {}", pathOfComponentInstances, propertyUniqueId, defaultValue);
929 if (pathOfComponentInstances == null || pathOfComponentInstances.size() < 2) {
930 return Either.left(defaultValue);
932 String result = defaultValue;
933 for (int i = 1; i < pathOfComponentInstances.size(); i++) {
934 String compInstanceId = pathOfComponentInstances.get(i);
935 Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> propertyValuesResult = this
936 .getAllPropertiesOfResourceInstanceOnlyPropertyDefId(compInstanceId, NodeTypeEnum.ResourceInstance);
937 log.trace("After fetching properties values of component instance {}. {}", compInstanceId, propertyValuesResult);
938 if (propertyValuesResult.isRight()) {
939 JanusGraphOperationStatus status = propertyValuesResult.right().value();
940 if (status != JanusGraphOperationStatus.NOT_FOUND) {
941 return Either.right(status);
946 ComponentInstanceProperty foundCompInstanceProperty = fetchByPropertyUid(propertyValuesResult.left().value(), propertyUniqueId);
947 log.trace("After finding the component instance property on{} . {}", compInstanceId, foundCompInstanceProperty);
948 if (foundCompInstanceProperty == null) {
951 List<PropertyRule> rules = getOrBuildRulesIfNotExists(pathOfComponentInstances.size() - i, pathOfComponentInstances.get(i),
952 foundCompInstanceProperty.getRules(), foundCompInstanceProperty.getValue());
953 log.trace("Rules of property {} on component instance {} are {}", propertyUniqueId, compInstanceId, rules);
954 PropertyRule matchedRule = findMatchRule(pathOfComponentInstances, i, rules);
955 log.trace("Match rule is {}", matchedRule);
956 if (matchedRule != null) {
957 result = matchedRule.getValue();
961 return Either.left(result);
964 private ComponentInstanceProperty fetchByPropertyUid(List<ComponentInstanceProperty> list, String propertyUniqueId) {
965 ComponentInstanceProperty result = null;
969 for (ComponentInstanceProperty instProperty : list) {
970 if (instProperty.getUniqueId().equals(propertyUniqueId)) {
971 result = instProperty;
978 private List<PropertyRule> getOrBuildRulesIfNotExists(int ruleSize, String compInstanceId, List<PropertyRule> rules, String value) {
982 rules = buildDefaultRule(compInstanceId, ruleSize, value);
986 private List<PropertyRule> getRulesOfPropertyValue(int size, String instanceId, ComponentInstanceProperty componentInstanceProperty) {
987 List<PropertyRule> rules = componentInstanceProperty.getRules();
989 rules = buildDefaultRule(instanceId, size, componentInstanceProperty.getValue());
994 private List<PropertyRule> buildDefaultRule(String componentInstanceId, int size, String value) {
995 List<PropertyRule> rules = new ArrayList<>();
996 List<String> rule = new ArrayList<>();
997 rule.add(componentInstanceId);
998 for (int i = 0; i < size - 1; i++) {
999 rule.add(PropertyRule.getRuleAnyMatch());
1001 PropertyRule propertyRule = new PropertyRule(rule, value);
1002 rules.add(propertyRule);
1006 private PropertyRule findMatchRule(List<String> pathOfInstances, int level, List<PropertyRule> rules) {
1007 PropertyRule propertyRule = null;
1008 String stringForMatch = buildStringForMatch(pathOfInstances, level);
1009 String firstCompInstance = pathOfInstances.get(level);
1010 if (rules != null) {
1011 for (PropertyRule rule : rules) {
1012 int ruleSize = rule.getRule().size();
1013 // check the length of the rule equals to the length of the
1016 if (ruleSize != pathOfInstances.size() - level) {
1019 // check that the rule starts with correct component instance id
1020 if (!checkFirstItem(firstCompInstance, rule.getFirstToken())) {
1023 String secondToken = rule.getToken(2);
1024 if (secondToken != null && (secondToken.equals(PropertyRule.getForceAll()) || secondToken.equals(PropertyRule.getALL()))) {
1025 propertyRule = rule;
1028 String patternStr = buildStringForMatch(rule.getRule(), 0);
1029 Pattern pattern = Pattern.compile(patternStr);
1030 Matcher matcher = pattern.matcher(stringForMatch);
1031 if (matcher.matches()) {
1032 if (log.isTraceEnabled()) {
1033 log.trace("{} matches the rule {}", stringForMatch, patternStr);
1035 propertyRule = rule;
1040 return propertyRule;
1043 private boolean checkFirstItem(String left, String right) {
1044 if (left != null && left.equals(right)) {
1050 private String buildStringForMatch(List<String> pathOfInstances, int level) {
1051 StringBuilder builder = new StringBuilder();
1052 for (int i = level; i < pathOfInstances.size(); i++) {
1053 builder.append(pathOfInstances.get(i));
1054 if (i < pathOfInstances.size() - 1) {
1055 builder.append("#");
1058 return builder.toString();
1061 public void updatePropertyByBestMatch(String propertyUniqueId, ComponentInstanceProperty instanceProperty,
1062 Map<String, ComponentInstanceProperty> instanceIdToValue) {
1063 List<String> pathOfInstances = instanceProperty.getPath();
1065 int size = pathOfInstances.size();
1066 int numberOfMatches = 0;
1067 for (String instanceId : pathOfInstances) {
1068 ComponentInstanceProperty componentInstanceProperty = instanceIdToValue.get(instanceId);
1069 if (componentInstanceProperty != null) {
1070 List<PropertyRule> rules = getRulesOfPropertyValue(size - level, instanceId, componentInstanceProperty);
1071 // If it is the first level instance, then update valueUniuqeId
1073 // parameter in order to know on update that
1075 // we should update and not create new node on graph.
1077 instanceProperty.setValueUniqueUid(componentInstanceProperty.getValueUniqueUid());
1078 instanceProperty.setRules(rules);
1080 PropertyRule rule = findMatchRule(pathOfInstances, level, rules);
1083 String value = rule.getValue();
1084 if (numberOfMatches == 1) {
1085 instanceProperty.setValue(value);
1086 if (log.isDebugEnabled()) {
1087 log.debug("Set the value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1088 pathOfInstances, value);
1090 } else if (numberOfMatches == 2) {
1091 // In case of another property value match, then use the
1093 // value to be the default value of the property.
1094 instanceProperty.setDefaultValue(value);
1095 if (log.isDebugEnabled()) {
1096 log.debug("Set the default value of property {} {} on path {} to be {}", propertyUniqueId, instanceProperty.getName(),
1097 pathOfInstances, value);
1108 * Add data type to graph.
1110 * 1. Add data type node
1112 * 2. Add edge between the former node to its parent(if exists)
1114 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
1116 * @param dataTypeDefinition
1119 private Either<DataTypeData, JanusGraphOperationStatus> addDataTypeToGraph(DataTypeDefinition dataTypeDefinition) {
1120 log.debug("Got data type {}", dataTypeDefinition);
1121 String dtUniqueId = UniqueIdBuilder.buildDataTypeUid(dataTypeDefinition.getModel(), dataTypeDefinition.getName());
1122 DataTypeData dataTypeData = buildDataTypeData(dataTypeDefinition, dtUniqueId);
1123 log.debug("Before adding data type to graph. dataTypeData = {}", dataTypeData);
1124 Either<DataTypeData, JanusGraphOperationStatus> createDataTypeResult = janusGraphGenericDao.createNode(dataTypeData, DataTypeData.class);
1125 log.debug("After adding data type to graph. status is = {}", createDataTypeResult);
1126 if (createDataTypeResult.isRight()) {
1127 JanusGraphOperationStatus operationStatus = createDataTypeResult.right().value();
1128 log.debug("Failed to data type {} to graph. status is {}", dataTypeDefinition.getName(), operationStatus);
1129 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", NodeTypeEnum.DataType.getName());
1130 return Either.right(operationStatus);
1132 DataTypeData resultCTD = createDataTypeResult.left().value();
1133 List<PropertyDefinition> properties = dataTypeDefinition.getProperties();
1134 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(resultCTD.getUniqueId(), dataTypeDefinition.getModel(),
1136 if (addPropertiesToDataType.isRight()) {
1137 log.debug("Failed add properties {} to data type {}", properties, dataTypeDefinition.getName());
1138 return Either.right(addPropertiesToDataType.right().value());
1141 final Either<GraphRelation, JanusGraphOperationStatus> modelRelationship = addDataTypeToModel(dataTypeDefinition);
1142 if (modelRelationship.isRight()) {
1143 return Either.right(modelRelationship.right().value());
1146 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1147 if (derivedFrom != null) {
1148 final Either<DataTypeDefinition, JanusGraphOperationStatus> derivedFromDataType = getDataTypeByNameValidForModel(derivedFrom, dataTypeDefinition.getModel());
1149 if (derivedFromDataType.isRight()) {
1150 return Either.right(derivedFromDataType.right().value());
1153 log.debug("Before creating relation between data type {} to its parent {}", dtUniqueId, derivedFrom);
1154 UniqueIdData from = new UniqueIdData(NodeTypeEnum.DataType, dtUniqueId);
1155 final String deriveFromUid = derivedFromDataType.left().value().getUniqueId();
1156 UniqueIdData to = new UniqueIdData(NodeTypeEnum.DataType, deriveFromUid);
1157 Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
1158 .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
1159 log.debug("After create relation between capability type {} to its parent {}. status is {}", dtUniqueId, derivedFrom, createRelation);
1160 if (createRelation.isRight()) {
1161 return Either.right(createRelation.right().value());
1164 return Either.left(createDataTypeResult.left().value());
1167 private Either<GraphRelation, JanusGraphOperationStatus> addDataTypeToModel(final DataTypeDefinition dataTypeDefinition) {
1168 final String model = dataTypeDefinition.getModel();
1169 if (model == null) {
1170 return Either.left(null);
1172 final GraphNode from = new UniqueIdData(NodeTypeEnum.Model, UniqueIdBuilder.buildModelUid(model));
1173 final GraphNode to = new UniqueIdData(NodeTypeEnum.DataType, dataTypeDefinition.getUniqueId());
1174 log.info("Connecting model {} to type {}", from, to);
1175 return janusGraphGenericDao.createRelation(from , to, GraphEdgeLabels.MODEL_ELEMENT, Collections.emptyMap());
1178 private DataTypeData buildDataTypeData(DataTypeDefinition dataTypeDefinition, String ctUniqueId) {
1179 DataTypeData dataTypeData = new DataTypeData(dataTypeDefinition);
1180 dataTypeData.getDataTypeDataDefinition().setUniqueId(ctUniqueId);
1181 Long creationDate = dataTypeData.getDataTypeDataDefinition().getCreationTime();
1182 if (creationDate == null) {
1183 creationDate = System.currentTimeMillis();
1185 dataTypeData.getDataTypeDataDefinition().setCreationTime(creationDate);
1186 dataTypeData.getDataTypeDataDefinition().setModificationTime(creationDate);
1187 return dataTypeData;
1191 * add properties to capability type.
1193 * Per property, add a property node and associate it to the capability type
1199 private Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType(final String uniqueId, final String modelName,
1200 final List<PropertyDefinition> properties) {
1201 Map<String, PropertyData> propertiesData = new HashMap<>();
1202 if (properties != null && !properties.isEmpty()) {
1203 for (PropertyDefinition propertyDefinition : properties) {
1204 String propertyName = propertyDefinition.getName();
1205 String propertyType = propertyDefinition.getType();
1206 Either<Boolean, JanusGraphOperationStatus> validPropertyType = isValidPropertyType(propertyType, modelName);
1207 if (validPropertyType.isRight()) {
1208 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1209 return Either.right(validPropertyType.right().value());
1211 Boolean isValid = validPropertyType.left().value();
1212 if (isValid == null || !isValid.booleanValue()) {
1213 log.debug("Data type {} contains invalid property type {}", uniqueId, propertyType);
1214 return Either.right(JanusGraphOperationStatus.INVALID_TYPE);
1216 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1217 .addPropertyToNodeType(propertyName, propertyDefinition, NodeTypeEnum.DataType, uniqueId);
1218 if (addPropertyToNodeType.isRight()) {
1219 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1220 log.debug("Failed to associate data type {} to property {} in graph. status is {}", uniqueId, propertyName, operationStatus);
1221 BeEcompErrorManager.getInstance()
1222 .logInternalFlowError("AddPropertyToDataType", "Failed to associate property to data type. Status is " + operationStatus,
1223 ErrorSeverity.ERROR);
1224 return Either.right(operationStatus);
1226 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1228 DataTypeData dataTypeData = new DataTypeData();
1229 dataTypeData.getDataTypeDataDefinition().setUniqueId(uniqueId);
1230 long modificationTime = System.currentTimeMillis();
1231 dataTypeData.getDataTypeDataDefinition().setModificationTime(modificationTime);
1232 Either<DataTypeData, JanusGraphOperationStatus> updateNode = janusGraphGenericDao.updateNode(dataTypeData, DataTypeData.class);
1233 if (updateNode.isRight()) {
1234 JanusGraphOperationStatus operationStatus = updateNode.right().value();
1235 log.debug("Failed to update modification time data type {} from graph. status is {}", uniqueId, operationStatus);
1236 BeEcompErrorManager.getInstance()
1237 .logInternalFlowError("AddPropertyToDataType", "Failed to fetch data type. Status is " + operationStatus, ErrorSeverity.ERROR);
1238 return Either.right(operationStatus);
1240 log.debug("Update data type uid {}. Set modification time to {}", uniqueId, modificationTime);
1243 return Either.left(propertiesData);
1246 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByNameValidForModel(final String name, final String modelName) {
1247 final Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1248 .getNode(GraphPropertiesDictionary.NAME.getProperty(), name, DataTypeData.class, modelName);
1249 if (dataTypesRes.isRight()) {
1250 final JanusGraphOperationStatus status = dataTypesRes.right().value();
1251 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, name, status);
1252 return Either.right(status);
1254 final DataTypeData dataType = dataTypesRes.left().value();
1255 final DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(dataType.getDataTypeDataDefinition());
1256 final JanusGraphOperationStatus propertiesStatus = fillProperties(dataTypeDefinition.getUniqueId(), dataTypeDefinition);
1257 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1258 log.error(BUSINESS_PROCESS_ERROR, FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, dataTypeDefinition.getUniqueId());
1259 return Either.right(propertiesStatus);
1261 final Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1262 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeDefinition.getUniqueId(), GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1263 DataTypeData.class);
1264 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, dataTypeDefinition.getUniqueId(), parentNode);
1265 if (parentNode.isRight()) {
1266 final JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1267 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1268 log.error(BUSINESS_PROCESS_ERROR, "Failed to find the parent data type of data type {}. status is {}", dataTypeDefinition.getUniqueId(), janusGraphOperationStatus);
1269 return Either.right(janusGraphOperationStatus);
1272 // derived from node was found
1273 final ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1274 final DataTypeData parentDataType = immutablePair.getKey();
1275 final Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentDataType.getUniqueId());
1276 if (dataTypeByUid.isRight()) {
1277 return Either.right(dataTypeByUid.right().value());
1279 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1280 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1282 return Either.left(dataTypeDefinition);
1286 * Build Data type object from graph by unique id
1291 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUid(String uniqueId) {
1292 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1293 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1294 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1295 if (dataTypesRes.isRight()) {
1296 JanusGraphOperationStatus status = dataTypesRes.right().value();
1297 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1298 return Either.right(status);
1300 DataTypeData ctData = dataTypesRes.left().value();
1301 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1302 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1303 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1304 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1305 return Either.right(propertiesStatus);
1307 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1308 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1309 DataTypeData.class);
1310 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1311 if (parentNode.isRight()) {
1312 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1313 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1314 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1315 result = Either.right(janusGraphOperationStatus);
1319 // derived from node was found
1320 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1321 DataTypeData parentCT = immutablePair.getKey();
1322 String parentUniqueId = parentCT.getUniqueId();
1323 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1324 if (dataTypeByUid.isRight()) {
1325 return Either.right(dataTypeByUid.right().value());
1327 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1328 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1330 result = Either.left(dataTypeDefinition);
1334 private JanusGraphOperationStatus fillProperties(String uniqueId, DataTypeDefinition dataTypeDefinition) {
1335 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this
1336 .findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
1337 if (findPropertiesOfNode.isRight()) {
1338 JanusGraphOperationStatus janusGraphOperationStatus = findPropertiesOfNode.right().value();
1339 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, janusGraphOperationStatus);
1340 if (JanusGraphOperationStatus.NOT_FOUND.equals(janusGraphOperationStatus)) {
1341 return JanusGraphOperationStatus.OK;
1343 return janusGraphOperationStatus;
1346 Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
1347 if (properties != null && !properties.isEmpty()) {
1348 List<PropertyDefinition> listOfProps = new ArrayList<>();
1349 for (Entry<String, PropertyDefinition> entry : properties.entrySet()) {
1350 String propName = entry.getKey();
1351 PropertyDefinition propertyDefinition = entry.getValue();
1352 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
1353 newPropertyDefinition.setName(propName);
1354 listOfProps.add(newPropertyDefinition);
1356 dataTypeDefinition.setProperties(listOfProps);
1358 return JanusGraphOperationStatus.OK;
1362 private Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition, boolean inTransaction) {
1363 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1365 Either<DataTypeData, JanusGraphOperationStatus> eitherStatus = addDataTypeToGraph(dataTypeDefinition);
1366 if (eitherStatus.isRight()) {
1367 log.debug("Failed to add data type {} to Graph. status is {}", dataTypeDefinition, eitherStatus.right().value().name());
1368 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("AddDataType", "DataType");
1369 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
1372 DataTypeData capabilityTypeData = eitherStatus.left().value();
1373 DataTypeDefinition dataTypeDefResult = convertDTDataToDTDefinition(capabilityTypeData);
1374 log.debug("The returned CapabilityTypeDefinition is {}", dataTypeDefResult);
1375 result = Either.left(dataTypeDefResult);
1379 if (!inTransaction) {
1380 if (result == null || result.isRight()) {
1381 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1382 janusGraphGenericDao.rollback();
1384 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1385 janusGraphGenericDao.commit();
1392 public Either<DataTypeDefinition, StorageOperationStatus> addDataType(DataTypeDefinition dataTypeDefinition) {
1393 return addDataType(dataTypeDefinition, true);
1397 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel, final boolean inTransaction) {
1398 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1400 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByNameValidForModel(name, validForModel);
1401 if (ctResult.isRight()) {
1402 JanusGraphOperationStatus status = ctResult.right().value();
1403 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1404 log.error("Failed to retrieve information on capability type {} status is {}", name, status);
1406 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1409 result = Either.left(ctResult.left().value());
1412 if (!inTransaction) {
1413 if (result == null || result.isRight()) {
1414 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1415 janusGraphGenericDao.rollback();
1417 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1418 janusGraphGenericDao.commit();
1425 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByName(final String name, final String validForModel) {
1426 return getDataTypeByName(name, validForModel, true);
1429 public Either<DataTypeDefinition, StorageOperationStatus> getDataTypeByUidWithoutDerived(String uid, boolean inTransaction) {
1430 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1432 Either<DataTypeDefinition, JanusGraphOperationStatus> ctResult = this.getDataTypeByUidWithoutDerivedDataTypes(uid);
1433 if (ctResult.isRight()) {
1434 JanusGraphOperationStatus status = ctResult.right().value();
1435 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1436 log.error(BUSINESS_PROCESS_ERROR, "Failed to retrieve information on data type {} status is {}", uid, status);
1438 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
1441 result = Either.left(ctResult.left().value());
1444 if (!inTransaction) {
1445 if (result == null || result.isRight()) {
1446 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1447 janusGraphGenericDao.rollback();
1449 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1450 janusGraphGenericDao.commit();
1456 public Either<DataTypeDefinition, JanusGraphOperationStatus> getDataTypeByUidWithoutDerivedDataTypes(String uniqueId) {
1457 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1458 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1459 if (dataTypesRes.isRight()) {
1460 JanusGraphOperationStatus status = dataTypesRes.right().value();
1461 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1462 return Either.right(status);
1464 DataTypeData ctData = dataTypesRes.left().value();
1465 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1466 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1467 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1468 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1469 return Either.right(propertiesStatus);
1471 return Either.left(dataTypeDefinition);
1475 * convert between graph Node object to Java object
1477 * @param dataTypeData
1480 protected DataTypeDefinition convertDTDataToDTDefinition(DataTypeData dataTypeData) {
1481 log.debug("The object returned after create data type is {}", dataTypeData);
1482 return new DataTypeDefinition(dataTypeData.getDataTypeDataDefinition());
1485 private Either<Boolean, JanusGraphOperationStatus> isValidPropertyType(String propertyType, final String modelName) {
1486 if (propertyType == null || propertyType.isEmpty()) {
1487 return Either.left(false);
1489 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(propertyType);
1490 if (toscaPropertyType == null) {
1491 return isDefinedInDataTypes(propertyType, modelName);
1493 return Either.left(true);
1497 public Either<Boolean, JanusGraphOperationStatus> isDefinedInDataTypes(final String propertyType, final String modelName) {
1498 Either<DataTypeDefinition, JanusGraphOperationStatus> dataType = getDataTypeByNameValidForModel(propertyType, modelName);
1499 if (dataType.isRight()) {
1500 JanusGraphOperationStatus status = dataType.right().value();
1501 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1502 return Either.left(false);
1504 return Either.right(status);
1506 return Either.left(true);
1509 public Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> getAllDataTypes() {
1510 Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
1511 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> result = Either.left(dataTypes);
1512 Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypes = janusGraphGenericDao
1513 .getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
1514 if (getAllDataTypes.isRight()) {
1515 JanusGraphOperationStatus status = getAllDataTypes.right().value();
1516 if (status != JanusGraphOperationStatus.NOT_FOUND) {
1517 return Either.right(status);
1522 List<DataTypeData> list = getAllDataTypes.left().value();
1524 log.trace("Number of data types to load is {}", list.size());
1525 List<String> collect = list.stream().map(p -> p.getDataTypeDataDefinition().getName()).collect(Collectors.toList());
1526 log.trace("The data types to load are {}", collect);
1527 for (DataTypeData dataTypeData : list) {
1528 log.trace("Going to fetch data type {}. uid is {}", dataTypeData.getDataTypeDataDefinition().getName(), dataTypeData.getUniqueId());
1529 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this
1530 .getAndAddDataTypeByUid(dataTypeData.getUniqueId(), dataTypes);
1531 if (dataTypeByUid.isRight()) {
1532 JanusGraphOperationStatus status = dataTypeByUid.right().value();
1533 if (status == JanusGraphOperationStatus.NOT_FOUND) {
1534 status = JanusGraphOperationStatus.INVALID_ID;
1536 return Either.right(status);
1540 if (log.isTraceEnabled()) {
1541 if (result.isRight()) {
1542 log.trace("After fetching all data types {}", result);
1544 Map<String, DataTypeDefinition> map = result.left().value();
1546 String types = map.keySet().stream().collect(Collectors.joining(",", "[", "]"));
1547 log.trace("After fetching all data types {} ", types);
1555 * Build Data type object from graph by unique id
1560 private Either<DataTypeDefinition, JanusGraphOperationStatus> getAndAddDataTypeByUid(String uniqueId,
1561 Map<String, DataTypeDefinition> allDataTypes) {
1562 Either<DataTypeDefinition, JanusGraphOperationStatus> result = null;
1563 if (allDataTypes.containsKey(uniqueId)) {
1564 return Either.left(allDataTypes.get(uniqueId));
1566 Either<DataTypeData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
1567 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
1568 if (dataTypesRes.isRight()) {
1569 JanusGraphOperationStatus status = dataTypesRes.right().value();
1570 log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
1571 return Either.right(status);
1573 DataTypeData ctData = dataTypesRes.left().value();
1574 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(ctData.getDataTypeDataDefinition());
1575 JanusGraphOperationStatus propertiesStatus = fillProperties(uniqueId, dataTypeDefinition);
1576 if (propertiesStatus != JanusGraphOperationStatus.OK) {
1577 log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
1578 return Either.right(propertiesStatus);
1580 allDataTypes.put(dataTypeDefinition.getName(), dataTypeDefinition);
1581 String derivedFrom = dataTypeDefinition.getDerivedFromName();
1582 if (allDataTypes.containsKey(derivedFrom)) {
1583 DataTypeDefinition parentDataTypeDefinition = allDataTypes.get(derivedFrom);
1584 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1585 return Either.left(dataTypeDefinition);
1587 Either<ImmutablePair<DataTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
1588 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.DataType,
1589 DataTypeData.class);
1590 log.debug(AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS, uniqueId, parentNode);
1591 if (parentNode.isRight()) {
1592 JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
1593 if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
1594 log.error("Failed to find the parent data type of data type {}. status is {}", uniqueId, janusGraphOperationStatus);
1595 result = Either.right(janusGraphOperationStatus);
1599 // derived from node was found
1600 ImmutablePair<DataTypeData, GraphEdge> immutablePair = parentNode.left().value();
1601 DataTypeData parentCT = immutablePair.getKey();
1602 String parentUniqueId = parentCT.getUniqueId();
1603 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = getDataTypeByUid(parentUniqueId);
1604 if (dataTypeByUid.isRight()) {
1605 return Either.right(dataTypeByUid.right().value());
1607 DataTypeDefinition parentDataTypeDefinition = dataTypeByUid.left().value();
1608 dataTypeDefinition.setDerivedFrom(parentDataTypeDefinition);
1610 result = Either.left(dataTypeDefinition);
1614 public Either<String, JanusGraphOperationStatus> checkInnerType(PropertyDataDefinition propDataDef) {
1615 String propertyType = propDataDef.getType();
1616 ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
1617 return getInnerType(type, propDataDef::getSchema);
1620 public Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypeNodes() {
1621 final Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypes =
1622 janusGraphGenericDao.getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
1623 if (getAllDataTypes.isRight() && getAllDataTypes.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
1624 return Either.left(Collections.emptyList());
1626 return getAllDataTypes;
1629 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType,
1630 Map<String, DataTypeDefinition> dataTypes) {
1631 log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
1632 ToscaPropertyType type = getType(propertyType);
1635 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
1636 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter
1637 .validateAndUpdate(value, dataTypeDefinition, dataTypes);
1638 if (Boolean.FALSE.equals(validateResult.right)) {
1639 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
1640 return Either.right(false);
1642 JsonElement jsonElement = validateResult.left;
1643 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
1644 return Either.left(valueFromJsonElement);
1646 log.trace("before validating property type {}", propertyType);
1647 boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
1648 if (!isValidProperty) {
1649 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
1650 return Either.right(false);
1653 Object convertedValue = value;
1654 if (!isEmptyValue(value) && isValidate) {
1655 PropertyValueConverter converter = type.getConverter();
1656 convertedValue = converter.convert(value, innerType, dataTypes);
1658 return Either.left(convertedValue);
1661 public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, String innerType,
1662 Map<String, DataTypeDefinition> dataTypes) {
1663 return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes);
1666 public <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType,
1668 return this.findPropertiesOfNode(nodeType, uniqueId).right().bind(this::handleNotFoundProperties).left()
1669 .bind(props -> getAllDerivedFromChainProperties(uniqueId, nodeType, clazz, props.values()));
1672 private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNotFoundProperties(
1673 JanusGraphOperationStatus janusGraphOperationStatus) {
1674 if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
1675 return Either.left(new HashMap<>());
1677 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1680 private <T extends GraphNode> Either<List<PropertyDefinition>, StorageOperationStatus> getAllDerivedFromChainProperties(String uniqueId,
1681 NodeTypeEnum nodeType,
1683 Collection<PropertyDefinition> nodeProps) {
1684 List<PropertyDefinition> accumulatedProps = new ArrayList<>(nodeProps);
1685 String currentNodeUid = uniqueId;
1686 Either<T, StorageOperationStatus> derivedFrom;
1687 while ((derivedFrom = derivedFromOperation.getDerivedFromChild(currentNodeUid, nodeType, clazz)).isLeft()) {
1688 currentNodeUid = derivedFrom.left().value().getUniqueId();
1689 JanusGraphOperationStatus janusGraphOperationStatus = fillPropertiesList(currentNodeUid, nodeType, accumulatedProps::addAll);
1690 if (janusGraphOperationStatus != JanusGraphOperationStatus.OK) {
1691 log.debug("failed to fetch properties for type {} with id {}", nodeType, currentNodeUid);
1692 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
1695 StorageOperationStatus getDerivedResult = derivedFrom.right().value();
1696 return isReachedEndOfDerivedFromChain(getDerivedResult) ? Either.left(accumulatedProps) : Either.right(getDerivedResult);
1699 private boolean isReachedEndOfDerivedFromChain(StorageOperationStatus getDerivedResult) {
1700 return getDerivedResult == StorageOperationStatus.NOT_FOUND;
1704 * @Override public PropertyOperation getPropertyOperation() { return this; }
1706 public JanusGraphOperationStatus fillPropertiesList(String uniqueId, NodeTypeEnum nodeType, Consumer<List<PropertyDefinition>> propertySetter) {
1707 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesRes = findPropertiesifExist(uniqueId, nodeType);
1708 if (findPropertiesRes.isRight()) {
1709 return findPropertiesRes.right().value();
1711 Map<String, PropertyDefinition> properties = findPropertiesRes.left().value();
1712 if (properties != null) {
1713 List<PropertyDefinition> propertiesAsList = properties.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
1714 propertySetter.accept(propertiesAsList);
1716 return JanusGraphOperationStatus.OK;
1719 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesifExist(String uniqueId, NodeTypeEnum nodeType) {
1720 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode = this.findPropertiesOfNode(nodeType, uniqueId);
1721 if (findPropertiesOfNode.isRight()) {
1722 log.debug("After looking for properties of vertex {}. status is {}", uniqueId, findPropertiesOfNode.right().value());
1723 if (findPropertiesOfNode.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
1724 return Either.left(Maps.newHashMap());
1726 return findPropertiesOfNode;
1728 return findPropertiesOfNode;
1732 * add properties to element type.
1734 * Per property, add a property node and associate it to the element type
1737 * @param propertiesMap
1740 protected Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum nodeType,
1741 Map<String, PropertyDefinition> propertiesMap) {
1742 Map<String, PropertyData> propertiesData = new HashMap<>();
1743 if (propertiesMap != null) {
1744 for (Entry<String, PropertyDefinition> propertyDefinitionEntry : propertiesMap.entrySet()) {
1745 String propertyName = propertyDefinitionEntry.getKey();
1746 Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType = this
1747 .addPropertyToNodeType(propertyName, propertyDefinitionEntry.getValue(), nodeType, uniqueId);
1748 if (addPropertyToNodeType.isRight()) {
1749 JanusGraphOperationStatus operationStatus = addPropertyToNodeType.right().value();
1750 log.error("Failed to associate {} {} to property {} in graph. status is {}", nodeType.getName(), uniqueId, propertyName,
1752 return Either.right(operationStatus);
1754 propertiesData.put(propertyName, addPropertyToNodeType.left().value());
1757 return Either.left(propertiesData);
1760 public Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToElementType(String uniqueId, NodeTypeEnum elementType,
1761 List<PropertyDefinition> properties) {
1762 Map<String, PropertyDefinition> propMap;
1763 if (properties == null) {
1766 propMap = properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, propDef -> propDef));
1768 return addPropertiesToElementType(uniqueId, elementType, propMap);
1772 public Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1773 DataTypeDefinition oldDataTypeDefinition) {
1774 return updateDataType(newDataTypeDefinition, oldDataTypeDefinition, true);
1777 private Either<DataTypeDefinition, StorageOperationStatus> updateDataType(DataTypeDefinition newDataTypeDefinition,
1778 DataTypeDefinition oldDataTypeDefinition, boolean inTransaction) {
1779 Either<DataTypeDefinition, StorageOperationStatus> result = null;
1781 List<PropertyDefinition> newProperties = newDataTypeDefinition.getProperties();
1782 List<PropertyDefinition> oldProperties = oldDataTypeDefinition.getProperties();
1783 String newDerivedFromName = newDataTypeDefinition.getDerivedFromName();
1784 String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName();
1785 String dataTypeName = newDataTypeDefinition.getName();
1786 List<PropertyDefinition> propertiesToAdd = new ArrayList<>();
1787 if (isPropertyOmitted(newProperties, oldProperties, dataTypeName) || isPropertyTypeChanged(dataTypeName, newProperties, oldProperties,
1788 propertiesToAdd) || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) {
1789 log.debug("The new data type {} is invalid.", dataTypeName);
1790 result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY);
1793 if (propertiesToAdd == null || propertiesToAdd.isEmpty()) {
1794 log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition);
1795 result = Either.right(StorageOperationStatus.OK);
1798 Map<String, String> newDescriptions = getPropertyDescriptionsToUpdate(oldProperties, newProperties);
1799 if (MapUtils.isNotEmpty(newDescriptions)) {
1800 JanusGraphOperationStatus updatePropertiesStatus = updateDataTypePropertyDescriptions(oldDataTypeDefinition.getUniqueId(),
1802 if (updatePropertiesStatus != JanusGraphOperationStatus.OK) {
1803 log.debug("#updateDataType - Failed to update the descriptions of the properties of the data type {}. Status is {}",
1804 oldDataTypeDefinition, updatePropertiesStatus);
1805 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1806 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatePropertiesStatus));
1810 Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToDataType = addPropertiesToDataType(
1811 oldDataTypeDefinition.getUniqueId(), oldDataTypeDefinition.getModel(), propertiesToAdd);
1812 if (addPropertiesToDataType.isRight()) {
1813 log.debug("Failed to update data type {} to Graph. Status is {}", oldDataTypeDefinition,
1814 addPropertiesToDataType.right().value().name());
1815 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError(UPDATE_DATA_TYPE, PROPERTY);
1816 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToDataType.right().value()));
1819 Either<DataTypeDefinition, JanusGraphOperationStatus> dataTypeByUid = this.getDataTypeByUid(oldDataTypeDefinition.getUniqueId());
1820 if (dataTypeByUid.isRight()) {
1821 JanusGraphOperationStatus status = addPropertiesToDataType.right().value();
1822 log.debug("Failed to get data type {} after update. Status is {}", oldDataTypeDefinition.getUniqueId(), status.name());
1823 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(UPDATE_DATA_TYPE, PROPERTY, status.name());
1824 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
1826 result = Either.left(dataTypeByUid.left().value());
1831 if (!inTransaction) {
1832 if (result == null || result.isRight()) {
1833 log.error(GOING_TO_EXECUTE_ROLLBACK_ON_GRAPH);
1834 janusGraphGenericDao.rollback();
1836 log.debug(GOING_TO_EXECUTE_COMMIT_ON_GRAPH);
1837 janusGraphGenericDao.commit();
1843 private boolean isPropertyTypeChanged(String dataTypeName, List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties,
1844 List<PropertyDefinition> outputPropertiesToAdd) {
1845 if (newProperties != null && oldProperties != null) {
1846 Map<String, PropertyDefinition> newPropsMapper = newProperties.stream()
1847 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1848 Map<String, PropertyDefinition> oldPropsMapper = oldProperties.stream()
1849 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
1850 for (Entry<String, PropertyDefinition> newPropertyEntry : newPropsMapper.entrySet()) {
1851 String propName = newPropertyEntry.getKey();
1852 PropertyDefinition propDef = newPropertyEntry.getValue();
1853 PropertyDefinition oldPropertyDefinition = oldPropsMapper.get(propName);
1854 if (oldPropertyDefinition == null) {
1855 log.debug("New property {} received in the data type {}", propName, dataTypeName);
1856 outputPropertiesToAdd.add(propDef);
1859 String oldType = oldPropertyDefinition.getType();
1860 String oldEntryType = getEntryType(oldPropertyDefinition);
1861 String newType = propDef.getType();
1862 String newEntryType = getEntryType(propDef);
1863 if (!oldType.equals(newType)) {
1864 log.debug("Existing property {} in data type {} has a differnet type {} than the new one {}", propName, dataTypeName, oldType,
1868 if (!equalsEntryTypes(oldEntryType, newEntryType)) {
1869 log.debug("Existing property {} in data type {} has a differnet entry type {} than the new one {}", propName, dataTypeName,
1870 oldEntryType, newEntryType);
1878 private boolean equalsEntryTypes(String oldEntryType, String newEntryType) {
1879 if (oldEntryType == null && newEntryType == null) {
1881 } else if (oldEntryType != null && newEntryType != null) {
1882 return oldEntryType.equals(newEntryType);
1888 private String getEntryType(PropertyDefinition oldPropertyDefinition) {
1889 String entryType = null;
1890 SchemaDefinition schema = oldPropertyDefinition.getSchema();
1891 if (schema != null) {
1892 PropertyDataDefinition schemaProperty = schema.getProperty();
1893 if (schemaProperty != null) {
1894 entryType = schemaProperty.getType();
1900 private boolean isPropertyOmitted(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties, String dataTypeName) {
1901 boolean isValid = validateChangeInCaseOfEmptyProperties(newProperties, oldProperties, dataTypeName);
1903 log.debug("At least one property is missing in the new data type {}", dataTypeName);
1906 if (newProperties != null && oldProperties != null) {
1907 List<String> newProps = newProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
1908 List<String> oldProps = oldProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
1909 if (!newProps.containsAll(oldProps)) {
1910 StringJoiner joiner = new StringJoiner(",", "[", "]");
1911 newProps.forEach(joiner::add);
1912 log.debug("Properties {} in data type {} are missing, but they already defined in the existing data type", joiner.toString(),
1920 private boolean validateChangeInCaseOfEmptyProperties(List<PropertyDefinition> newProperties, List<PropertyDefinition> oldProperties,
1921 String dataTypeName) {
1922 if (newProperties != null) {
1923 if (newProperties.isEmpty()) {
1924 newProperties = null;
1927 if (oldProperties != null) {
1928 if (oldProperties.isEmpty()) {
1929 oldProperties = null;
1932 if ((newProperties == null && oldProperties == null) || (newProperties != null && oldProperties != null)) {
1938 private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) {
1939 if (newDerivedFromName != null) {
1940 boolean isEqual = newDerivedFromName.equals(oldDerivedFromName);
1942 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1943 oldDerivedFromName);
1946 } else if (oldDerivedFromName == null) {
1948 } else {// new=null, old != null
1949 log.debug("The new datatype {} derived from another data type {} than the existing one {}", dataTypeName, newDerivedFromName,
1950 oldDerivedFromName);
1960 public Either<Integer, StorageOperationStatus> increaseAndGetObjInstancePropertyCounter(String instanceId, NodeTypeEnum nodeType) {
1961 Either<JanusGraph, JanusGraphOperationStatus> graphResult = janusGraphGenericDao.getGraph();
1962 if (graphResult.isRight()) {
1963 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graphResult.right().value()));
1965 Either<JanusGraphVertex, JanusGraphOperationStatus> vertexService = janusGraphGenericDao
1966 .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(nodeType), instanceId);
1967 if (vertexService.isRight()) {
1968 log.debug("failed to fetch vertex of resource instance for id = {}", instanceId);
1969 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexService.right().value()));
1971 Vertex vertex = vertexService.left().value();
1972 VertexProperty<Object> vertexProperty = vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty());
1973 Integer counter = 0;
1974 if (vertexProperty.isPresent() && vertexProperty.value() != null) {
1975 counter = (Integer) vertexProperty.value();
1978 vertex.property(GraphPropertiesDictionary.PROPERTY_COUNTER.getProperty(), counter);
1979 return Either.left(counter);
1982 public Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesUniqueness(
1983 Map<String, PropertyDefinition> inheritedProperties, List<PropertyDefinition> properties) {
1984 Either<List<PropertyDefinition>, JanusGraphOperationStatus> result = Either.left(properties);
1985 for (PropertyDefinition property : properties) {
1986 JanusGraphOperationStatus status = validatePropertyUniqueness(inheritedProperties, property);
1987 if (status != JanusGraphOperationStatus.OK) {
1988 result = Either.right(status);
1996 * Validates uniqueness of examined property by comparing it with properties in propertiesOfType and updates if need type and inner type of the
1999 private JanusGraphOperationStatus validatePropertyUniqueness(Map<String, PropertyDefinition> inheritedProperties, PropertyDefinition property) {
2000 String propertyName = property.getName();
2001 String propertyType = property.getType();
2002 JanusGraphOperationStatus result = JanusGraphOperationStatus.OK;
2003 if (inheritedProperties.containsKey(propertyName)) {
2004 PropertyDefinition defaultProperty = inheritedProperties.get(propertyName);
2005 if (typesMismatch(propertyType, defaultProperty.getType())) {
2006 log.error("#validatePropertyUniqueness - Property with name {} and different type already exists.", propertyName);
2007 result = JanusGraphOperationStatus.PROPERTY_NAME_ALREADY_EXISTS;
2009 property.setType(defaultProperty.getType());
2010 String innerType = defaultProperty.getSchemaType();
2011 PropertyDataDefinition schemaProperty = property.getSchemaProperty();
2012 if (schemaProperty != null) {
2013 schemaProperty.setType(innerType);
2020 private boolean typesMismatch(String type1, String type2) {
2021 return type1 != null && type2 != null && !type2.equals(type1);
2024 public <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllTypePropertiesFromAllDerivedFrom(
2025 String nextParentUid, NodeTypeEnum nodeType, Class<T> clazz) {
2026 Map<String, PropertyDefinition> allProperies = new HashMap<>();
2027 return getTypePropertiesFromDerivedFromRecursively(nextParentUid, allProperies, nodeType, clazz);
2030 private <T extends GraphNode> Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getTypePropertiesFromDerivedFromRecursively(
2031 String nextParentUid, Map<String, PropertyDefinition> allProperies, NodeTypeEnum nodeType, Class<T> clazz) {
2032 JanusGraphOperationStatus error;
2033 Either<List<ImmutablePair<T, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
2034 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(nodeType), nextParentUid, GraphEdgeLabels.DERIVED_FROM, nodeType, clazz);
2035 if (childrenNodes.isRight()) {
2036 if (childrenNodes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
2037 error = childrenNodes.right().value();
2038 log.debug("#getTypePropertiesFromDerivedFromRecursively - Couldn't fetch derived from node with UID {}, error: {}", nextParentUid,
2040 return Either.right(error);
2042 log.debug("#getTypePropertiesFromDerivedFromRecursively - Derived from node is not found with UID {} - this is OK for root.",
2044 return Either.left(allProperies);
2047 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesOfTypeRes = findPropertiesOfNode(nodeType, nextParentUid);
2048 if (allPropertiesOfTypeRes.isRight() && !allPropertiesOfTypeRes.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
2049 error = allPropertiesOfTypeRes.right().value();
2051 "#getTypePropertiesFromDerivedFromRecursively - Failed to retrieve properties for node with UID {} from graph. status is {}",
2052 nextParentUid, error);
2053 return Either.right(error);
2054 } else if (allPropertiesOfTypeRes.isLeft()) {
2055 if (allProperies.isEmpty()) {
2056 allProperies.putAll(allPropertiesOfTypeRes.left().value());
2058 allProperies.putAll(allPropertiesOfTypeRes.left().value().entrySet().stream().filter(e -> !allProperies.containsKey(e.getKey()))
2059 .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
2062 return getTypePropertiesFromDerivedFromRecursively(childrenNodes.left().value().get(0).getLeft().getUniqueId(), allProperies, nodeType,
2067 private JanusGraphOperationStatus updateDataTypePropertyDescriptions(String uniqueId, Map<String, String> newDescriptions) {
2068 if (MapUtils.isNotEmpty(newDescriptions)) {
2069 Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getDataTypePropertiesRes = janusGraphGenericDao
2070 .getChildrenVertecies(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), uniqueId, GraphEdgeLabels.PROPERTY);
2071 if (getDataTypePropertiesRes.isRight()) {
2072 log.debug("#updateDataTypePropertiesDescriptions - Failed to fetch the property verticies of the Data type {} ", uniqueId);
2073 return getDataTypePropertiesRes.right().value();
2075 getDataTypePropertiesRes.left().value().stream().filter(pair -> newDescriptions.containsKey(getPropertyNameFromEdge(pair)))
2076 .forEach(pair -> setNewDescriptionToVertex(newDescriptions.get(getPropertyNameFromEdge(pair)), pair));
2078 return JanusGraphOperationStatus.OK;
2081 private JanusGraphVertexProperty<String> setNewDescriptionToVertex(String newDescription, ImmutablePair<JanusGraphVertex, Edge> pair) {
2082 return pair.getLeft().property(GraphPropertiesDictionary.DESCRIPTION.getProperty(), newDescription);
2085 private String getPropertyNameFromEdge(ImmutablePair<JanusGraphVertex, Edge> pair) {
2086 return (String) pair.getRight().property(GraphPropertiesDictionary.NAME.getProperty()).value();
2089 private Map<String, String> getPropertyDescriptionsToUpdate(List<PropertyDefinition> oldProperties, List<PropertyDefinition> newProperties) {
2090 Map<String, PropertyDefinition> newPropertiesMap = newProperties.stream().collect(Collectors.toMap(PropertyDefinition::getName, p -> p));
2091 return oldProperties.stream()
2092 .filter(p -> newPropertiesMap.containsKey(p.getName()) && !descriptionsEqual(p, newPropertiesMap.get(p.getName())))
2093 .collect(Collectors.toMap(PropertyDefinition::getName, p -> newPropertiesMap.get(p.getName()).getDescription()));
2096 private boolean descriptionsEqual(PropertyDefinition property, PropertyDefinition otherProperty) {
2097 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2100 if (StringUtils.isNotEmpty(property.getDescription()) && StringUtils.isEmpty(otherProperty.getDescription())) {
2103 if (StringUtils.isEmpty(property.getDescription()) && StringUtils.isNotEmpty(otherProperty.getDescription())) {
2106 return property.getDescription().equals(otherProperty.getDescription());
2109 public static class PropertyConstraintSerialiser implements JsonSerializer<PropertyConstraint> {
2112 public JsonElement serialize(PropertyConstraint src, Type typeOfSrc, JsonSerializationContext context) {
2113 JsonParser parser = new JsonParser();
2114 JsonObject result = new JsonObject();
2115 JsonArray jsonArray = new JsonArray();
2116 if (src instanceof InRangeConstraint) {
2117 InRangeConstraint rangeConstraint = (InRangeConstraint) src;
2118 jsonArray.add(parser.parse(rangeConstraint.getRangeMinValue()));
2119 jsonArray.add(parser.parse(rangeConstraint.getRangeMaxValue()));
2120 result.add("inRange", jsonArray);
2121 } else if (src instanceof GreaterThanConstraint) {
2122 GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src;
2123 jsonArray.add(parser.parse(greaterThanConstraint.getGreaterThan()));
2124 result.add("greaterThan", jsonArray);
2125 } else if (src instanceof LessOrEqualConstraint) {
2126 LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src;
2127 jsonArray.add(parser.parse(lessOrEqualConstraint.getLessOrEqual()));
2128 result.add("lessOrEqual", jsonArray);
2130 log.warn("PropertyConstraint {} is not supported. Ignored.", src.getClass().getName());
2136 public static class PropertyConstraintDeserialiser implements JsonDeserializer<PropertyConstraint> {
2138 private static final String THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL = "The value of GreaterThanConstraint is null";
2141 public PropertyConstraint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
2142 PropertyConstraint propertyConstraint = null;
2143 Set<Entry<String, JsonElement>> set = json.getAsJsonObject().entrySet();
2144 if (set.size() == 1) {
2145 Entry<String, JsonElement> element = set.iterator().next();
2146 String key = element.getKey();
2147 JsonElement value = element.getValue();
2148 ConstraintType constraintType = ConstraintType.getByType(key);
2149 if (constraintType == null) {
2150 log.warn("ConstraintType was not found for constraint name:{}", key);
2152 switch (constraintType) {
2154 if (value != null) {
2155 if (value instanceof JsonArray) {
2156 JsonArray rangeArray = (JsonArray) value;
2157 if (rangeArray.size() != 2) {
2158 log.error("The range constraint content is invalid. value = {}", value);
2160 InRangeConstraint rangeConstraint = new InRangeConstraint();
2161 String minValue = rangeArray.get(0).getAsString();
2163 JsonElement maxElement = rangeArray.get(1);
2164 if (maxElement.isJsonNull()) {
2165 maxValue = String.valueOf(maxElement.getAsJsonNull());
2167 maxValue = maxElement.getAsString();
2169 rangeConstraint.setRangeMinValue(minValue);
2170 rangeConstraint.setRangeMaxValue(maxValue);
2171 propertyConstraint = rangeConstraint;
2175 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2179 if (value != null) {
2180 String asString = value.getAsString();
2181 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
2182 propertyConstraint = new GreaterThanConstraint(asString);
2185 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2189 if (value != null) {
2190 String asString = value.getAsString();
2191 log.debug("Before adding value to LessThanConstraint object. value = {}", asString);
2192 propertyConstraint = new LessThanConstraint(asString);
2195 log.warn("The value of LessThanConstraint is null");
2198 case GREATER_OR_EQUAL:
2199 if (value != null) {
2200 String asString = value.getAsString();
2201 log.debug("Before adding value to GreaterThanConstraint object. value = {}", asString);
2202 propertyConstraint = new GreaterOrEqualConstraint(asString);
2205 log.warn("The value of GreaterOrEqualConstraint is null");
2209 if (value != null) {
2210 String asString = value.getAsString();
2211 log.debug("Before adding value to LessOrEqualConstraint object. value = {}", asString);
2212 propertyConstraint = new LessOrEqualConstraint(asString);
2214 log.warn(THE_VALUE_OF_GREATER_THAN_CONSTRAINT_IS_NULL);
2218 if (value != null) {
2219 JsonArray rangeArray = (JsonArray) value;
2220 if (rangeArray.size() == 0) {
2221 log.error("The valid values constraint content is invalid. value = {}", value);
2223 ValidValuesConstraint vvConstraint = new ValidValuesConstraint();
2224 List<String> validValues = new ArrayList<>();
2225 for (JsonElement jsonElement : rangeArray) {
2226 String item = jsonElement.getAsString();
2227 validValues.add(item);
2229 vvConstraint.setValidValues(validValues);
2230 propertyConstraint = vvConstraint;
2235 if (value != null) {
2236 int asInt = value.getAsInt();
2237 log.debug("Before adding value to Min Length object. value = {}", asInt);
2238 propertyConstraint = new MinLengthConstraint(asInt);
2241 log.warn("The value of MinLengthConstraint is null");
2245 log.warn("Key {} is not supported. Ignored.", key);
2249 return propertyConstraint;
2253 public static class PropertyConstraintJacksonDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer<PropertyConstraint> {
2256 public PropertyConstraint deserialize(com.fasterxml.jackson.core.JsonParser json, DeserializationContext context) throws IOException {
2257 ObjectCodec oc = json.getCodec();
2258 JsonNode node = oc.readTree(json);