diff options
author | kissand <andras.zoltan.kiss@est.tech> | 2022-05-12 15:59:18 +0200 |
---|---|---|
committer | kissand <andras.zoltan.kiss@est.tech> | 2022-06-08 09:46:28 +0200 |
commit | e9ed581de0a6090c513e6fca0052b69396cb3cc8 (patch) | |
tree | ea66ec265e0544cf0037e9fe2969a5f017d9ad45 /cps-ncmp-service | |
parent | 002fb164cde7079cb3cac65a14b74fec9588ddc5 (diff) |
Merge 2 'query' end points in NCMP
- merge two endpoint for a same backend
- use xPath query instead of sql query
- modify searches endpoint to return a cmHandle object with all public
properties
- handle old (deprecated) queries
- handle public property queries
- create useful examples
- use more verbose error messages
- simplify openapi yamls
- create new query service
- change second endpoint name to a better matched name
- modify legacy tests with new requirements
- create new tests for the new scenarios
Issue-ID: CPS-1016
Change-Id: I7476e9dbd510ec93b5b48ce85d477ecb2dadffff
Signed-off-by: kissand <andras.zoltan.kiss@est.tech>
Diffstat (limited to 'cps-ncmp-service')
11 files changed, 646 insertions, 146 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyCmHandlerQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyCmHandlerQueryService.java new file mode 100644 index 0000000000..f8d51feba8 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyCmHandlerQueryService.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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; + +import java.util.Collection; +import org.onap.cps.spi.model.CmHandleQueryParameters; +import org.onap.cps.spi.model.DataNode; + +public interface NetworkCmProxyCmHandlerQueryService { + /** + * Query and return cm handles that match the given query parameters. + * + * @param cmHandleQueryParameters the cm handle query parameters + * @return collection of cm handles + */ + Collection<DataNode> queryCmHandles(CmHandleQueryParameters cmHandleQueryParameters); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java index 7527ae5c50..ce850cc82f 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java @@ -106,15 +106,6 @@ public interface NetworkCmProxyDataService { Collection<ModuleReference> getYangResourcesModuleReferences(String cmHandleId); /** - * Query cm handle identifiers for the given collection of module names. - * - * @param moduleNames module names. - * @return a collection of cm handle identifiers. The schema set for each cm handle must include all the - * given module names - */ - Collection<String> executeCmHandleHasAllModulesSearch(Collection<String> moduleNames); - - /** * Query cm handle details by cm handle's name. * * @param cmHandleId cm handle identifier @@ -134,7 +125,15 @@ public interface NetworkCmProxyDataService { * Query and return cm handles that match the given query parameters. * * @param cmHandleQueryApiParameters the cm handle query parameters + * @return collection of cm handles + */ + Set<NcmpServiceCmHandle> executeCmHandleSearch(CmHandleQueryApiParameters cmHandleQueryApiParameters); + + /** + * Query and return cm handle ids that match the given query parameters. + * + * @param cmHandleQueryApiParameters the cm handle query parameters * @return collection of cm handle ids */ - Set<String> queryCmHandles(CmHandleQueryApiParameters cmHandleQueryApiParameters); + Set<String> executeCmHandleIdSearch(CmHandleQueryApiParameters cmHandleQueryApiParameters); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceImpl.java new file mode 100644 index 0000000000..ef6e953e2f --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceImpl.java @@ -0,0 +1,180 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.constants.DmiRegistryConstants.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DMI_REGISTRY_ANCHOR; +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; +import static org.onap.cps.utils.CmHandleQueryRestParametersValidator.validateModuleNameConditionProperties; + +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 lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService; +import org.onap.cps.spi.CpsAdminPersistenceService; +import org.onap.cps.spi.CpsDataPersistenceService; +import org.onap.cps.spi.model.Anchor; +import org.onap.cps.spi.model.CmHandleQueryParameters; +import org.onap.cps.spi.model.ConditionProperties; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.model.DataNodeIdentifier; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCmHandlerQueryService { + + private static final String PROPERTY_QUERY_NAME = "hasAllProperties"; + private static final String MODULE_QUERY_NAME = "hasAllModules"; + private final CpsDataPersistenceService cpsDataPersistenceService; + private final CpsAdminPersistenceService cpsAdminPersistenceService; + private final JsonObjectMapper jsonObjectMapper; + + /** + * Query and return cm handles that match the given query parameters. + * + * @param cmHandleQueryParameters the cm handle query parameters + * @return collection of cm handles + */ + @Override + public Collection<DataNode> queryCmHandles(final CmHandleQueryParameters cmHandleQueryParameters) { + + if (cmHandleQueryParameters.getCmHandleQueryParameters().isEmpty()) { + return getAllCmHandles(); + } + + final Collection<DataNodeIdentifier> amalgamatedQueryResultIdentifiers = new ArrayList<>(); + final Map<DataNodeIdentifier, DataNode> amalgamatedQueryResults = new HashMap<>(); + + final boolean firstQuery = moduleNameQuery(cmHandleQueryParameters, + amalgamatedQueryResultIdentifiers, amalgamatedQueryResults); + + publicPropertyQuery(cmHandleQueryParameters, amalgamatedQueryResultIdentifiers, + amalgamatedQueryResults, firstQuery); + + final Collection<DataNode> filteredDataNodes = new ArrayList<>(); + amalgamatedQueryResultIdentifiers.forEach(amalgamatedQueryResultIdentifier -> + filteredDataNodes.add(amalgamatedQueryResults.get(amalgamatedQueryResultIdentifier)) + ); + + return filteredDataNodes; + } + + private void publicPropertyQuery(final CmHandleQueryParameters cmHandleQueryParameters, + final Collection<DataNodeIdentifier> amalgamatedQueryResultIdentifiers, + final Map<DataNodeIdentifier, DataNode> amalgamatedQueryResults, + boolean firstQuery) { + for (final Map.Entry<String, String> entry : + getPublicPropertyPairs(cmHandleQueryParameters.getCmHandleQueryParameters()).entrySet()) { + final String cmHandlePath = "//public-properties[@name='" + entry.getKey() + "' " + "and @value='" + + entry.getValue() + "']" + "/ancestor::cm-handles"; + + final Collection<DataNode> dataNodes = getDataNodes(cmHandlePath); + + if (firstQuery) { + firstQuery = false; + dataNodes.forEach(dataNode -> { + final DataNodeIdentifier dataNodeIdentifier = + jsonObjectMapper.convertToValueType(dataNode, DataNodeIdentifier.class); + amalgamatedQueryResultIdentifiers.add(dataNodeIdentifier); + amalgamatedQueryResults.put(dataNodeIdentifier, dataNode); + }); + } else { + final Collection<DataNodeIdentifier> singleConditionQueryDataNodeIdentifiers = new ArrayList<>(); + dataNodes.forEach(dataNode -> { + final DataNodeIdentifier dataNodeIdentifier = + jsonObjectMapper.convertToValueType(dataNode, DataNodeIdentifier.class); + singleConditionQueryDataNodeIdentifiers.add(dataNodeIdentifier); + amalgamatedQueryResults.put(dataNodeIdentifier, dataNode); + }); + amalgamatedQueryResultIdentifiers.retainAll(singleConditionQueryDataNodeIdentifiers); + } + + if (amalgamatedQueryResultIdentifiers.isEmpty()) { + break; + } + } + } + + private boolean moduleNameQuery(final CmHandleQueryParameters cmHandleQueryParameters, + final Collection<DataNodeIdentifier> amalgamatedQueryResultIdentifiers, + final Map<DataNodeIdentifier, DataNode> amalgamatedQueryResults) { + boolean firstQuery = true; + if (!getModuleNames(cmHandleQueryParameters.getCmHandleQueryParameters()).isEmpty()) { + final Collection<Anchor> anchors = cpsAdminPersistenceService.queryAnchors("NFP-Operational", + getModuleNames(cmHandleQueryParameters.getCmHandleQueryParameters())); + anchors.forEach(anchor -> { + final List<DataNode> dataNodes = getDataNodes("//cm-handles[@id='" + anchor.getName() + "']"); + dataNodes.parallelStream().forEach(dataNode -> { + final DataNodeIdentifier dataNodeIdentifier = + jsonObjectMapper.convertToValueType(dataNode, DataNodeIdentifier.class); + amalgamatedQueryResultIdentifiers.add(dataNodeIdentifier); + amalgamatedQueryResults.put(dataNodeIdentifier, dataNode); + }); + }); + firstQuery = false; + } + return firstQuery; + } + + private List<Map<String, String>> getConditions(final List<ConditionProperties> conditionProperties, + final String name) { + for (final ConditionProperties conditionProperty : conditionProperties) { + if (conditionProperty.getConditionName().equals(name)) { + return conditionProperty.getConditionParameters(); + } + } + return Collections.emptyList(); + } + + private List<String> getModuleNames(final List<ConditionProperties> conditionProperties) { + final List<String> result = new ArrayList<>(); + getConditions(conditionProperties, MODULE_QUERY_NAME).parallelStream().forEach( + conditionProperty -> { + validateModuleNameConditionProperties(conditionProperty); + result.add(conditionProperty.get("moduleName")); + } + ); + return result; + } + + private Map<String, String> getPublicPropertyPairs(final List<ConditionProperties> conditionProperties) { + final Map<String, String> result = new HashMap<>(); + getConditions(conditionProperties, PROPERTY_QUERY_NAME).forEach(result::putAll); + return result; + } + + private Collection<DataNode> getAllCmHandles() { + return getDataNodes("//public-properties/ancestor::cm-handles"); + } + + private List<DataNode> getDataNodes(final String cmHandlePath) { + return cpsDataPersistenceService.queryDataNodes( + NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandlePath, INCLUDE_ALL_DESCENDANTS); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index 717cae565c..6ba1043b32 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -30,12 +30,11 @@ import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPER import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMESTAMP; import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum; import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; +import static org.onap.cps.utils.CmHandleQueryRestParametersValidator.validateCmHandleQueryParameters; -import com.google.common.base.Strings; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -45,9 +44,11 @@ import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; import org.onap.cps.ncmp.api.impl.operations.DmiOperations; +import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.inventory.sync.ModuleSyncService; @@ -61,6 +62,7 @@ import org.onap.cps.spi.exceptions.AlreadyDefinedException; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.onap.cps.spi.exceptions.DataValidationException; import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; +import org.onap.cps.spi.model.CmHandleQueryParameters; import org.onap.cps.spi.model.ModuleReference; import org.onap.cps.utils.CpsValidator; import org.onap.cps.utils.JsonObjectMapper; @@ -88,21 +90,23 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private final ModuleSyncService moduleSyncService; + private final NetworkCmProxyCmHandlerQueryService networkCmProxyCmHandlerQueryService; + @Override public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule( - final DmiPluginRegistration dmiPluginRegistration) { + final DmiPluginRegistration dmiPluginRegistration) { dmiPluginRegistration.validateDmiPluginRegistration(); final DmiPluginRegistrationResponse dmiPluginRegistrationResponse = new DmiPluginRegistrationResponse(); dmiPluginRegistrationResponse.setRemovedCmHandles( - parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration.getRemovedCmHandles())); + parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration.getRemovedCmHandles())); if (!dmiPluginRegistration.getCreatedCmHandles().isEmpty()) { dmiPluginRegistrationResponse.setCreatedCmHandles( - parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration)); + parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration)); } if (!dmiPluginRegistration.getUpdatedCmHandles().isEmpty()) { dmiPluginRegistrationResponse.setUpdatedCmHandles( - networkCmProxyDataServicePropertyHandler - .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles())); + networkCmProxyDataServicePropertyHandler + .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles())); } return dmiPluginRegistrationResponse; } @@ -154,28 +158,35 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService } /** - * Retrieve cm handle identifiers for the given list of module names. + * Retrieve cm handles with details for the given query parameters. * - * @param moduleNames module names. - * @return a collection of anchor identifiers + * @param cmHandleQueryApiParameters cm handle query parameters + * @return cm handles with details */ @Override - public Collection<String> executeCmHandleHasAllModulesSearch(final Collection<String> moduleNames) { - return cpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNames); - } + public Set<NcmpServiceCmHandle> executeCmHandleSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters) { - @Override - public Set<String> queryCmHandles(final CmHandleQueryApiParameters cmHandleQueryApiParameters) { + final CmHandleQueryParameters cmHandleQueryParameters = jsonObjectMapper.convertToValueType( + cmHandleQueryApiParameters, CmHandleQueryParameters.class); - cmHandleQueryApiParameters.getPublicProperties().forEach((key, value) -> { - if (Strings.isNullOrEmpty(key)) { - throw new DataValidationException("Invalid Query Parameter.", - "Missing property name - please supply a valid name."); - } - }); + validateCmHandleQueryParameters(cmHandleQueryParameters); + + return networkCmProxyCmHandlerQueryService.queryCmHandles(cmHandleQueryParameters).stream() + .map(dataNode -> YangDataConverter + .convertCmHandleToYangModel(dataNode, dataNode.getLeaves().get("id").toString())) + .map(YangDataConverter::convertYangModelCmHandleToNcmpServiceCmHandle).collect(Collectors.toSet()); + } - return cpsAdminService.queryCmHandles(jsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, - org.onap.cps.spi.model.CmHandleQueryParameters.class)); + /** + * Retrieve cm handle ids for the given query parameters. + * + * @param cmHandleQueryApiParameters cm handle query parameters + * @return cm handle ids + */ + @Override + public Set<String> executeCmHandleIdSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters) { + return executeCmHandleSearch(cmHandleQueryApiParameters).stream().map(NcmpServiceCmHandle::getCmHandleId) + .collect(Collectors.toSet()); } /** @@ -187,16 +198,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService @Override public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleId) { CpsValidator.validateNameCharacters(cmHandleId); - final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); - final YangModelCmHandle yangModelCmHandle = - inventoryPersistence.getYangModelCmHandle(cmHandleId); - final List<YangModelCmHandle.Property> dmiProperties = yangModelCmHandle.getDmiProperties(); - final List<YangModelCmHandle.Property> publicProperties = yangModelCmHandle.getPublicProperties(); - ncmpServiceCmHandle.setCmHandleId(yangModelCmHandle.getId()); - ncmpServiceCmHandle.setCompositeState(yangModelCmHandle.getCompositeState()); - setDmiProperties(dmiProperties, ncmpServiceCmHandle); - setPublicProperties(publicProperties, ncmpServiceCmHandle); - return ncmpServiceCmHandle; + return YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle( + inventoryPersistence.getYangModelCmHandle(cmHandleId)); } /** @@ -212,7 +215,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService inventoryPersistence.getYangModelCmHandle(cmHandleId); final List<YangModelCmHandle.Property> yangModelPublicProperties = yangModelCmHandle.getPublicProperties(); final Map<String, String> cmHandlePublicProperties = new HashMap<>(); - asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties); + YangDataConverter.asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties); return cmHandlePublicProperties; } @@ -223,23 +226,23 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService * @return cm-handle registration response for create cm-handle requests. */ public List<CmHandleRegistrationResponse> parseAndCreateCmHandlesInDmiRegistrationAndSyncModules( - final DmiPluginRegistration dmiPluginRegistration) { + final DmiPluginRegistration dmiPluginRegistration) { List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>(); try { cmHandleRegistrationResponses = dmiPluginRegistration.getCreatedCmHandles().stream() - .map(cmHandle -> - YangModelCmHandle.toYangModelCmHandle( - dmiPluginRegistration.getDmiPlugin(), - dmiPluginRegistration.getDmiDataPlugin(), - dmiPluginRegistration.getDmiModelPlugin(), cmHandle) - ) - .map(this::registerAndSyncNewCmHandle) - .collect(Collectors.toList()); + .map(cmHandle -> + YangModelCmHandle.toYangModelCmHandle( + dmiPluginRegistration.getDmiPlugin(), + dmiPluginRegistration.getDmiDataPlugin(), + dmiPluginRegistration.getDmiModelPlugin(), cmHandle) + ) + .map(this::registerAndSyncNewCmHandle) + .collect(Collectors.toList()); } catch (final DataValidationException dataValidationException) { cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createFailureResponse(dmiPluginRegistration - .getCreatedCmHandles().stream() - .map(NcmpServiceCmHandle::getCmHandleId).findFirst().orElse(null), - RegistrationError.CM_HANDLE_INVALID_ID)); + .getCreatedCmHandles().stream() + .map(NcmpServiceCmHandle::getCmHandleId).findFirst().orElse(null), + RegistrationError.CM_HANDLE_INVALID_ID)); } return cmHandleRegistrationResponses; } @@ -252,31 +255,31 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService } protected List<CmHandleRegistrationResponse> parseAndRemoveCmHandlesInDmiRegistration( - final List<String> tobeRemovedCmHandles) { + final List<String> tobeRemovedCmHandles) { final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = - new ArrayList<>(tobeRemovedCmHandles.size()); + new ArrayList<>(tobeRemovedCmHandles.size()); for (final String cmHandle : tobeRemovedCmHandles) { try { CpsValidator.validateNameCharacters(cmHandle); deleteSchemaSetWithCascade(cmHandle); cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - "/dmi-registry/cm-handles[@id='" + cmHandle + "']", NO_TIMESTAMP); + "/dmi-registry/cm-handles[@id='" + cmHandle + "']", NO_TIMESTAMP); cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandle)); } catch (final DataNodeNotFoundException dataNodeNotFoundException) { log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", - cmHandle, dataNodeNotFoundException.getMessage()); + cmHandle, dataNodeNotFoundException.getMessage()); cmHandleRegistrationResponses.add(CmHandleRegistrationResponse - .createFailureResponse(cmHandle, RegistrationError.CM_HANDLE_DOES_NOT_EXIST)); + .createFailureResponse(cmHandle, RegistrationError.CM_HANDLE_DOES_NOT_EXIST)); } catch (final DataValidationException dataValidationException) { log.error("Unable to de-register cm-handle id: {}, caused by: {}", - cmHandle, dataValidationException.getMessage()); + cmHandle, dataValidationException.getMessage()); cmHandleRegistrationResponses.add(CmHandleRegistrationResponse - .createFailureResponse(cmHandle, RegistrationError.CM_HANDLE_INVALID_ID)); + .createFailureResponse(cmHandle, RegistrationError.CM_HANDLE_INVALID_ID)); } catch (final Exception exception) { log.error("Unable to de-register cm-handle id : {} , caused by : {}", - cmHandle, exception.getMessage()); + cmHandle, exception.getMessage()); cmHandleRegistrationResponses.add( - CmHandleRegistrationResponse.createFailureResponse(cmHandle, exception)); + CmHandleRegistrationResponse.createFailureResponse(cmHandle, exception)); } } return cmHandleRegistrationResponses; @@ -285,47 +288,25 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private void deleteSchemaSetWithCascade(final String schemaSetName) { try { cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, - CASCADE_DELETE_ALLOWED); + CASCADE_DELETE_ALLOWED); } catch (final SchemaSetNotFoundException schemaSetNotFoundException) { log.warn("Schema set {} does not exist or already deleted", schemaSetName); } } - private void setDmiProperties(final List<YangModelCmHandle.Property> dmiProperties, - final NcmpServiceCmHandle ncmpServiceCmHandle) { - final Map<String, String> dmiPropertiesMap = new LinkedHashMap<>(dmiProperties.size()); - asPropertiesMap(dmiProperties, dmiPropertiesMap); - ncmpServiceCmHandle.setDmiProperties(dmiPropertiesMap); - } - - private void setPublicProperties(final List<YangModelCmHandle.Property> publicProperties, - final NcmpServiceCmHandle ncmpServiceCmHandle) { - final Map<String, String> publicPropertiesMap = new LinkedHashMap<>(); - asPropertiesMap(publicProperties, publicPropertiesMap); - ncmpServiceCmHandle.setPublicProperties(publicPropertiesMap); - } - - private void asPropertiesMap(final List<YangModelCmHandle.Property> properties, - final Map<String, String> propertiesMap) { - for (final YangModelCmHandle.Property property: properties) { - propertiesMap.put(property.getName(), property.getValue()); - } - } - private CmHandleRegistrationResponse registerAndSyncNewCmHandle(final YangModelCmHandle yangModelCmHandle) { try { final String cmHandleJsonData = String.format("{\"cm-handles\":[%s]}", - jsonObjectMapper.asJsonString(yangModelCmHandle)); + jsonObjectMapper.asJsonString(yangModelCmHandle)); cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, - cmHandleJsonData, NO_TIMESTAMP); + cmHandleJsonData, NO_TIMESTAMP); syncModulesAndCreateAnchor(yangModelCmHandle); return CmHandleRegistrationResponse.createSuccessResponse(yangModelCmHandle.getId()); } catch (final AlreadyDefinedException alreadyDefinedException) { return CmHandleRegistrationResponse.createFailureResponse( - yangModelCmHandle.getId(), RegistrationError.CM_HANDLE_ALREADY_EXIST); + yangModelCmHandle.getId(), RegistrationError.CM_HANDLE_ALREADY_EXIST); } catch (final Exception exception) { return CmHandleRegistrationResponse.createFailureResponse(yangModelCmHandle.getId(), exception); } } - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java new file mode 100644 index 0000000000..1df7bba9a1 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java @@ -0,0 +1,123 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.utils; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.api.inventory.CompositeState; +import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +import org.onap.cps.spi.model.DataNode; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class YangDataConverter { + + /** + * This method convert yang model cm handle to ncmp service cm handle. + * @param yangModelCmHandle the yang model of the cm handle + * @return ncmp service cm handle + */ + public static NcmpServiceCmHandle convertYangModelCmHandleToNcmpServiceCmHandle( + final YangModelCmHandle yangModelCmHandle) { + final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); + final List<YangModelCmHandle.Property> dmiProperties = yangModelCmHandle.getDmiProperties(); + final List<YangModelCmHandle.Property> publicProperties = yangModelCmHandle.getPublicProperties(); + ncmpServiceCmHandle.setCmHandleId(yangModelCmHandle.getId()); + ncmpServiceCmHandle.setCompositeState(yangModelCmHandle.getCompositeState()); + setDmiProperties(dmiProperties, ncmpServiceCmHandle); + setPublicProperties(publicProperties, ncmpServiceCmHandle); + return ncmpServiceCmHandle; + } + + /** + * This method convert yang model cm handle properties to simple map. + * @param properties the yang model cm handle properties + * @param propertiesMap the String, String map for the results + */ + public static void asPropertiesMap(final List<YangModelCmHandle.Property> properties, + final Map<String, String> propertiesMap) { + for (final YangModelCmHandle.Property property : properties) { + propertiesMap.put(property.getName(), property.getValue()); + } + } + + /** + * This method convert cm handle data node to yang model cm handle. + * @param cmHandleDataNode the datanode of the cm handle + * @param cmHandleId the id of the cm handle + * @return yang model cm handle + */ + public static YangModelCmHandle convertCmHandleToYangModel(final DataNode cmHandleDataNode, + final String cmHandleId) { + final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); + ncmpServiceCmHandle.setCmHandleId(cmHandleId); + populateCmHandleDetails(cmHandleDataNode, ncmpServiceCmHandle); + return YangModelCmHandle.toYangModelCmHandle( + (String) cmHandleDataNode.getLeaves().get("dmi-service-name"), + (String) cmHandleDataNode.getLeaves().get("dmi-data-service-name"), + (String) cmHandleDataNode.getLeaves().get("dmi-model-service-name"), + ncmpServiceCmHandle + ); + } + + private static void populateCmHandleDetails(final DataNode cmHandleDataNode, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final Map<String, String> dmiProperties = new LinkedHashMap<>(); + final Map<String, String> publicProperties = new LinkedHashMap<>(); + final CompositeStateBuilder compositeStateBuilder = new CompositeStateBuilder(); + CompositeState compositeState = compositeStateBuilder.build(); + for (final DataNode childDataNode: cmHandleDataNode.getChildDataNodes()) { + if (childDataNode.getXpath().contains("/additional-properties[@name=")) { + addProperty(childDataNode, dmiProperties); + } else if (childDataNode.getXpath().contains("/public-properties[@name=")) { + addProperty(childDataNode, publicProperties); + } else if (childDataNode.getXpath().endsWith("/state")) { + compositeState = compositeStateBuilder.fromDataNode(childDataNode).build(); + } + } + ncmpServiceCmHandle.setDmiProperties(dmiProperties); + ncmpServiceCmHandle.setPublicProperties(publicProperties); + ncmpServiceCmHandle.setCompositeState(compositeState); + } + + private static void addProperty(final DataNode propertyDataNode, final Map<String, String> propertiesAsMap) { + propertiesAsMap.put(String.valueOf(propertyDataNode.getLeaves().get("name")), + String.valueOf(propertyDataNode.getLeaves().get("value"))); + } + + private static void setDmiProperties(final List<YangModelCmHandle.Property> dmiProperties, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final Map<String, String> dmiPropertiesMap = new LinkedHashMap<>(dmiProperties.size()); + asPropertiesMap(dmiProperties, dmiPropertiesMap); + ncmpServiceCmHandle.setDmiProperties(dmiPropertiesMap); + } + + private static void setPublicProperties(final List<YangModelCmHandle.Property> publicProperties, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final Map<String, String> publicPropertiesMap = new LinkedHashMap<>(); + asPropertiesMap(publicProperties, publicPropertiesMap); + ncmpServiceCmHandle.setPublicProperties(publicPropertiesMap); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java index 873a44913a..c880ec7537 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java @@ -21,13 +21,11 @@ package org.onap.cps.ncmp.api.inventory; import java.time.OffsetDateTime; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import lombok.RequiredArgsConstructor; import org.onap.cps.api.CpsDataService; +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.NcmpServiceCmHandle; import org.onap.cps.spi.CpsDataPersistenceService; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; @@ -98,16 +96,7 @@ public class InventoryPersistence { */ public YangModelCmHandle getYangModelCmHandle(final String cmHandleId) { CpsValidator.validateNameCharacters(cmHandleId); - final DataNode cmHandleDataNode = getCmHandleDataNode(cmHandleId); - final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); - ncmpServiceCmHandle.setCmHandleId(cmHandleId); - populateCmHandleDetails(cmHandleDataNode, ncmpServiceCmHandle); - return YangModelCmHandle.toYangModelCmHandle( - (String) cmHandleDataNode.getLeaves().get("dmi-service-name"), - (String) cmHandleDataNode.getLeaves().get("dmi-data-service-name"), - (String) cmHandleDataNode.getLeaves().get("dmi-model-service-name"), - ncmpServiceCmHandle - ); + return YangDataConverter.convertCmHandleToYangModel(getCmHandleDataNode(cmHandleId), cmHandleId); } private DataNode getCmHandleDataNode(final String cmHandle) { @@ -118,29 +107,4 @@ public class InventoryPersistence { FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); } - private static void populateCmHandleDetails(final DataNode cmHandleDataNode, - final NcmpServiceCmHandle ncmpServiceCmHandle) { - final Map<String, String> dmiProperties = new LinkedHashMap<>(); - final Map<String, String> publicProperties = new LinkedHashMap<>(); - final CompositeStateBuilder compositeStateBuilder = new CompositeStateBuilder(); - CompositeState compositeState = compositeStateBuilder.build(); - for (final DataNode childDataNode: cmHandleDataNode.getChildDataNodes()) { - if (childDataNode.getXpath().contains("/additional-properties[@name=")) { - addProperty(childDataNode, dmiProperties); - } else if (childDataNode.getXpath().contains("/public-properties[@name=")) { - addProperty(childDataNode, publicProperties); - } else if (childDataNode.getXpath().endsWith("/state")) { - compositeState = compositeStateBuilder.fromDataNode(childDataNode).build(); - } - } - ncmpServiceCmHandle.setDmiProperties(dmiProperties); - ncmpServiceCmHandle.setPublicProperties(publicProperties); - ncmpServiceCmHandle.setCompositeState(compositeState); - } - - private static void addProperty(final DataNode propertyDataNode, final Map<String, String> propertiesAsMap) { - propertiesAsMap.put(String.valueOf(propertyDataNode.getLeaves().get("name")), - String.valueOf(propertyDataNode.getLeaves().get("value"))); - } - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java index 3f584ed153..bf6600d97e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java @@ -20,22 +20,24 @@ package org.onap.cps.ncmp.api.models; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Collections; -import java.util.Map; +import java.util.List; import javax.validation.Valid; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; -@Setter @Getter -@JsonInclude(Include.NON_NULL) +@Setter +@EqualsAndHashCode +@JsonInclude(Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) public class CmHandleQueryApiParameters { - - @JsonProperty("publicCmHandleProperties") + @JsonProperty("cmHandleQueryParameters") @Valid - private Map<String, String> publicProperties = Collections.emptyMap(); - + private List<ConditionApiProperties> cmHandleQueryParameters = Collections.emptyList(); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java new file mode 100644 index 0000000000..9f6d64e164 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.validation.Valid; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class ConditionApiProperties { + @JsonProperty("conditionName") + private String conditionName = ""; + + @JsonProperty("conditionParameters") + @Valid + private List<Map<String, String>> conditionParameters = Collections.emptyList(); +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy new file mode 100644 index 0000000000..a1ad9af191 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy @@ -0,0 +1,149 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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 com.fasterxml.jackson.databind.ObjectMapper +import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService +import org.onap.cps.spi.CpsAdminPersistenceService +import org.onap.cps.spi.CpsDataPersistenceService +import org.onap.cps.spi.model.Anchor +import org.onap.cps.spi.model.CmHandleQueryParameters +import org.onap.cps.spi.model.ConditionProperties +import org.onap.cps.spi.model.DataNode +import org.onap.cps.utils.JsonObjectMapper +import spock.lang.Specification + +import java.util.stream.Collectors + +class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification { + + def cpsDataPersistenceService = Mock(CpsDataPersistenceService) + def cpsAdminPersistenceService = Mock(CpsAdminPersistenceService) + + NetworkCmProxyCmHandlerQueryService objectUnderTest = new NetworkCmProxyCmHandlerQueryServiceImpl( + cpsDataPersistenceService, cpsAdminPersistenceService, new JsonObjectMapper(new ObjectMapper()) + ) + + def 'Retrieve cm handles with public properties when #scenario.'() { + given: 'a condition property' + def cmHandleQueryParameters = new CmHandleQueryParameters() + def conditionProperties = new ConditionProperties() + conditionProperties.conditionName = 'hasAllProperties' + conditionProperties.conditionParameters = publicProperties + cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) + and: 'mock services' + mockResponses() + when: 'the service is invoked' + def returnedCmHandles = objectUnderTest.queryCmHandles(cmHandleQueryParameters) + then: 'the correct expected cm handles are returned' + returnedCmHandles.stream().map(d -> d.leaves.get('id').toString()).collect(Collectors.toList()) == expectedCmHandleIds + where: 'the following data is used' + scenario | publicProperties || expectedCmHandleIds + 'single matching property' | [['Contact' : 'newemailforstore@bookstore.com']] || ['PNFDemo', 'PNFDemo2', 'PNFDemo4'] + 'public property dont match' | [['wont_match' : 'wont_match']] || [] + '2 properties, only one match (and)' | [['Contact' : 'newemailforstore@bookstore.com'], ['Contact2': 'newemailforstore2@bookstore.com']] || ['PNFDemo4'] + '2 properties, no match (and)' | [['Contact' : 'newemailforstore@bookstore.com'], ['Contact2': '']] || [] + } + + def 'Retrieve cm handles with module names when #scenario.'() { + given: 'a condition property' + def cmHandleQueryParameters = new CmHandleQueryParameters() + def conditionProperties = new ConditionProperties() + conditionProperties.conditionName = 'hasAllModules' + conditionProperties.conditionParameters = moduleNames + cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) + and: 'mock services' + mockResponses() + when: 'the service is invoked' + def returnedCmHandles = objectUnderTest.queryCmHandles(cmHandleQueryParameters) + then: 'the correct expected cm handles are returned' + returnedCmHandles.stream().map(d -> d.leaves.get('id').toString()).collect(Collectors.toList()) == expectedCmHandleIds + where: 'the following data is used' + scenario | moduleNames || expectedCmHandleIds + 'single matching module name' | [['moduleName' : 'MODULE-NAME-001']] || ['PNFDemo2', 'PNFDemo3', 'PNFDemo'] + 'module name dont match' | [['moduleName' : 'MODULE-NAME-004']] || [] + '2 module names, only one match (and)' | [['moduleName' : 'MODULE-NAME-002'], ['moduleName': 'MODULE-NAME-003']] || ['PNFDemo4'] + '2 module names, no match (and)' | [['moduleName' : 'MODULE-NAME-002'], ['moduleName': 'MODULE-NAME-004']] || [] + } + + def 'Retrieve cm handles with combined queries when #scenario.'() { + given: 'condition properties' + def cmHandleQueryParameters = new CmHandleQueryParameters() + def conditionProperties1 = new ConditionProperties() + conditionProperties1.conditionName = 'hasAllProperties' + conditionProperties1.conditionParameters = publicProperties + def conditionProperties2 = new ConditionProperties() + conditionProperties2.conditionName = 'hasAllModules' + conditionProperties2.conditionParameters = moduleNames + cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties1,conditionProperties2]) + and: 'mock services' + mockResponses() + when: 'the service is invoked' + def returnedCmHandles = objectUnderTest.queryCmHandles(cmHandleQueryParameters) + then: 'the correct expected cm handles are returned' + returnedCmHandles.stream().map(d -> d.leaves.get('id').toString()).collect(Collectors.toList()) == expectedCmHandleIds + where: 'the following data is used' + scenario | moduleNames | publicProperties || expectedCmHandleIds + 'particularly intersect' | [['moduleName' : 'MODULE-NAME-001']] | [['Contact' : 'newemailforstore@bookstore.com']] || ['PNFDemo2', 'PNFDemo'] + 'empty intersect' | [['moduleName' : 'MODULE-NAME-004']] | [['Contact' : 'newemailforstore@bookstore.com']] || [] + 'total intersect' | [['moduleName' : 'MODULE-NAME-002']] | [['Contact2' : 'newemailforstore2@bookstore.com']] || ['PNFDemo4'] + } + + def 'Retrieve cm handles when the query is empty.'() { + given: 'mock services' + mockResponses() + when: 'the service is invoked' + def cmHandleQueryParameters = new CmHandleQueryParameters() + def returnedCmHandles = objectUnderTest.queryCmHandles(cmHandleQueryParameters) + then: 'the correct expected cm handles are returned' + returnedCmHandles.stream().map(d -> d.leaves.get('id').toString()).collect(Collectors.toList()) == ['PNFDemo', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4'] + } + + void mockResponses() { + def pNFDemo = new DataNode(xpath: 'cmHandle/id[\'PNFDemo\']', leaves: ['id':'PNFDemo']) + def pNFDemo2 = new DataNode(xpath: 'cmHandle/id[\'PNFDemo2\']', leaves: ['id':'PNFDemo2']) + def pNFDemo3 = new DataNode(xpath: 'cmHandle/id[\'PNFDemo3\']', leaves: ['id':'PNFDemo3']) + def pNFDemo4 = new DataNode(xpath: 'cmHandle/id[\'PNFDemo4\']', leaves: ['id':'PNFDemo4']) + + cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'Contact\' and @value=\'newemailforstore@bookstore.com\']/ancestor::cm-handles', _) + >> [pNFDemo, pNFDemo2, pNFDemo4] + cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'wont_match\' and @value=\'wont_match\']/ancestor::cm-handles', _) + >> [] + cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'Contact2\' and @value=\'newemailforstore2@bookstore.com\']/ancestor::cm-handles', _) + >> [pNFDemo4] + cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\'Contact2\' and @value=\'\']/ancestor::cm-handles', _) + >> [] + cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties/ancestor::cm-handles', _) + >> [pNFDemo, pNFDemo2, pNFDemo3, pNFDemo4] + cpsDataPersistenceService.queryDataNodes(_, _, '//cm-handles[@id=\'PNFDemo\']', _) >> [pNFDemo] + cpsDataPersistenceService.queryDataNodes(_, _, '//cm-handles[@id=\'PNFDemo2\']', _) >> [pNFDemo2] + cpsDataPersistenceService.queryDataNodes(_, _, '//cm-handles[@id=\'PNFDemo3\']', _) >> [pNFDemo3] + cpsDataPersistenceService.queryDataNodes(_, _, '//cm-handles[@id=\'PNFDemo4\']', _) >> [pNFDemo4] + + cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-001']) >> [new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo3'), new Anchor(name: 'PNFDemo')] + cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-004']) >> [] + cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-003', 'MODULE-NAME-002']) >> [new Anchor(name: 'PNFDemo4')] + cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-002', 'MODULE-NAME-003']) >> [new Anchor(name: 'PNFDemo4')] + cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-004', 'MODULE-NAME-002']) >> [] + cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-002', 'MODULE-NAME-004']) >> [] + cpsAdminPersistenceService.queryAnchors(_, ['MODULE-NAME-002']) >> [new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo4')] + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy index f56aea7f33..6fbc4eb30e 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy @@ -22,6 +22,7 @@ package org.onap.cps.ncmp.api.impl import com.fasterxml.jackson.databind.ObjectMapper +import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.api.CpsAdminService import org.onap.cps.api.CpsDataService @@ -64,6 +65,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def mockNetworkCmProxyDataServicePropertyHandler = Mock(NetworkCmProxyDataServicePropertyHandler) def mockInventoryPersistence = Mock(InventoryPersistence) def mockModuleSyncService = Mock(ModuleSyncService) + def stubbedNetworkCmProxyCmHandlerQueryService = Stub(NetworkCmProxyCmHandlerQueryService) def noTimestamp = null def objectUnderTest = getObjectUnderTestWithModelSyncDisabled() @@ -387,6 +389,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def getObjectUnderTest() { return Spy(new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, - mockCpsModuleService, mockCpsAdminService, mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockModuleSyncService)) + mockCpsModuleService, mockCpsAdminService, mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, + mockModuleSyncService, stubbedNetworkCmProxyCmHandlerQueryService)) } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy index 55a1a8d1fa..cc183a3b0c 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy @@ -22,15 +22,19 @@ package org.onap.cps.ncmp.api.impl -import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException +import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeState import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters +import org.onap.cps.ncmp.api.models.ConditionApiProperties import org.onap.cps.ncmp.api.models.DmiPluginRegistration import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.ncmp.api.inventory.sync.ModuleSyncService +import org.onap.cps.spi.model.CmHandleQueryParameters +import org.onap.cps.spi.model.ConditionProperties import spock.lang.Shared import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL @@ -61,6 +65,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def mockInventoryPersistence = Mock(InventoryPersistence) def mockModuleSyncService = Mock(ModuleSyncService) def mockDmiPluginRegistration = Mock(DmiPluginRegistration) + def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandlerQueryService) def NO_TOPIC = null def NO_REQUEST_ID = null @@ -70,7 +75,8 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id') def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, - mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockModuleSyncService) + mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, + mockModuleSyncService, mockCpsCmHandlerQueryService) def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']" @@ -160,13 +166,6 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 0 * mockCpsModuleService.getYangResourcesModuleReferences(*_) } - def 'Get cm handle identifiers for the given module names.'() { - when: 'execute a cm handle search for the given module names' - objectUnderTest.executeCmHandleHasAllModulesSearch(['some-module-name']) - then: 'get anchor identifiers is invoked with the expected parameters' - 1 * mockCpsAdminService.queryAnchorNames('NFP-Operational', ['some-module-name']) - } - def 'Get a cm handle.'() { given: 'the system returns a yang modelled cm handle' def dmiServiceName = 'some service name' @@ -245,4 +244,25 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 1 * mockCpsAdminService.createAnchor('NFP-Operational', null, 'some-cm-handle-id') } + + def 'Execute cm handle id search'(){ + given: 'valid CmHandleQueryApiParameters input' + def cmHandleQueryApiParameters = new CmHandleQueryApiParameters() + def conditionApiProperties = new ConditionApiProperties() + conditionApiProperties.conditionName = 'hasAllModules' + conditionApiProperties.conditionParameters = [[moduleName:'module-name-1']] + cmHandleQueryApiParameters.cmHandleQueryParameters = [conditionApiProperties] + and: 'valid CmHandleQueryParameters input' + def cmHandleQueryParameters = new CmHandleQueryParameters() + def conditionProperties = new ConditionProperties() + conditionProperties.conditionName = 'hasAllModules' + conditionProperties.conditionParameters = [[moduleName:'module-name-1']] + cmHandleQueryParameters.cmHandleQueryParameters = [conditionProperties] + and: 'query cm handle method return with a data node list' + mockCpsCmHandlerQueryService.queryCmHandles(cmHandleQueryParameters) >> [ new DataNode(leaves: [id:'cm-handle-id-1'] )] + when: 'execute cm handle search is called' + def result = objectUnderTest.executeCmHandleIdSearch(cmHandleQueryApiParameters) + then: 'result is the same collection as returned by the CPS Data Service' + assert result == ['cm-handle-id-1'] as Set + } } |