/*- * ============LICENSE_START======================================================= * SDC * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= */ package org.openecomp.sdc.be.model.jsonjanusgraph.operations; import fj.data.Either; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; import org.apache.commons.collections.MapUtils; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty; import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupInstance; import org.openecomp.sdc.be.model.GroupInstanceProperty; import org.openecomp.sdc.be.model.GroupProperty; import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.StorageException; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.utils.GroupUtils; import org.openecomp.sdc.common.jsongraph.util.CommonUtility; import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum; import org.openecomp.sdc.common.log.wrappers.Logger; @org.springframework.stereotype.Component("groups-operation") public class GroupsOperation extends BaseOperation { private static final Logger log = Logger.getLogger(GroupsOperation.class.getName()); public StorageOperationStatus deleteCalculatedCapabilitiesWithProperties(String componentId, List groupDefinitions) { Optional error = groupDefinitions.stream() .map(g -> removeCalculatedCapabilityFromComponent(componentId, g.getUniqueId())).filter(status -> status != StorageOperationStatus.OK) .findFirst(); if (!error.isPresent()) { Map extractCapabilityPropertiesFromGroups = ModelConverter .extractCapabilityPropertiesFromGroups(groupDefinitions, false); error = extractCapabilityPropertiesFromGroups.keySet().stream() .map(k -> removeCalculatedCapabilityPropertiesFromComponent(componentId, k)).filter(status -> status != StorageOperationStatus.OK) .findFirst(); } if (error.isPresent()) { return error.get(); } return StorageOperationStatus.OK; } /** * Adds the map of the calculated capabilities and the map of the calculated capabilities properties the the component on the graph * * @param componentId * @param calculatedCapabilities * @param calculatedCapabilitiesProperties * @return status of the result the operation */ public StorageOperationStatus addCalculatedCapabilitiesWithProperties(String componentId, Map calculatedCapabilities, Map calculatedCapabilitiesProperties) { Optional error = calculatedCapabilities.entrySet().stream() .map(e -> addElementToComponent(componentId, VertexTypeEnum.CALCULATED_CAPABILITIES, EdgeLabelEnum.CALCULATED_CAPABILITIES, e)) .filter(status -> status != StorageOperationStatus.OK).findFirst(); if (!error.isPresent()) { error = calculatedCapabilitiesProperties.entrySet().stream().map(e -> addCalculatedCapabilityPropertiesToComponent(componentId, e)) .filter(status -> status != StorageOperationStatus.OK).findFirst(); } if (error.isPresent()) { return error.get(); } return StorageOperationStatus.OK; } public StorageOperationStatus updateCalculatedCapabilitiesWithProperties(String componentId, Map calculatedCapabilities, Map calculatedCapabilitiesProperties) { Optional error = calculatedCapabilities.entrySet().stream() .map(e -> updateCalculatedCapabilityOfComponent(componentId, e)).filter(status -> status != StorageOperationStatus.OK).findFirst(); if (!error.isPresent()) { error = calculatedCapabilitiesProperties.entrySet().stream().map(e -> updateCalculatedCapabilityPropertiesOnComponent(componentId, e)) .filter(status -> status != StorageOperationStatus.OK).findFirst(); } if (error.isPresent()) { return error.get(); } return StorageOperationStatus.OK; } private StorageOperationStatus updateCalculatedCapabilityOfComponent(String componentId, Entry capabilities) { if (MapUtils.isNotEmpty(capabilities.getValue().getMapToscaDataDefinition())) { return updateToscaDataDeepElementsBlockToToscaElement(componentId, EdgeLabelEnum.CALCULATED_CAPABILITIES, capabilities.getValue(), capabilities.getKey()); } return StorageOperationStatus.OK; } private StorageOperationStatus addCalculatedCapabilityPropertiesToComponent(String componentId, Entry properties) { if (MapUtils.isNotEmpty(properties.getValue().getMapToscaDataDefinition())) { return addToscaDataDeepElementsBlockToToscaElement(componentId, EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, properties.getValue(), properties.getKey()); } return StorageOperationStatus.OK; } private StorageOperationStatus updateCalculatedCapabilityPropertiesOnComponent(String componentId, Entry properties) { if (MapUtils.isNotEmpty(properties.getValue().getMapToscaDataDefinition())) { return updateToscaDataDeepElementsBlockToToscaElement(componentId, EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, properties.getValue(), properties.getKey()); } return StorageOperationStatus.OK; } private StorageOperationStatus removeCalculatedCapabilityFromComponent(String componentId, String groupId) { return deleteToscaDataDeepElementsBlockOfToscaElement(componentId, EdgeLabelEnum.CALCULATED_CAPABILITIES, groupId); } private StorageOperationStatus removeCalculatedCapabilityPropertiesFromComponent(String componentId, String groupId) { return deleteToscaDataDeepElementsBlockOfToscaElement(componentId, EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, groupId); } public Either, StorageOperationStatus> createGroups(Component component, Map groups) { Either, StorageOperationStatus> result = null; Either getComponentVertex = null; StorageOperationStatus status = null; getComponentVertex = janusGraphDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse); if (getComponentVertex.isRight()) { result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); } if (result == null) { status = topologyTemplateOperation.associateGroupsToComponent(getComponentVertex.left().value(), groups); if (status != StorageOperationStatus.OK) { result = Either.right(status); } } if (result == null) { result = Either.left(ModelConverter.convertToGroupDefinitions(groups)); } return result; } public Either, StorageOperationStatus> addGroups(Component component, List groups) { Either, StorageOperationStatus> result = null; Either getComponentVertex; StorageOperationStatus status; getComponentVertex = janusGraphDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse); if (getComponentVertex.isRight()) { result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); } if (result == null) { status = addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, groups, JsonPresentationFields.CI_INVARIANT_NAME); if (status != StorageOperationStatus.OK) { result = Either.right(status); } } if (result == null) { Map mapGroup = groups.stream().collect(Collectors.toMap(GroupDataDefinition::getInvariantName, x -> x)); result = Either.left(ModelConverter.convertToGroupDefinitions(mapGroup)); } return result; } public Either, StorageOperationStatus> deleteGroups(Component component, List groups) { Either, StorageOperationStatus> result = null; Either getComponentVertex = null; StorageOperationStatus status = null; getComponentVertex = janusGraphDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse); if (getComponentVertex.isRight()) { result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); } if (result == null) { List groupInvariantName = groups.stream().map(GroupDataDefinition::getInvariantName).collect(Collectors.toList()); status = deleteToscaDataElements(component.getUniqueId(), EdgeLabelEnum.GROUPS, groupInvariantName); if (status != StorageOperationStatus.OK) { result = Either.right(status); } } if (result == null) { Map mapGroup = groups.stream().collect(Collectors.toMap(GroupDataDefinition::getName, x -> x)); result = Either.left(ModelConverter.convertToGroupDefinitions(mapGroup)); } return result; } public Either, StorageOperationStatus> updateGroups(Component component, List groups, PromoteVersionEnum promoteVersion) { Either, StorageOperationStatus> result = null; Either getComponentVertex = null; StorageOperationStatus status = null; getComponentVertex = janusGraphDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse); if (getComponentVertex.isRight()) { result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); } if (result == null) { groups.forEach(gr -> updateVersion(promoteVersion, gr)); status = updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, groups, JsonPresentationFields.CI_INVARIANT_NAME); if (status != StorageOperationStatus.OK) { result = Either.right(status); } } if (result == null) { Map mapGroup = groups.stream().collect(Collectors.toMap(GroupDataDefinition::getInvariantName, x -> x)); result = Either.left(ModelConverter.convertToGroupDefinitions(mapGroup)); updateGroupsOnComponent(component, ModelConverter.convertToGroupDefinitions(mapGroup)); } return result; } private void updateGroupsOnComponent(Component component, List groupsToUpdate) { List groupsFromResource = component.getGroups(); for (GroupDefinition group : groupsToUpdate) { Optional op = groupsFromResource.stream().filter(p -> p.getInvariantName().equalsIgnoreCase(group.getInvariantName())) .findAny(); if (op.isPresent()) { GroupDefinition groupToUpdate = op.get(); groupToUpdate.setMembers(group.getMembers()); groupToUpdate.setCapabilities(group.getCapabilities()); groupToUpdate.setProperties(group.getProperties()); } } } private void updateVersion(PromoteVersionEnum promoteVersion, T group) { group.setVersion(GroupUtils.updateVersion(promoteVersion, group.getVersion())); } public void updateGroupOnComponent(String componentId, GroupDefinition groupDefinition, PromoteVersionEnum promoteMinorVersion) { GraphVertex componentVertex = janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata).left().on(this::onJanusGraphError); updateVersion(promoteMinorVersion, groupDefinition); StorageOperationStatus updateToscaResult = updateToscaDataOfToscaElement(componentVertex, EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, groupDefinition, JsonPresentationFields.CI_INVARIANT_NAME); if (StorageOperationStatus.OK != updateToscaResult) { throw new StorageException(updateToscaResult, groupDefinition.getUniqueId()); } updateLastUpdateDate(componentVertex); } public StorageOperationStatus updateGroupsOnComponent(String componentId, List groups) { GraphVertex componentVertex = janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata).left().on(this::onJanusGraphError); StorageOperationStatus updateToscaResult = updateToscaDataOfToscaElement(componentVertex, EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, groups, JsonPresentationFields.CI_INVARIANT_NAME); if (StorageOperationStatus.OK != updateToscaResult) { throw new StorageException(updateToscaResult); } updateLastUpdateDate(componentVertex); return updateToscaResult; } private void updateLastUpdateDate(GraphVertex componentVertex) { componentVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis()); janusGraphDao.updateVertex(componentVertex).left().on(this::onJanusGraphError); } GraphVertex onJanusGraphError(JanusGraphOperationStatus janusGraphOperationStatus) { throw new StorageException(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus)); } public Either, StorageOperationStatus> updateGroupPropertiesOnComponent(String componentId, GroupDefinition group, List newGroupProperties, PromoteVersionEnum promoteMinorVersion) { Either getComponentVertex = janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata); if (getComponentVertex.isRight()) { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch component {}. Status is {} ", componentId); return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); } GraphVertex componentVertex = getComponentVertex.left().value(); //update List properties = group.getProperties(); newGroupProperties.forEach(np -> { Optional currentProp = properties.stream().filter(p -> p.getName().equals(np.getName())).findAny(); if (currentProp.isPresent()) { currentProp.get().setValue(np.getValue()); currentProp.get().setToscaFunction(np.getToscaFunction()); } }); updateVersion(promoteMinorVersion, group); StorageOperationStatus updateDataRes = updateToscaDataOfToscaElement(componentVertex, EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, group, JsonPresentationFields.CI_INVARIANT_NAME); if (updateDataRes != StorageOperationStatus.OK) { log.debug("Failed to update properties for group {} error {}", group.getName(), updateDataRes); return Either.right(updateDataRes); } componentVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis()); Either updateRes = janusGraphDao.updateVertex(componentVertex); if (updateRes.isRight()) { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the component {}. Status is {} ", componentId, updateRes.right().value()); return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updateRes.right().value())); } return Either.left(newGroupProperties); } public Either, StorageOperationStatus> updateGroupInstances(Component component, String instanceId, List updatedGroupInstances) { Either, StorageOperationStatus> result = null; StorageOperationStatus status = null; Either getComponentVertex = janusGraphDao .getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse); if (getComponentVertex.isRight()) { result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); } if (result == null) { List pathKeys = new ArrayList<>(); pathKeys.add(instanceId); status = updateToscaDataDeepElementsOfToscaElement(component.getUniqueId(), EdgeLabelEnum.INST_GROUPS, VertexTypeEnum.INST_GROUPS, updatedGroupInstances, pathKeys, JsonPresentationFields.NAME); if (status != StorageOperationStatus.OK) { result = Either.right(status); } } if (result == null) { result = Either.left(updatedGroupInstances); } return result; } public Either updateGroup(Component component, GroupDefinition currentGroup) { StorageOperationStatus status = updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, currentGroup, JsonPresentationFields.CI_INVARIANT_NAME); if (status != StorageOperationStatus.OK) { CommonUtility .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update group {} of component {}. The status is}. ", currentGroup.getName(), component.getName(), status); return Either.right(status); } return Either.left(currentGroup); } public StorageOperationStatus deleteGroup(Component component, String currentGroupName) { StorageOperationStatus status = deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, currentGroupName, JsonPresentationFields.CI_INVARIANT_NAME); if (status != StorageOperationStatus.OK) { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete group {} of component {}. The status is}. ", currentGroupName, component.getName(), status); } return status; } public Either addGroup(Component component, GroupDefinition currentGroup, PromoteVersionEnum promoteMinorVersion) { updateVersion(promoteMinorVersion, currentGroup); StorageOperationStatus status = addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, currentGroup, JsonPresentationFields.CI_INVARIANT_NAME); if (status != StorageOperationStatus.OK) { CommonUtility .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update group {} of component {}. The status is}. ", currentGroup.getName(), component.getName(), status); return Either.right(status); } return Either.left(currentGroup); } public Either updateGroupInstancePropertyValuesOnGraph(String componentId, String instanceId, GroupInstance oldGroupInstance, List newProperties) { List propertiesOld = oldGroupInstance.getProperties(); newProperties.forEach(np -> { Optional prop = propertiesOld.stream().filter(p -> p.getName().equals(np.getName())).findFirst(); prop.ifPresent(propertyDataDefinition -> propertyDataDefinition.setValue(np.getValue())); }); GroupInstanceDataDefinition groupInstanceDataDefinition = new GroupInstanceDataDefinition(oldGroupInstance); List pathKeys = new ArrayList<>(); groupInstanceDataDefinition.setModificationTime(System.currentTimeMillis()); groupInstanceDataDefinition.setCustomizationUUID(UUID.randomUUID().toString()); pathKeys.add(instanceId); StorageOperationStatus updateDataRes = updateToscaDataDeepElementOfToscaElement(componentId, EdgeLabelEnum.INST_GROUPS, VertexTypeEnum.INST_GROUPS, groupInstanceDataDefinition, pathKeys, JsonPresentationFields.NAME); if (updateDataRes != StorageOperationStatus.OK) { log.debug("Failed to update properties for group instance {} error {}", oldGroupInstance.getName(), updateDataRes); return Either.right(updateDataRes); } return Either.left(oldGroupInstance); } }