/* * ============LICENSE_START======================================================= * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * 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. * * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ package org.onap.cps.ncmp.api.impl; import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_MODULES; import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_PROPERTIES; import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_CPS_PATH; import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCpsPathConditionProperties; import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateModuleNameConditionProperties; import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle; import static org.onap.cps.spi.FetchDescendantsOption.DIRECT_CHILDREN_ONLY; import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.cpspath.parser.PathParsingException; import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService; import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries; import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType; import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.exceptions.DataValidationException; import org.onap.cps.spi.model.ConditionProperties; import org.onap.cps.spi.model.DataNode; import org.springframework.stereotype.Service; @Service @Slf4j @RequiredArgsConstructor public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmHandleQueryService { private static final Collection NO_QUERY_TO_EXECUTE = null; private final CmHandleQueries cmHandleQueries; private final InventoryPersistence inventoryPersistence; @Override public Collection queryCmHandleIds( final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { return executeQueries(cmHandleQueryServiceParameters, this::executeCpsPathQuery, this::queryCmHandlesByPublicProperties, this::executeModuleNameQuery); } @Override public Collection queryCmHandleIdsForInventory( final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { return executeQueries(cmHandleQueryServiceParameters, this::queryCmHandlesByPublicProperties, this::queryCmHandlesByPrivateProperties, this::queryCmHandlesByDmiPlugin); } @Override public Collection queryCmHandles( final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) { return getAllCmHandles(); } final Collection cmHandleIds = queryCmHandleIds(cmHandleQueryServiceParameters); return getNcmpServiceCmHandles(cmHandleIds); } private Collection queryCmHandlesByDmiPlugin( final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { final Map dmiPropertyQueryPairs = getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), InventoryQueryConditions.CM_HANDLE_WITH_DMI_PLUGIN.getName()); if (dmiPropertyQueryPairs.isEmpty()) { return NO_QUERY_TO_EXECUTE; } final String dmiPluginIdentifierValue = dmiPropertyQueryPairs .get(PropertyType.DMI_PLUGIN.getYangContainerName()); return cmHandleQueries.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifierValue); } private Collection queryCmHandlesByPrivateProperties( final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { final Map privatePropertyQueryPairs = getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName()); return privatePropertyQueryPairs.isEmpty() ? NO_QUERY_TO_EXECUTE : cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs); } private Collection queryCmHandlesByPublicProperties( final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { final Map publicPropertyQueryPairs = getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), HAS_ALL_PROPERTIES.getConditionName()); return publicPropertyQueryPairs.isEmpty() ? NO_QUERY_TO_EXECUTE : cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs); } private Collection executeModuleNameQuery( final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { final Collection moduleNamesForQuery = getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters()); if (moduleNamesForQuery.isEmpty()) { return NO_QUERY_TO_EXECUTE; } return inventoryPersistence.getCmHandleIdsWithGivenModules(moduleNamesForQuery); } private Collection executeCpsPathQuery( final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { final Map cpsPathCondition = getCpsPathCondition(cmHandleQueryServiceParameters.getCmHandleQueryParameters()); if (!validateCpsPathConditionProperties(cpsPathCondition)) { return Collections.emptySet(); } final Collection cpsPathQueryResult; if (cpsPathCondition.isEmpty()) { return NO_QUERY_TO_EXECUTE; } try { cpsPathQueryResult = collectCmHandleIdsFromDataNodes( cmHandleQueries.queryCmHandleAncestorsByCpsPath( cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS)); } catch (final PathParsingException pathParsingException) { throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(), pathParsingException); } return cpsPathQueryResult; } private Collection getModuleNamesForQuery(final List conditionProperties) { final List result = new ArrayList<>(); getConditions(conditionProperties, HAS_ALL_MODULES.getConditionName()).forEach( conditionProperty -> { validateModuleNameConditionProperties(conditionProperty); result.add(conditionProperty.get("moduleName")); }); return result; } private Map getCpsPathCondition(final List conditionProperties) { final Map result = new HashMap<>(); getConditions(conditionProperties, WITH_CPS_PATH.getConditionName()).forEach(result::putAll); return result; } private Map getPropertyPairs(final List conditionProperties, final String queryProperty) { final Map result = new HashMap<>(); getConditions(conditionProperties, queryProperty).forEach(result::putAll); return result; } private List> getConditions(final List conditionProperties, final String name) { for (final ConditionProperties conditionProperty : conditionProperties) { if (conditionProperty.getConditionName().equals(name)) { return conditionProperty.getConditionParameters(); } } return Collections.emptyList(); } private Collection getAllCmHandles() { final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT).iterator().next(); return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet()); } private Collection getAllCmHandleIds() { final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY) .iterator().next(); return collectCmHandleIdsFromDataNodes(dataNode.getChildDataNodes()); } private Collection getNcmpServiceCmHandles(final Collection cmHandleIds) { final Collection yangModelcmHandles = inventoryPersistence.getYangModelCmHandles(cmHandleIds); final Collection ncmpServiceCmHandles = new ArrayList<>(yangModelcmHandles.size()); yangModelcmHandles.forEach(yangModelcmHandle -> ncmpServiceCmHandles.add(YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(yangModelcmHandle)) ); return ncmpServiceCmHandles; } private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) { return convertYangModelCmHandleToNcmpServiceCmHandle(YangDataConverter .convertCmHandleToYangModel(dataNode, dataNode.getLeaves().get("id").toString())); } private Collection executeQueries(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final Function>... queryFunctions) { if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) { return getAllCmHandleIds(); } Collection combinedQueryResult = NO_QUERY_TO_EXECUTE; for (final Function> queryFunction : queryFunctions) { final Collection queryResult = queryFunction.apply(cmHandleQueryServiceParameters); if (noEntriesFoundCanStopQuerying(queryResult)) { return Collections.emptySet(); } combinedQueryResult = combineCmHandleQueryResults(combinedQueryResult, queryResult); } return combinedQueryResult; } private boolean noEntriesFoundCanStopQuerying(final Collection queryResult) { return queryResult != NO_QUERY_TO_EXECUTE && queryResult.isEmpty(); } private Collection combineCmHandleQueryResults(final Collection firstQuery, final Collection secondQuery) { if (firstQuery == NO_QUERY_TO_EXECUTE && secondQuery == NO_QUERY_TO_EXECUTE) { return NO_QUERY_TO_EXECUTE; } else if (firstQuery == NO_QUERY_TO_EXECUTE) { return secondQuery; } else if (secondQuery == NO_QUERY_TO_EXECUTE) { return firstQuery; } else { firstQuery.retainAll(secondQuery); return firstQuery; } } private Collection collectCmHandleIdsFromDataNodes(final Collection dataNodes) { return dataNodes.stream().map(dataNode -> (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); } }