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.springframework.util.CollectionUtils.isEmpty;
24 import com.google.common.base.Strings;
25 import fj.data.Either;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
30 import java.util.Optional;
32 import java.util.function.Function;
33 import java.util.stream.Collectors;
34 import org.apache.commons.lang3.tuple.ImmutablePair;
35 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
36 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
37 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
38 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
39 import org.openecomp.sdc.be.dao.neo4j.GraphEdgePropertiesDictionary;
40 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
41 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
42 import org.openecomp.sdc.be.model.CapabilityDefinition;
43 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
44 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
45 import org.openecomp.sdc.be.model.PropertyDefinition;
46 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
47 import org.openecomp.sdc.be.resources.data.CapabilityData;
48 import org.openecomp.sdc.be.resources.data.CapabilityTypeData;
49 import org.openecomp.sdc.be.resources.data.PropertyData;
50 import org.openecomp.sdc.be.resources.data.PropertyValueData;
51 import org.openecomp.sdc.common.log.wrappers.Logger;
52 import org.springframework.stereotype.Component;
54 @Component("capability-operation")
55 public class CapabilityOperation extends AbstractOperation {
57 private static final Logger log = Logger.getLogger(CapabilityOperation.class.getName());
58 private final CapabilityTypeOperation capabilityTypeOperation;
59 private final PropertyOperation propertyOperation;
61 public CapabilityOperation(CapabilityTypeOperation capabilityTypeOperation, PropertyOperation propertyOperation) {
62 this.capabilityTypeOperation = capabilityTypeOperation;
63 this.propertyOperation = propertyOperation;
66 public Either<CapabilityData, JanusGraphOperationStatus> addCapabilityToGraph(String resourceId, CapabilityTypeData capTypeData,
67 CapabilityDefinition capabilityDefinition) {
68 log.debug("#addCapabilityToGraph - capabilityDefinition={}", capabilityDefinition);
69 String capUniqueId = UniqueIdBuilder.buildCapabilityUid(resourceId, capabilityDefinition.getName());
70 CapabilityData capabilityData = buildCapabilityData(capabilityDefinition, capUniqueId);
71 log.debug("addCapabilityToGraph - Before adding capability to graph. capabilityTypeData = {}", capabilityData);
72 Either<CapabilityData, JanusGraphOperationStatus> createCapResult = janusGraphGenericDao.createNode(capabilityData, CapabilityData.class);
73 log.debug("addCapabilityToGraph - After adding capability to graph. status is = {}", createCapResult);
74 if (createCapResult.isRight()) {
75 JanusGraphOperationStatus operationStatus = createCapResult.right().value();
76 log.error("addCapabilityToGraph - Failed to add capability of type {} to graph. status is {}", capabilityDefinition.getType(),
78 return createCapResult;
80 createCapResult = connectToCapabilityType(capabilityData, capTypeData).left()
81 .bind(res -> createCapabilityProperties(capabilityData, capTypeData)).left().map(res -> capabilityData);
82 return createCapResult;
85 private Either<GraphRelation, JanusGraphOperationStatus> connectToCapabilityType(CapabilityData capabilityData,
86 CapabilityTypeData capabilityTypeData) {
87 Map<String, Object> properties = new HashMap<>();
88 String capabilityName = capabilityData.getCapabilityDataDefinition().getName();
89 properties.put(GraphEdgePropertiesDictionary.NAME.getProperty(), capabilityName);
90 return janusGraphGenericDao.createRelation(capabilityData, capabilityTypeData, GraphEdgeLabels.CAPABILITY_IMPL, properties);
97 public Either<List<CapabilityDefinition>, JanusGraphOperationStatus> getCapabilitiesWithProps(
98 List<ImmutablePair<CapabilityData, GraphEdge>> capabilites) {
99 List<Either<CapabilityDefinition, JanusGraphOperationStatus>> listFilledCapabilitiesResults = capabilites.stream().map(ImmutablePair::getLeft)
100 .map(this::toCapabilityDefinitionWithProps).collect(Collectors.toList());
101 Optional<JanusGraphOperationStatus> status = listFilledCapabilitiesResults.stream().filter(Either::isRight).map(res -> res.right().value())
103 if (status.isPresent()) {
104 return Either.right(status.get());
106 List<CapabilityDefinition> listCapabilities = listFilledCapabilitiesResults.stream().map(res -> res.left().value())
107 .collect(Collectors.toList());
108 return Either.left(listCapabilities);
111 private Either<CapabilityDefinition, JanusGraphOperationStatus> toCapabilityDefinitionWithProps(CapabilityData capabilityData) {
112 CapabilityDefinition capabilityDefinition = new CapabilityDefinition(capabilityData.getCapabilityDataDefinition());
113 return getCapabilityProperties(capabilityDefinition.getUniqueId(), capabilityDefinition.getType()).left().map(props -> {
114 capabilityDefinition.setProperties(props);
115 return capabilityDefinition;
120 * get all properties of the capability.
122 * the property definition is taken from the capability type.
124 * @param capabilityUid
127 private Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> getCapabilityProperties(String capabilityUid, String capabilityType) {
128 Either<CapabilityTypeDefinition, JanusGraphOperationStatus> capabilityTypeRes = capabilityTypeOperation
129 .getCapabilityTypeByType(capabilityType);
130 if (capabilityTypeRes.isRight()) {
131 JanusGraphOperationStatus status = capabilityTypeRes.right().value();
132 return Either.right(status);
134 CapabilityTypeDefinition capabilityTypeDefinition = capabilityTypeRes.left().value();
135 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> typesPropsRes = getPropertiesOfCapabilityTypeAndAcestors(
136 capabilityTypeDefinition);
137 if (typesPropsRes.isRight()) {
138 JanusGraphOperationStatus status = typesPropsRes.right().value();
139 return Either.right(status);
141 Map<String, PropertyDefinition> capabilityTypeProperties = typesPropsRes.left().value();
142 if (isEmpty(capabilityTypeProperties)) {
143 return Either.right(JanusGraphOperationStatus.OK);
145 Map<String, PropertyDefinition> uidToPropDefMap = capabilityTypeProperties.values().stream()
146 .collect(Collectors.toMap(PropertyDefinition::getUniqueId, Function.identity()));
147 // Find all properties values on the capability
148 Either<List<ImmutablePair<PropertyValueData, GraphEdge>>, JanusGraphOperationStatus> propertyValNodes = janusGraphGenericDao
149 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Capability), capabilityUid, GraphEdgeLabels.PROPERTY_VALUE,
150 NodeTypeEnum.PropertyValue, PropertyValueData.class);
151 if (propertyValNodes.isRight()) {
152 return onLoadPropValuesFailure(propertyValNodes.right().value(), capabilityTypeProperties);
154 List<ImmutablePair<PropertyValueData, GraphEdge>> propValsRelationPairs = propertyValNodes.left().value();
155 if (isEmpty(propValsRelationPairs)) {
156 return Either.right(JanusGraphOperationStatus.OK);
158 List<ComponentInstanceProperty> capabilityProperties = new ArrayList<>();
159 for (ImmutablePair<PropertyValueData, GraphEdge> propValRelPair : propValsRelationPairs) {
160 PropertyValueData propertyValueData = propValRelPair.getLeft();
161 Either<ImmutablePair<PropertyData, GraphEdge>, JanusGraphOperationStatus> propertyDefRes = janusGraphGenericDao
162 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PropertyValue), propertyValueData.getUniqueId(),
163 GraphEdgeLabels.PROPERTY_IMPL, NodeTypeEnum.Property, PropertyData.class);
164 if (propertyDefRes.isRight()) {
165 JanusGraphOperationStatus status = propertyDefRes.right().value();
166 if (status == JanusGraphOperationStatus.NOT_FOUND) {
167 status = JanusGraphOperationStatus.INVALID_ID;
169 return Either.right(status);
171 ImmutablePair<PropertyData, GraphEdge> propertyDefPair = propertyDefRes.left().value();
172 PropertyData propertyData = propertyDefPair.left;
173 String propertyUniqueId = propertyData.getPropertyDataDefinition().getUniqueId();
174 PropertyDefinition propertyDefinition = uidToPropDefMap.get(propertyUniqueId);
175 ComponentInstanceProperty capabilityProperty = new ComponentInstanceProperty(propertyDefinition, propertyValueData.getValue(),
176 propertyValueData.getUniqueId());
177 capabilityProperties.add(capabilityProperty);
179 Set<String> processedProps = buildProcessedPropsSet(capabilityProperties);
180 // Find all properties which does not have property value on the group.
181 List<ComponentInstanceProperty> leftProps = filterCapabilityTypesProps(capabilityTypeProperties, processedProps);
182 if (leftProps != null) {
183 capabilityProperties.addAll(leftProps);
185 return Either.left(capabilityProperties);
189 * @param capabilityProperties
192 private Set<String> buildProcessedPropsSet(List<ComponentInstanceProperty> capabilityProperties) {
193 return capabilityProperties.stream().map(ComponentInstanceProperty::getName).collect(Collectors.toSet());
196 private Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> onLoadPropValuesFailure(JanusGraphOperationStatus status,
197 Map<String, PropertyDefinition> capabilityTypeProperties) {
198 if (status == JanusGraphOperationStatus.NOT_FOUND) {
199 return Either.left(buildPropsFromCapabilityTypeProps(capabilityTypeProperties));
201 return Either.right(status);
206 * @param capabilityTypeProperties
209 private List<ComponentInstanceProperty> buildPropsFromCapabilityTypeProps(Map<String, PropertyDefinition> capabilityTypeProperties) {
210 return capabilityTypeProperties.values().stream().map(p -> new ComponentInstanceProperty(p, p.getDefaultValue(), null))
211 .collect(Collectors.toList());
215 * @param capabilityTypeRes
216 * @param capabilityTypeDefinition
219 private Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getPropertiesOfCapabilityTypeAndAcestors(
220 CapabilityTypeDefinition capabilityTypeDefinition) {
221 // Get the properties on the group type of this capability
222 Map<String, PropertyDefinition> capabilityTypeProperties = capabilityTypeDefinition.getProperties();
223 String derivedFrom = capabilityTypeDefinition.getDerivedFrom();
224 if (!Strings.isNullOrEmpty(derivedFrom)) {
225 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> parentPropsRes = capabilityTypeOperation
226 .getAllCapabilityTypePropertiesFromAllDerivedFrom(derivedFrom);
227 if (parentPropsRes.isRight()) {
228 JanusGraphOperationStatus status = parentPropsRes.right().value();
229 return Either.right(status);
231 if (capabilityTypeProperties != null) {
232 capabilityTypeProperties.putAll(parentPropsRes.left().value());
234 capabilityTypeProperties = parentPropsRes.left().value();
237 return Either.left(capabilityTypeProperties);
241 * Create all property values of the capability and their relations to relevant properties of the capability type.
243 * @param capabilityDefintion
244 * @param capabilityTypeData
247 private Either<List<ComponentInstanceProperty>, JanusGraphOperationStatus> createCapabilityProperties(CapabilityData capabilityData,
248 CapabilityTypeData capabilityTypeData) {
249 CapabilityDefinition capabilityDefintion = (CapabilityDefinition) capabilityData.getCapabilityDataDefinition();
250 CapabilityTypeDefinition capabilityTypeDefinition = (CapabilityTypeDefinition) capabilityTypeData.getCapabilityTypeDataDefinition();
251 Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> typesPropsRes = getPropertiesOfCapabilityTypeAndAcestors(
252 capabilityTypeDefinition);
253 if (typesPropsRes.isRight()) {
254 JanusGraphOperationStatus status = typesPropsRes.right().value();
255 return Either.right(status);
257 Map<String, PropertyDefinition> capabilityTypeProperties = typesPropsRes.left().value();
258 if (isEmpty(capabilityTypeProperties) && !isEmpty(capabilityDefintion.getProperties())) {
259 log.debug("#createCapabilityProperties - It's not valid if group capability has properties while corresponding capability type doesn't.");
260 return Either.right(JanusGraphOperationStatus.MATCH_NOT_FOUND);
262 Optional<JanusGraphOperationStatus> error = capabilityDefintion.getProperties().stream()
263 .map(property -> createPropertyValue(property, capabilityData, capabilityTypeProperties.get(property.getName()))).filter(Either::isRight)
264 .map(result -> result.right().value()).findFirst();
265 if (error.isPresent()) {
266 return Either.right(error.get());
268 return Either.left(capabilityDefintion.getProperties());
272 * @param capabilityTypeProperties
273 * @param excludePropsWithUniqueIds
276 private List<ComponentInstanceProperty> filterCapabilityTypesProps(Map<String, PropertyDefinition> capabilityTypeProperties,
277 Set<String> excludePropsWithNames) {
278 return capabilityTypeProperties.values().stream().filter(p -> !excludePropsWithNames.contains(p.getName()))
279 .map(p -> new ComponentInstanceProperty(p, p.getDefaultValue(), null)).collect(Collectors.toList());
282 private Either<PropertyValueData, JanusGraphOperationStatus> createPropertyValue(ComponentInstanceProperty capabilityProperty,
283 CapabilityData capabilityData,
284 PropertyDefinition capTypePropertyDefinition) {
285 if (capTypePropertyDefinition == null) {
286 return Either.right(JanusGraphOperationStatus.MATCH_NOT_FOUND);
288 CapabilityDefinition capabilityDefintion = (CapabilityDefinition) capabilityData.getCapabilityDataDefinition();
289 Either<Integer, StorageOperationStatus> indexRes = propertyOperation
290 .increaseAndGetObjInstancePropertyCounter(capabilityDefintion.getUniqueId(), NodeTypeEnum.Capability);
291 String uniqueId = UniqueIdBuilder.buildResourceInstancePropertyValueUid(capabilityDefintion.getUniqueId(), indexRes.left().value());
292 PropertyValueData propertyValueData = new PropertyValueData();
293 propertyValueData.setUniqueId(uniqueId);
294 propertyValueData.setValue(capabilityProperty.getValue());
295 Either<PropertyValueData, JanusGraphOperationStatus> propResult = janusGraphGenericDao.createNode(propertyValueData, PropertyValueData.class);
296 // It's not accepted if Capability Type doesn't have suitable property
297 propResult = propResult.left().bind(propValueData -> connectToProperty(propValueData, capTypePropertyDefinition)).left()
298 .bind(graphRelation -> connectCapability(propertyValueData, capTypePropertyDefinition.getName(), capabilityData)).left()
299 .map(graphRelation -> propertyValueData);
300 propResult.left().foreachDoEffect(propValueData -> capabilityProperty.setUniqueId(uniqueId));
304 private Either<GraphRelation, JanusGraphOperationStatus> connectCapability(PropertyValueData propValueData, String name,
305 CapabilityData capabilityData) {
306 Map<String, Object> properties = new HashMap<>();
307 properties.put(GraphEdgePropertiesDictionary.NAME.getProperty(), name);
308 return janusGraphGenericDao.createRelation(capabilityData, propValueData, GraphEdgeLabels.PROPERTY_VALUE, properties);
311 private Either<GraphRelation, JanusGraphOperationStatus> connectToProperty(PropertyValueData propValueData,
312 PropertyDefinition propertyDefinition) {
313 Either<PropertyData, JanusGraphOperationStatus> dataTypesRes = janusGraphGenericDao
314 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyDefinition.getUniqueId(), PropertyData.class);
315 Map<String, Object> properties = new HashMap<>();
316 properties.put(GraphEdgePropertiesDictionary.NAME.getProperty(), propertyDefinition.getName());
317 return dataTypesRes.left()
318 .bind(propertyData -> janusGraphGenericDao.createRelation(propValueData, propertyData, GraphEdgeLabels.PROPERTY_IMPL, properties));
321 private CapabilityData buildCapabilityData(CapabilityDefinition capabilityDefinition, String ctUniqueId) {
322 CapabilityData capabilityData = new CapabilityData(capabilityDefinition);
323 capabilityData.setUniqueId(ctUniqueId);
324 Long creationDate = capabilityData.getCreationTime();
325 if (creationDate == null) {
326 creationDate = System.currentTimeMillis();
328 capabilityData.setCreationTime(creationDate);
329 capabilityData.setModificationTime(creationDate);
330 return capabilityData;
333 public StorageOperationStatus deleteCapability(CapabilityDefinition capabilityDef) {
334 return janusGraphGenericDao
335 .deleteChildrenNodes(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), capabilityDef.getUniqueId(), GraphEdgeLabels.PROPERTY_VALUE,
336 NodeTypeEnum.PropertyValue, PropertyValueData.class).left()
337 .bind(props -> janusGraphGenericDao.deleteNode(new CapabilityData(capabilityDef), CapabilityData.class)).right()
338 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus).right().on(capData -> StorageOperationStatus.OK);