diff options
Diffstat (limited to 'cps-service/src')
35 files changed, 346 insertions, 692 deletions
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsAnchorService.java b/cps-service/src/main/java/org/onap/cps/api/CpsAnchorService.java index a247150c15..fcb969ba30 100644 --- a/cps-service/src/main/java/org/onap/cps/api/CpsAnchorService.java +++ b/cps-service/src/main/java/org/onap/cps/api/CpsAnchorService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation + * Copyright (C) 2023-2024 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,15 @@ public interface CpsAnchorService { void createAnchor(String dataspaceName, String schemaSetName, String anchorName); /** + * Get an anchor in the given dataspace using the anchor name. + * + * @param dataspaceName dataspace name + * @param anchorName anchor name + * @return an anchor + */ + Anchor getAnchor(String dataspaceName, String anchorName); + + /** * Read all anchors in the given dataspace. * * @param dataspaceName dataspace name @@ -45,13 +54,22 @@ public interface CpsAnchorService { Collection<Anchor> getAnchors(String dataspaceName); /** + * Read all anchors in the given dataspace with the anchor names. + * + * @param dataspaceName dataspace name + * @param anchorNames anchor names + * @return a collection of anchors + */ + Collection<Anchor> getAnchors(String dataspaceName, Collection<String> anchorNames); + + /** * Read all anchors associated with the given schema-set in the given dataspace. * * @param dataspaceName dataspace name * @param schemaSetName schema-set name * @return a collection of anchors */ - Collection<Anchor> getAnchors(String dataspaceName, String schemaSetName); + Collection<Anchor> getAnchorsBySchemaSetName(String dataspaceName, String schemaSetName); /** * Read all anchors associated with the given schema-sets in the given dataspace. @@ -60,16 +78,7 @@ public interface CpsAnchorService { * @param schemaSetNames schema-set names * @return a collection of anchors */ - Collection<Anchor> getAnchors(String dataspaceName, Collection<String> schemaSetNames); - - /** - * Get an anchor in the given dataspace using the anchor name. - * - * @param dataspaceName dataspace name - * @param anchorName anchor name - * @return an anchor - */ - Anchor getAnchor(String dataspaceName, String anchorName); + Collection<Anchor> getAnchorsBySchemaSetNames(String dataspaceName, Collection<String> schemaSetNames); /** * Delete anchor by name in given dataspace. diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java index f396b49e6b..68e1880d77 100644 --- a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java +++ b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java @@ -55,7 +55,7 @@ public interface CpsDataService { * @param anchorName anchor name * @param nodeData node data * @param observedTimestamp observedTimestamp - * @param contentType node data content type + * @param contentType JSON/XML content type */ void saveData(String dataspaceName, String anchorName, String nodeData, OffsetDateTime observedTimestamp, ContentType contentType); @@ -80,7 +80,7 @@ public interface CpsDataService { * @param parentNodeXpath parent node xpath * @param nodeData node data * @param observedTimestamp observedTimestamp - * @param contentType node data content type + * @param contentType JSON/XML content type * */ void saveData(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData, @@ -93,11 +93,12 @@ public interface CpsDataService { * @param dataspaceName dataspace name * @param anchorName anchor name * @param parentNodeXpath parent node xpath - * @param jsonData json data representing list element(s) + * @param nodeData node data representing list element(s) * @param observedTimestamp observedTimestamp + * @param contentType JSON/XML content type */ - void saveListElements(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData, - OffsetDateTime observedTimestamp); + void saveListElements(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData, + OffsetDateTime observedTimestamp, ContentType contentType); /** * Retrieves all the datanodes by XPath for given dataspace and anchor. @@ -134,7 +135,7 @@ public interface CpsDataService { * @param parentNodeXpath xpath to parent node * @param nodeData node data * @param observedTimestamp observedTimestamp - * @param contentType node data content type + * @param contentType JSON/XML content type */ void updateNodeLeaves(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData, OffsetDateTime observedTimestamp, ContentType contentType); @@ -145,22 +146,24 @@ public interface CpsDataService { * @param dataspaceName dataspace name * @param anchorName anchor name * @param parentNodeXpath xpath to parent node - * @param jsonData json data + * @param nodeData node data * @param observedTimestamp observedTimestamp + * @param contentType JSON/XML content type */ - void updateDataNodeAndDescendants(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData, - OffsetDateTime observedTimestamp); + void updateDataNodeAndDescendants(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData, + OffsetDateTime observedTimestamp, ContentType contentType); /** * Replaces multiple existing data nodes' content including descendants in a batch operation. * * @param dataspaceName dataspace name * @param anchorName anchor name - * @param nodesJsonData map of xpath and node JSON data + * @param nodeDataPerXPath map of xpath and node JSON/XML data * @param observedTimestamp observedTimestamp + * @param contentType JSON/XML content type */ - void updateDataNodesAndDescendants(String dataspaceName, String anchorName, Map<String, String> nodesJsonData, - OffsetDateTime observedTimestamp); + void updateDataNodesAndDescendants(String dataspaceName, String anchorName, Map<String, String> nodeDataPerXPath, + OffsetDateTime observedTimestamp, ContentType contentType); /** * Replaces list content by removing all existing elements and inserting the given new elements as json diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java index bdd361458e..931209c998 100644 --- a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java +++ b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java @@ -155,4 +155,37 @@ public interface CpsModuleService { Collection<ModuleReference> identifyNewModuleReferences( Collection<ModuleReference> moduleReferencesToCheck); + /** + * Retrieves module references based on the provided dataspace name, anchor name and attribute filters + * for both parent and child fragments. + + * This method constructs and executes a SQL query to find module references from a database, using + * the specified `dataspaceName`, `anchorName` and two sets of attribute filters: one for parent fragments + * and one for child fragments. The method applies these filters to identify the appropriate fragments + * and schema sets, and then retrieves the corresponding module references. + + * The SQL query is dynamically built based on the provided attribute filters: + * - The `parentAttributes` map is used to filter the parent fragments. The entries in this map are + * converted into a WHERE clause for the parent fragments. + * - The `childAttributes` map is used to filter the child fragments. This is applied to the child fragments + * after filtering the parent fragments. + * + * @param dataspaceName the name of the dataspace to filter on. It is used to locate the relevant dataspace + * in the database. + * @param anchorName the name of the anchor to filter on. It is used to locate the relevant anchor within + * the dataspace. + * @param parentAttributes a map of attributes to filter parent fragments. Each entry in this map represents + * an attribute key-value pair used in the WHERE clause for parent fragments. + * @param childAttributes a map of attributes to filter child fragments. Each entry in this map represents + * an attribute key-value pair used in the WHERE clause for child fragments. + * @return a collection of {@link ModuleReference} objects that match the given criteria. Each + * {@code ModuleReference} contains information about a module's name and revision. + * @implNote The method assumes that both `parentAttributes` and `childAttributes` maps contain at least + * one entry. The first entry from `parentAttributes` is used to filter parent fragments, + * and the first entry from `childAttributes` is used to filter child fragments. + */ + Collection<ModuleReference> getModuleReferencesByAttribute(final String dataspaceName, final String anchorName, + final Map<String, String> parentAttributes, + final Map<String, String> childAttributes); + } diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java index aa9c45d09a..5ca0fe63d4 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation + * Copyright (C) 2023-2024 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,10 @@ package org.onap.cps.api.impl; import java.util.Collection; import lombok.RequiredArgsConstructor; import org.onap.cps.api.CpsAnchorService; +import org.onap.cps.impl.utils.CpsValidator; import org.onap.cps.spi.CpsAdminPersistenceService; import org.onap.cps.spi.CpsDataPersistenceService; import org.onap.cps.spi.model.Anchor; -import org.onap.cps.spi.utils.CpsValidator; import org.springframework.stereotype.Service; @Service @@ -44,28 +44,36 @@ public class CpsAnchorServiceImpl implements CpsAnchorService { } @Override + public Anchor getAnchor(final String dataspaceName, final String anchorName) { + cpsValidator.validateNameCharacters(dataspaceName, anchorName); + return cpsAdminPersistenceService.getAnchor(dataspaceName, anchorName); + } + + @Override public Collection<Anchor> getAnchors(final String dataspaceName) { cpsValidator.validateNameCharacters(dataspaceName); return cpsAdminPersistenceService.getAnchors(dataspaceName); } @Override - public Collection<Anchor> getAnchors(final String dataspaceName, final String schemaSetName) { - cpsValidator.validateNameCharacters(dataspaceName, schemaSetName); - return cpsAdminPersistenceService.getAnchors(dataspaceName, schemaSetName); + public Collection<Anchor> getAnchors(final String dataspaceName, final Collection<String> anchorNames) { + cpsValidator.validateNameCharacters(dataspaceName); + cpsValidator.validateNameCharacters(anchorNames); + return cpsAdminPersistenceService.getAnchors(dataspaceName, anchorNames); } @Override - public Collection<Anchor> getAnchors(final String dataspaceName, final Collection<String> schemaSetNames) { - cpsValidator.validateNameCharacters(dataspaceName); - cpsValidator.validateNameCharacters(schemaSetNames); - return cpsAdminPersistenceService.getAnchors(dataspaceName, schemaSetNames); + public Collection<Anchor> getAnchorsBySchemaSetName(final String dataspaceName, final String schemaSetName) { + cpsValidator.validateNameCharacters(dataspaceName, schemaSetName); + return cpsAdminPersistenceService.getAnchorsBySchemaSetName(dataspaceName, schemaSetName); } @Override - public Anchor getAnchor(final String dataspaceName, final String anchorName) { - cpsValidator.validateNameCharacters(dataspaceName, anchorName); - return cpsAdminPersistenceService.getAnchor(dataspaceName, anchorName); + public Collection<Anchor> getAnchorsBySchemaSetNames(final String dataspaceName, + final Collection<String> schemaSetNames) { + cpsValidator.validateNameCharacters(dataspaceName); + cpsValidator.validateNameCharacters(schemaSetNames); + return cpsAdminPersistenceService.getAnchorsBySchemaSetNames(dataspaceName, schemaSetNames); } @Override diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java index 5a48428772..eed4f09bf0 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java @@ -42,6 +42,7 @@ import org.onap.cps.api.CpsDeltaService; import org.onap.cps.cpspath.parser.CpsPathUtil; import org.onap.cps.events.CpsDataUpdateEventsService; import org.onap.cps.events.model.Data.Operation; +import org.onap.cps.impl.utils.CpsValidator; import org.onap.cps.spi.CpsDataPersistenceService; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.exceptions.DataValidationException; @@ -49,7 +50,6 @@ import org.onap.cps.spi.model.Anchor; import org.onap.cps.spi.model.DataNode; import org.onap.cps.spi.model.DataNodeBuilder; import org.onap.cps.spi.model.DeltaReport; -import org.onap.cps.spi.utils.CpsValidator; import org.onap.cps.utils.ContentType; import org.onap.cps.utils.DataMapUtils; import org.onap.cps.utils.JsonObjectMapper; @@ -119,12 +119,13 @@ public class CpsDataServiceImpl implements CpsDataService { @Override @Timed(value = "cps.data.service.list.element.save", description = "Time taken to save list elements") - public void saveListElements(final String dataspaceName, final String anchorName, final String parentNodeXpath, - final String jsonData, final OffsetDateTime observedTimestamp) { + public void saveListElements(final String dataspaceName, final String anchorName, + final String parentNodeXpath, final String nodeData, + final OffsetDateTime observedTimestamp, final ContentType contentType) { cpsValidator.validateNameCharacters(dataspaceName, anchorName); final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName); final Collection<DataNode> listElementDataNodeCollection = - buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, jsonData, ContentType.JSON); + buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, nodeData, contentType); if (isRootNodeXpath(parentNodeXpath)) { cpsDataPersistenceService.storeDataNodes(dataspaceName, anchorName, listElementDataNodeCollection); } else { @@ -251,12 +252,12 @@ public class CpsDataServiceImpl implements CpsDataService { @Timed(value = "cps.data.service.datanode.descendants.update", description = "Time taken to update a data node and descendants") public void updateDataNodeAndDescendants(final String dataspaceName, final String anchorName, - final String parentNodeXpath, final String jsonData, - final OffsetDateTime observedTimestamp) { + final String parentNodeXpath, final String nodeData, + final OffsetDateTime observedTimestamp, final ContentType contentType) { cpsValidator.validateNameCharacters(dataspaceName, anchorName); final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName); final Collection<DataNode> dataNodes = - buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, jsonData, ContentType.JSON); + buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, nodeData, contentType); cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, dataNodes); sendDataUpdatedEvent(anchor, parentNodeXpath, Operation.UPDATE, observedTimestamp); } @@ -265,13 +266,13 @@ public class CpsDataServiceImpl implements CpsDataService { @Timed(value = "cps.data.service.datanode.descendants.batch.update", description = "Time taken to update a batch of data nodes and descendants") public void updateDataNodesAndDescendants(final String dataspaceName, final String anchorName, - final Map<String, String> nodesJsonData, - final OffsetDateTime observedTimestamp) { + final Map<String, String> nodeDataPerXPath, + final OffsetDateTime observedTimestamp, final ContentType contentType) { cpsValidator.validateNameCharacters(dataspaceName, anchorName); final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName); - final Collection<DataNode> dataNodes = buildDataNodesWithParentNodeXpath(anchor, nodesJsonData); + final Collection<DataNode> dataNodes = buildDataNodesWithParentNodeXpath(anchor, nodeDataPerXPath, contentType); cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, dataNodes); - nodesJsonData.keySet().forEach(nodeXpath -> + nodeDataPerXPath.keySet().forEach(nodeXpath -> sendDataUpdatedEvent(anchor, nodeXpath, Operation.UPDATE, observedTimestamp)); } @@ -399,8 +400,7 @@ public class CpsDataServiceImpl implements CpsDataService { private List<Map<String, Object>> prefixResolver(final Anchor anchor, final Collection<DataNode> dataNodes) { final List<Map<String, Object>> prefixToDataNodes = new ArrayList<>(dataNodes.size()); for (final DataNode dataNode: dataNodes) { - final String prefix = prefixResolver - .getPrefix(anchor.getDataspaceName(), anchor.getName(), dataNode.getXpath()); + final String prefix = prefixResolver.getPrefix(anchor, dataNode.getXpath()); final Map<String, Object> prefixToDataNode = DataMapUtils.toDataMapWithIdentifier(dataNode, prefix); prefixToDataNodes.add(prefixToDataNode); } @@ -408,11 +408,12 @@ public class CpsDataServiceImpl implements CpsDataService { } private Collection<DataNode> buildDataNodesWithParentNodeXpath(final Anchor anchor, - final Map<String, String> nodesJsonData) { + final Map<String, String> nodesJsonData, + final ContentType contentType) { final Collection<DataNode> dataNodes = new ArrayList<>(); for (final Map.Entry<String, String> nodeJsonData : nodesJsonData.entrySet()) { dataNodes.addAll(buildDataNodesWithParentNodeXpath(anchor, nodeJsonData.getKey(), - nodeJsonData.getValue(), ContentType.JSON)); + nodeJsonData.getValue(), contentType)); } return dataNodes; } diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataspaceServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataspaceServiceImpl.java index a7f5da4874..6bccf2a865 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataspaceServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataspaceServiceImpl.java @@ -26,9 +26,9 @@ package org.onap.cps.api.impl; import java.util.Collection; import lombok.RequiredArgsConstructor; import org.onap.cps.api.CpsDataspaceService; +import org.onap.cps.impl.utils.CpsValidator; import org.onap.cps.spi.CpsAdminPersistenceService; import org.onap.cps.spi.model.Dataspace; -import org.onap.cps.spi.utils.CpsValidator; import org.springframework.stereotype.Service; @Service diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDeltaServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDeltaServiceImpl.java index 2f99dbf7bb..7819568ae1 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDeltaServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDeltaServiceImpl.java @@ -20,7 +20,6 @@ package org.onap.cps.api.impl; - import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; @@ -179,7 +178,7 @@ public class CpsDeltaServiceImpl implements CpsDeltaService { final List<DeltaReport> updatedDeltaReportEntries) { for (final Map.Entry<Map<String, Serializable>, Map<String, Serializable>> entry: updatedLeavesAsSourceDataToTargetData.entrySet()) { - final DeltaReport updatedDataForDeltaReport = new DeltaReportBuilder().actionUpdate() + final DeltaReport updatedDataForDeltaReport = new DeltaReportBuilder().actionReplace() .withXpath(xpath).withSourceData(entry.getKey()).withTargetData(entry.getValue()).build(); updatedDeltaReportEntries.add(updatedDataForDeltaReport); } @@ -195,7 +194,7 @@ public class CpsDeltaServiceImpl implements CpsDeltaService { for (final Map.Entry<String, DataNode> entry: xpathToAddedNodes.entrySet()) { final String xpath = entry.getKey(); final DataNode dataNode = entry.getValue(); - final DeltaReport addedDataForDeltaReport = new DeltaReportBuilder().actionAdd().withXpath(xpath) + final DeltaReport addedDataForDeltaReport = new DeltaReportBuilder().actionCreate().withXpath(xpath) .withTargetData(dataNode.getLeaves()).build(); addedDeltaReportEntries.add(addedDataForDeltaReport); } diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java index 14b949e5ae..a600b22b61 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java @@ -30,6 +30,7 @@ import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.onap.cps.api.CpsAnchorService; import org.onap.cps.api.CpsModuleService; +import org.onap.cps.impl.utils.CpsValidator; import org.onap.cps.spi.CascadeDeleteAllowed; import org.onap.cps.spi.CpsModulePersistenceService; import org.onap.cps.spi.exceptions.SchemaSetInUseException; @@ -37,7 +38,6 @@ import org.onap.cps.spi.model.Anchor; import org.onap.cps.spi.model.ModuleDefinition; import org.onap.cps.spi.model.ModuleReference; import org.onap.cps.spi.model.SchemaSet; -import org.onap.cps.spi.utils.CpsValidator; import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder; import org.onap.cps.yang.YangTextSchemaSourceSet; import org.springframework.stereotype.Service; @@ -97,7 +97,7 @@ public class CpsModuleServiceImpl implements CpsModuleService { public void deleteSchemaSet(final String dataspaceName, final String schemaSetName, final CascadeDeleteAllowed cascadeDeleteAllowed) { cpsValidator.validateNameCharacters(dataspaceName, schemaSetName); - final Collection<Anchor> anchors = cpsAnchorService.getAnchors(dataspaceName, schemaSetName); + final Collection<Anchor> anchors = cpsAnchorService.getAnchorsBySchemaSetName(dataspaceName, schemaSetName); if (!anchors.isEmpty() && isCascadeDeleteProhibited(cascadeDeleteAllowed)) { throw new SchemaSetInUseException(dataspaceName, schemaSetName); } @@ -114,8 +114,9 @@ public class CpsModuleServiceImpl implements CpsModuleService { public void deleteSchemaSetsWithCascade(final String dataspaceName, final Collection<String> schemaSetNames) { cpsValidator.validateNameCharacters(dataspaceName); cpsValidator.validateNameCharacters(schemaSetNames); - final Collection<String> anchorNames = cpsAnchorService.getAnchors(dataspaceName, schemaSetNames) - .stream().map(Anchor::getName).collect(Collectors.toSet()); + final Collection<String> anchorNames = + cpsAnchorService.getAnchorsBySchemaSetNames(dataspaceName, schemaSetNames) + .stream().map(Anchor::getName).collect(Collectors.toSet()); cpsAnchorService.deleteAnchors(dataspaceName, anchorNames); cpsModulePersistenceService.deleteSchemaSets(dataspaceName, schemaSetNames); cpsModulePersistenceService.deleteUnusedYangResourceModules(); @@ -170,6 +171,17 @@ public class CpsModuleServiceImpl implements CpsModuleService { return cpsModulePersistenceService.identifyNewModuleReferences(moduleReferencesToCheck); } + @Timed(value = "cps.module.service.module.reference.query", + description = "Time taken to query list of module references") + @Override + public Collection<ModuleReference> getModuleReferencesByAttribute(final String dataspaceName, + final String anchorName, + final Map<String, String> parentAttributes, + final Map<String, String> childAttributes) { + return cpsModulePersistenceService.getModuleReferencesByAttribute(dataspaceName, anchorName, parentAttributes, + childAttributes); + } + private boolean isCascadeDeleteProhibited(final CascadeDeleteAllowed cascadeDeleteAllowed) { return CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED == cascadeDeleteAllowed; } diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java index 1d7a7ceeb0..d1c98986e6 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java @@ -25,11 +25,11 @@ import io.micrometer.core.annotation.Timed; import java.util.Collection; import lombok.RequiredArgsConstructor; import org.onap.cps.api.CpsQueryService; +import org.onap.cps.impl.utils.CpsValidator; import org.onap.cps.spi.CpsDataPersistenceService; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.PaginationOption; import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.utils.CpsValidator; import org.springframework.stereotype.Service; @Service diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java b/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java index 4fdae5a307..8b85dfca32 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java @@ -27,8 +27,8 @@ import io.micrometer.core.instrument.Metrics; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import lombok.RequiredArgsConstructor; +import org.onap.cps.impl.utils.CpsValidator; import org.onap.cps.spi.CpsModulePersistenceService; -import org.onap.cps.spi.utils.CpsValidator; import org.onap.cps.yang.YangTextSchemaSourceSet; import org.onap.cps.yang.YangTextSchemaSourceSetBuilder; import org.springframework.cache.annotation.CacheConfig; diff --git a/cps-service/src/main/java/org/onap/cps/cache/AnchorDataCacheConfig.java b/cps-service/src/main/java/org/onap/cps/cache/AnchorDataCacheConfig.java deleted file mode 100644 index efe19c6cb7..0000000000 --- a/cps-service/src/main/java/org/onap/cps/cache/AnchorDataCacheConfig.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * ============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.cache; - -import com.hazelcast.config.MapConfig; -import com.hazelcast.map.IMap; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Core infrastructure of the hazelcast distributed cache for anchor data config use cases. - */ -@Configuration -public class AnchorDataCacheConfig extends HazelcastCacheConfig { - - private static final MapConfig anchorDataCacheMapConfig = createMapConfig("anchorDataCacheMapConfig"); - - /** - * Distributed instance of anchor data cache that contains module prefix by anchor name as properties. - * - * @return configured map of anchor data cache - */ - @Bean - public IMap<String, AnchorDataCacheEntry> anchorDataCache() { - return createHazelcastInstance("hazelCastInstanceCpsCore", anchorDataCacheMapConfig).getMap("anchorDataCache"); - } -} diff --git a/cps-service/src/main/java/org/onap/cps/cache/AnchorDataCacheEntry.java b/cps-service/src/main/java/org/onap/cps/cache/AnchorDataCacheEntry.java deleted file mode 100644 index 41adbdd5dc..0000000000 --- a/cps-service/src/main/java/org/onap/cps/cache/AnchorDataCacheEntry.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * ============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.cache; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -public class AnchorDataCacheEntry implements Serializable { - - private static final long serialVersionUID = 2111243947810370698L; - - private Map<String, Serializable> properties = new HashMap<>(); - - public Object getProperty(final String propertyName) { - return properties.get(propertyName); - } - - public void setProperty(final String propertyName, final Serializable value) { - properties.put(propertyName, value); - } - - public boolean hasProperty(final String propertyName) { - return properties.containsKey(propertyName); - } -} diff --git a/cps-service/src/main/java/org/onap/cps/cache/HazelcastCacheConfig.java b/cps-service/src/main/java/org/onap/cps/cache/HazelcastCacheConfig.java deleted file mode 100644 index 418de9b17a..0000000000 --- a/cps-service/src/main/java/org/onap/cps/cache/HazelcastCacheConfig.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * ============LICENSE_START======================================================== - * Copyright (C) 2023-2024 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.cache; - -import com.hazelcast.config.Config; -import com.hazelcast.config.MapConfig; -import com.hazelcast.config.NamedConfig; -import com.hazelcast.config.QueueConfig; -import com.hazelcast.config.RestEndpointGroup; -import com.hazelcast.config.SetConfig; -import com.hazelcast.core.Hazelcast; -import com.hazelcast.core.HazelcastInstance; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; - -/** - * Core infrastructure of the hazelcast distributed cache. - */ -@Slf4j -public class HazelcastCacheConfig { - - @Value("${hazelcast.cluster-name}") - protected String clusterName; - - @Value("${hazelcast.mode.kubernetes.enabled}") - protected boolean cacheKubernetesEnabled; - - @Value("${hazelcast.mode.kubernetes.service-name}") - protected String cacheKubernetesServiceName; - - protected HazelcastInstance createHazelcastInstance(final String hazelcastInstanceName, - final NamedConfig namedConfig) { - return Hazelcast.newHazelcastInstance(initializeConfig(hazelcastInstanceName, namedConfig)); - } - - private Config initializeConfig(final String instanceName, final NamedConfig namedConfig) { - final Config config = new Config(instanceName); - if (namedConfig instanceof MapConfig) { - config.addMapConfig((MapConfig) namedConfig); - } - if (namedConfig instanceof QueueConfig) { - config.addQueueConfig((QueueConfig) namedConfig); - } - if (namedConfig instanceof SetConfig) { - config.addSetConfig((SetConfig) namedConfig); - } - - config.setClusterName(clusterName); - config.setClassLoader(org.onap.cps.spi.model.Dataspace.class.getClassLoader()); - exposeClusterInformation(config); - updateDiscoveryMode(config); - return config; - } - - protected static MapConfig createMapConfig(final String configName) { - final MapConfig mapConfig = new MapConfig(configName); - mapConfig.setBackupCount(1); - return mapConfig; - } - - protected static QueueConfig createQueueConfig(final String configName) { - final QueueConfig commonQueueConfig = new QueueConfig(configName); - commonQueueConfig.setBackupCount(1); - return commonQueueConfig; - } - - protected static SetConfig createSetConfig(final String configName) { - final SetConfig commonSetConfig = new SetConfig(configName); - commonSetConfig.setBackupCount(1); - return commonSetConfig; - } - - protected void updateDiscoveryMode(final Config config) { - if (cacheKubernetesEnabled) { - log.info("Enabling kubernetes mode with service-name : {}", cacheKubernetesServiceName); - config.getNetworkConfig().getJoin().getKubernetesConfig().setEnabled(true) - .setProperty("service-name", cacheKubernetesServiceName); - } - } - - protected void exposeClusterInformation(final Config config) { - config.getNetworkConfig().getRestApiConfig().setEnabled(true) - .enableGroups(RestEndpointGroup.HEALTH_CHECK, RestEndpointGroup.CLUSTER_READ); - } - -} diff --git a/cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java b/cps-service/src/main/java/org/onap/cps/impl/utils/CpsValidator.java index ceb75c09b2..fd677eb2d2 100644 --- a/cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java +++ b/cps-service/src/main/java/org/onap/cps/impl/utils/CpsValidator.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.spi.utils; +package org.onap.cps.impl.utils; import org.onap.cps.spi.PaginationOption; diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java index 2b21619cb7..25830a55de 100755 --- a/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java +++ b/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020-2022 Nordix Foundation. + * Copyright (C) 2020-2024 Nordix Foundation. * Modifications Copyright (C) 2020-2022 Bell Canada. * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2022 TechMahindra Ltd. @@ -73,30 +73,48 @@ public interface CpsAdminPersistenceService { void createAnchor(String dataspaceName, String schemaSetName, String anchorName); /** - * Read all anchors associated with the given schema-set in the given dataspace. + * Get an anchor in the given dataspace using the anchor name. + * + * @param dataspaceName dataspace name + * @param anchorName anchor name + * @return an anchor + */ + Anchor getAnchor(String dataspaceName, String anchorName); + + /** + * Read all anchors in the given a dataspace. * * @param dataspaceName dataspace name - * @param schemaSetName schema-set name * @return a collection of anchors */ - Collection<Anchor> getAnchors(String dataspaceName, String schemaSetName); + Collection<Anchor> getAnchors(String dataspaceName); /** - * Read all anchors associated with multiple schema-sets in the given dataspace. + * Read all anchors in the given dataspace with the anchor names. * - * @param dataspaceName dataspace name - * @param schemaSetNames schema-set names + * @param dataspaceName dataspace name + * @param anchorNames anchor names * @return a collection of anchors */ - Collection<Anchor> getAnchors(String dataspaceName, Collection<String> schemaSetNames); + Collection<Anchor> getAnchors(String dataspaceName, Collection<String> anchorNames); /** - * Read all anchors in the given a dataspace. + * Read all anchors associated with the given schema-set in the given dataspace. * * @param dataspaceName dataspace name + * @param schemaSetName schema-set name * @return a collection of anchors */ - Collection<Anchor> getAnchors(String dataspaceName); + Collection<Anchor> getAnchorsBySchemaSetName(String dataspaceName, String schemaSetName); + + /** + * Read all anchors associated with multiple schema-sets in the given dataspace. + * + * @param dataspaceName dataspace name + * @param schemaSetNames schema-set names + * @return a collection of anchors + */ + Collection<Anchor> getAnchorsBySchemaSetNames(String dataspaceName, Collection<String> schemaSetNames); /** * Query anchor names for the given module names in the provided dataspace. @@ -110,15 +128,6 @@ public interface CpsAdminPersistenceService { Collection<String> queryAnchorNames(String dataspaceName, Collection<String> moduleNames); /** - * Get an anchor in the given dataspace using the anchor name. - * - * @param dataspaceName dataspace name - * @param anchorName anchor name - * @return an anchor - */ - Anchor getAnchor(String dataspaceName, String anchorName); - - /** * Delete anchor by name in given dataspace. * * @param dataspaceName dataspace name diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java index eeaaa47991..793f38e4bc 100755 --- a/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java +++ b/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java @@ -153,4 +153,20 @@ public interface CpsModulePersistenceService { Collection<ModuleReference> identifyNewModuleReferences( Collection<ModuleReference> moduleReferencesToCheck); + /** + * Retrieves module references based on the specified dataspace, anchor, and attribute filters. + + * Constructs and executes a SQL query to find module references by applying filters for parent and child fragments. + * Uses `parentAttributes` for filtering parent fragments and `childAttributes` for filtering child fragments. + * + * @param dataspaceName the name of the dataspace to filter on. + * @param anchorName the name of the anchor to filter on. + * @param parentAttributes a map of attributes for filtering parent fragments. + * @param childAttributes a map of attributes for filtering child fragments. + * @return a collection of {@link ModuleReference} objects matching the criteria. + */ + Collection<ModuleReference> getModuleReferencesByAttribute(final String dataspaceName, final String anchorName, + final Map<String, String> parentAttributes, + final Map<String, String> childAttributes); + } diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DeltaReport.java b/cps-service/src/main/java/org/onap/cps/spi/model/DeltaReport.java index 34715e70b9..c6270a41d2 100644 --- a/cps-service/src/main/java/org/onap/cps/spi/model/DeltaReport.java +++ b/cps-service/src/main/java/org/onap/cps/spi/model/DeltaReport.java @@ -32,9 +32,9 @@ import lombok.Setter; @JsonInclude(JsonInclude.Include.NON_NULL) public class DeltaReport { - public static final String ADD_ACTION = "add"; + public static final String CREATE_ACTION = "create"; public static final String REMOVE_ACTION = "remove"; - public static final String UPDATE_ACTION = "update"; + public static final String REPLACE_ACTION = "replace"; DeltaReport() {} diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DeltaReportBuilder.java b/cps-service/src/main/java/org/onap/cps/spi/model/DeltaReportBuilder.java index 1e151eeb2d..a7e7aae215 100644 --- a/cps-service/src/main/java/org/onap/cps/spi/model/DeltaReportBuilder.java +++ b/cps-service/src/main/java/org/onap/cps/spi/model/DeltaReportBuilder.java @@ -48,8 +48,8 @@ public class DeltaReportBuilder { return this; } - public DeltaReportBuilder actionAdd() { - this.action = DeltaReport.ADD_ACTION; + public DeltaReportBuilder actionCreate() { + this.action = DeltaReport.CREATE_ACTION; return this; } @@ -58,8 +58,8 @@ public class DeltaReportBuilder { return this; } - public DeltaReportBuilder actionUpdate() { - this.action = DeltaReport.UPDATE_ACTION; + public DeltaReportBuilder actionReplace() { + this.action = DeltaReport.REPLACE_ACTION; return this; } diff --git a/cps-service/src/main/java/org/onap/cps/utils/PrefixResolver.java b/cps-service/src/main/java/org/onap/cps/utils/PrefixResolver.java index 35dc7347b2..c3097cc552 100644 --- a/cps-service/src/main/java/org/onap/cps/utils/PrefixResolver.java +++ b/cps-service/src/main/java/org/onap/cps/utils/PrefixResolver.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation. + * Copyright (C) 2022-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,53 +20,25 @@ package org.onap.cps.utils; -import com.hazelcast.map.IMap; -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; import lombok.RequiredArgsConstructor; -import org.onap.cps.api.CpsAnchorService; import org.onap.cps.api.impl.YangTextSchemaSourceSetCache; -import org.onap.cps.cache.AnchorDataCacheEntry; import org.onap.cps.cpspath.parser.CpsPathPrefixType; import org.onap.cps.cpspath.parser.CpsPathQuery; import org.onap.cps.cpspath.parser.CpsPathUtil; import org.onap.cps.spi.model.Anchor; import org.onap.cps.yang.YangTextSchemaSourceSet; -import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor public class PrefixResolver { - private static final long ANCHOR_DATA_CACHE_TTL_SECS = TimeUnit.HOURS.toSeconds(1); - - private static final String CACHE_ENTRY_PROPERTY_NAME = "prefixPerContainerName"; - - private final CpsAnchorService cpsAnchorService; - private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache; - private final IMap<String, AnchorDataCacheEntry> anchorDataCache; - - /** - * Get the module prefix for the given xpath for a dataspace and anchor name. - * - * @param dataspaceName the name of the dataspace - * @param anchorName the name of the anchor the xpath belongs to - * @param xpath the xpath to prefix a prefix for - * @return the prefix of the module the top level element of given xpath - */ - public String getPrefix(final String dataspaceName, final String anchorName, final String xpath) { - final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName); - return getPrefix(anchor, xpath); - } - /** * Get the module prefix for the given xpath under the given anchor. * @@ -75,57 +47,25 @@ public class PrefixResolver { * @return the prefix of the module the top level element of given xpath */ public String getPrefix(final Anchor anchor, final String xpath) { - final Map<String, String> prefixPerContainerName = getPrefixPerContainerName(anchor); - return getPrefixForTopContainer(prefixPerContainerName, xpath); - } - - private Map<String, String> getPrefixPerContainerName(final Anchor anchor) { - if (anchorDataCache.containsKey(anchor.getName())) { - final AnchorDataCacheEntry anchorDataCacheEntry = anchorDataCache.get(anchor.getName()); - if (anchorDataCacheEntry.hasProperty(CACHE_ENTRY_PROPERTY_NAME)) { - return (Map) anchorDataCacheEntry.getProperty(CACHE_ENTRY_PROPERTY_NAME); - } - } - return createAndCachePrefixPerContainerNameMap(anchor); - } - - private String getPrefixForTopContainer(final Map<String, String> prefixPerContainerName, - final String xpath) { final CpsPathQuery cpsPathQuery = CpsPathUtil.getCpsPathQuery(xpath); - if (cpsPathQuery.getCpsPathPrefixType() == CpsPathPrefixType.ABSOLUTE) { - final String topLevelContainerName = cpsPathQuery.getContainerNames().get(0); - if (prefixPerContainerName.containsKey(topLevelContainerName)) { - return prefixPerContainerName.get(topLevelContainerName); - } + if (cpsPathQuery.getCpsPathPrefixType() != CpsPathPrefixType.ABSOLUTE) { + return ""; } - return ""; - } + final String topLevelContainerName = cpsPathQuery.getContainerNames().get(0); - private Map<String, String> createAndCachePrefixPerContainerNameMap(final Anchor anchor) { final YangTextSchemaSourceSet yangTextSchemaSourceSet = - yangTextSchemaSourceSetCache.get(anchor.getDataspaceName(), anchor.getSchemaSetName()); + yangTextSchemaSourceSetCache.get(anchor.getDataspaceName(), anchor.getSchemaSetName()); final SchemaContext schemaContext = yangTextSchemaSourceSet.getSchemaContext(); - final Map<QNameModule, String> prefixPerQNameModule = new HashMap<>(schemaContext.getModules().size()); - for (final Module module : schemaContext.getModules()) { - prefixPerQNameModule.put(module.getQNameModule(), module.getPrefix()); - } - final HashMap<String, String> prefixPerContainerName = new HashMap<>(); - for (final DataSchemaNode dataSchemaNode : schemaContext.getChildNodes()) { - if (dataSchemaNode instanceof DataNodeContainer) { - final String containerName = dataSchemaNode.getQName().getLocalName(); - final String prefix = prefixPerQNameModule.get(dataSchemaNode.getQName().getModule()); - prefixPerContainerName.put(containerName, prefix); - } - } - cachePrefixPerContainerNameMap(anchor.getName(), prefixPerContainerName); - return prefixPerContainerName; - } - private void cachePrefixPerContainerNameMap(final String anchorName, - final Serializable prefixPerContainerName) { - final AnchorDataCacheEntry anchorDataCacheEntry = new AnchorDataCacheEntry(); - anchorDataCacheEntry.setProperty(CACHE_ENTRY_PROPERTY_NAME, prefixPerContainerName); - anchorDataCache.put(anchorName, anchorDataCacheEntry, ANCHOR_DATA_CACHE_TTL_SECS, TimeUnit.SECONDS); + return schemaContext.getChildNodes().stream() + .filter(DataNodeContainer.class::isInstance) + .map(SchemaNode::getQName) + .filter(qname -> qname.getLocalName().equals(topLevelContainerName)) + .findFirst() + .map(QName::getModule) + .flatMap(schemaContext::findModule) + .map(Module::getPrefix) + .orElse(""); } } diff --git a/cps-service/src/main/java/org/onap/cps/utils/YangParserHelper.java b/cps-service/src/main/java/org/onap/cps/utils/YangParserHelper.java index 5cadd29368..597164598a 100644 --- a/cps-service/src/main/java/org/onap/cps/utils/YangParserHelper.java +++ b/cps-service/src/main/java/org/onap/cps/utils/YangParserHelper.java @@ -120,13 +120,9 @@ public class YangParserHelper { try (jsonParserStream) { jsonParserStream.parse(jsonReader); - } catch (final IOException | JsonSyntaxException exception) { + } catch (final IOException | JsonSyntaxException | IllegalStateException | IllegalArgumentException exception) { throw new DataValidationException( - "Failed to parse json data: " + jsonData, exception.getMessage(), exception); - } catch (final IllegalStateException | IllegalArgumentException exception) { - throw new DataValidationException( - "Failed to parse json data. Unsupported xpath or json data:" + jsonData, exception - .getMessage(), exception); + "Data Validation Failed", "Failed to parse json data. " + exception.getMessage(), exception); } return dataContainerNodeBuilder.build(); } @@ -168,7 +164,7 @@ public class YangParserHelper { } catch (final XMLStreamException | URISyntaxException | IOException | SAXException | NullPointerException | ParserConfigurationException | TransformerException exception) { throw new DataValidationException( - "Failed to parse xml data: " + xmlData, exception.getMessage(), exception); + "Data Validation Failed", "Failed to parse xml data: " + exception.getMessage(), exception); } final DataContainerChild dataContainerChild = (DataContainerChild) getFirstChildXmlRoot(normalizedNodeResult.getResult()); diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy index c7865386bc..ccf943a470 100644 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation + * Copyright (C) 2023-2024 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,11 @@ package org.onap.cps.api.impl +import org.onap.cps.impl.utils.CpsValidator import org.onap.cps.spi.CpsAdminPersistenceService import org.onap.cps.spi.CpsDataPersistenceService import org.onap.cps.spi.exceptions.ModuleNamesNotFoundException import org.onap.cps.spi.model.Anchor -import org.onap.cps.spi.utils.CpsValidator import spock.lang.Specification class CpsAnchorServiceImplSpec extends Specification { @@ -59,9 +59,9 @@ class CpsAnchorServiceImplSpec extends Specification { def 'Retrieve all anchors for schema-set.'() { given: 'that anchor is associated with the dataspace and schemaset' def anchors = [new Anchor()] - mockCpsAdminPersistenceService.getAnchors('someDataspace', 'someSchemaSet') >> anchors + mockCpsAdminPersistenceService.getAnchorsBySchemaSetName('someDataspace', 'someSchemaSet') >> anchors when: 'get anchors is called for a dataspace name and schema set name' - def result = objectUnderTest.getAnchors('someDataspace', 'someSchemaSet') + def result = objectUnderTest.getAnchorsBySchemaSetName('someDataspace', 'someSchemaSet') then: 'the collection provided by persistence service is returned as result' result == anchors and: 'the CpsValidator is called on the dataspaceName, schemaSetName' @@ -71,9 +71,9 @@ class CpsAnchorServiceImplSpec extends Specification { def 'Retrieve all anchors for multiple schema-sets.'() { given: 'that anchor is associated with the dataspace and schemasets' def anchors = [new Anchor(), new Anchor()] - mockCpsAdminPersistenceService.getAnchors('someDataspace', _ as Collection<String>) >> anchors + mockCpsAdminPersistenceService.getAnchorsBySchemaSetNames('someDataspace', _ as Collection<String>) >> anchors when: 'get anchors is called for a dataspace name and schema set names' - def result = objectUnderTest.getAnchors('someDataspace', ['schemaSet1', 'schemaSet2']) + def result = objectUnderTest.getAnchorsBySchemaSetNames('someDataspace', ['schemaSet1', 'schemaSet2']) then: 'the collection provided by persistence service is returned as result' result == anchors and: 'the CpsValidator is called on the dataspace name and schema-set names' @@ -93,6 +93,21 @@ class CpsAnchorServiceImplSpec extends Specification { 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someAnchor') } + def 'Retrieve multiple anchors for dataspace and provided anchor names.'() { + given: 'multiple anchors names to get' + def anchorNames = ['anchor1', 'anchor2'] + and: 'that anchors are associated with the dataspace and anchor names' + def anchors = [new Anchor(), new Anchor()] + mockCpsAdminPersistenceService.getAnchors('someDataspace', anchorNames) >> anchors + when: 'get anchors is called for a dataspace name and anchor names' + def result = objectUnderTest.getAnchors('someDataspace', anchorNames) + then: 'the collection provided by persistence service is returned as result' + result == anchors + and: 'the CpsValidator is called on the dataspace name and anchor names' + 1 * mockCpsValidator.validateNameCharacters('someDataspace') + 1 * mockCpsValidator.validateNameCharacters(anchorNames) + } + def 'Delete anchor.'() { when: 'delete anchor is invoked' objectUnderTest.deleteAnchor('someDataspace','someAnchor') @@ -105,15 +120,17 @@ class CpsAnchorServiceImplSpec extends Specification { } def 'Delete multiple anchors.'() { + given: 'multiple anchors to delete' + def anchorNames = ['anchor1', 'anchor2'] when: 'delete anchors is invoked' - objectUnderTest.deleteAnchors('someDataspace', ['anchor1', 'anchor2']) + objectUnderTest.deleteAnchors('someDataspace', anchorNames) then: 'delete data nodes is invoked on the data service with expected parameters' - 1 * mockCpsDataPersistenceService.deleteDataNodes('someDataspace', _ as Collection<String>) + 1 * mockCpsDataPersistenceService.deleteDataNodes('someDataspace', anchorNames) and: 'the persistence service method is invoked with same parameters to delete anchor' - 1 * mockCpsAdminPersistenceService.deleteAnchors('someDataspace',_ as Collection<String>) + 1 * mockCpsAdminPersistenceService.deleteAnchors('someDataspace', anchorNames) and: 'the CpsValidator is called on the dataspace name and anchor names' 1 * mockCpsValidator.validateNameCharacters('someDataspace') - 1 * mockCpsValidator.validateNameCharacters(_) + 1 * mockCpsValidator.validateNameCharacters(anchorNames) } def 'Query all anchor identifiers for a dataspace and module names.'() { diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy index edf25715b3..9846b30158 100644 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy @@ -23,14 +23,15 @@ package org.onap.cps.api.impl -import com.fasterxml.jackson.databind.ObjectMapper import ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger import ch.qos.logback.core.read.ListAppender +import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.TestUtils import org.onap.cps.api.CpsAnchorService import org.onap.cps.api.CpsDeltaService import org.onap.cps.events.CpsDataUpdateEventsService +import org.onap.cps.impl.utils.CpsValidator import org.onap.cps.spi.CpsDataPersistenceService import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.exceptions.ConcurrencyException @@ -40,12 +41,11 @@ import org.onap.cps.spi.exceptions.SessionManagerException import org.onap.cps.spi.exceptions.SessionTimeoutException import org.onap.cps.spi.model.Anchor import org.onap.cps.spi.model.DataNodeBuilder -import org.onap.cps.spi.utils.CpsValidator import org.onap.cps.utils.ContentType -import org.onap.cps.utils.YangParser -import org.onap.cps.utils.YangParserHelper import org.onap.cps.utils.JsonObjectMapper import org.onap.cps.utils.PrefixResolver +import org.onap.cps.utils.YangParser +import org.onap.cps.utils.YangParserHelper import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder import org.onap.cps.yang.YangTextSchemaSourceSet import org.onap.cps.yang.YangTextSchemaSourceSetBuilder @@ -53,8 +53,11 @@ import org.slf4j.LoggerFactory import org.springframework.context.annotation.AnnotationConfigApplicationContext import spock.lang.Shared import spock.lang.Specification + import java.time.OffsetDateTime +import static org.onap.cps.events.model.Data.Operation.DELETE + class CpsDataServiceImplSpec extends Specification { def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService) def mockCpsAnchorService = Mock(CpsAnchorService) @@ -130,8 +133,8 @@ class CpsDataServiceImplSpec extends Specification { where: 'given parameters' scenario | invalidData | contentType || expectedMessage 'no data nodes' | '{}' | ContentType.JSON || 'No data nodes' - 'invalid json' | '{invalid json' | ContentType.JSON || 'Failed to parse json data' - 'invalid xml' | '<invalid xml' | ContentType.XML || 'Failed to parse xml data' + 'invalid json' | '{invalid json' | ContentType.JSON || 'Data Validation Failed' + 'invalid xml' | '<invalid xml' | ContentType.XML || 'Data Validation Failed' } def 'Saving list element data fragment under Root node.'() { @@ -139,7 +142,7 @@ class CpsDataServiceImplSpec extends Specification { setupSchemaSetMocks('bookstore.yang') when: 'save data method is invoked with list element json data' def jsonData = '{"bookstore-address":[{"bookstore-name":"Easons","address":"Dublin,Ireland","postal-code":"D02HA21"}]}' - objectUnderTest.saveListElements(dataspaceName, anchorName, '/', jsonData, observedTimestamp) + objectUnderTest.saveListElements(dataspaceName, anchorName, '/', jsonData, observedTimestamp, ContentType.JSON) then: 'the persistence service method is invoked with correct parameters' 1 * mockCpsDataPersistenceService.storeDataNodes(dataspaceName, anchorName, { dataNodeCollection -> @@ -167,12 +170,11 @@ class CpsDataServiceImplSpec extends Specification { 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName) } - def 'Saving list element data fragment under existing node.'() { + def 'Saving list element data fragment under existing JSON/XML node.'() { given: 'schema set for given anchor and dataspace references test-tree model' setupSchemaSetMocks('test-tree.yang') - when: 'save data method is invoked with list element json data' - def jsonData = '{"branch": [{"name": "A"}, {"name": "B"}]}' - objectUnderTest.saveListElements(dataspaceName, anchorName, '/test-tree', jsonData, observedTimestamp) + when: 'save data method is invoked with list element data' + objectUnderTest.saveListElements(dataspaceName, anchorName, '/test-tree', data, observedTimestamp, contentType) then: 'the persistence service method is invoked with correct parameters' 1 * mockCpsDataPersistenceService.addListElements(dataspaceName, anchorName, '/test-tree', { dataNodeCollection -> @@ -185,16 +187,23 @@ class CpsDataServiceImplSpec extends Specification { ) and: 'the CpsValidator is called on the dataspaceName and AnchorName' 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName) + where: + data | contentType + '{"branch": [{"name": "A"}, {"name": "B"}]}' | ContentType.JSON + '<test-tree xmlns="org:onap:cps:test:test-tree"><branch><name>A</name></branch><branch><name>B</name></branch></test-tree>' | ContentType.XML } - def 'Saving empty list element data fragment.'() { + def 'Saving empty list element data fragment for JSON/XML data.'() { given: 'schema set for given anchor and dataspace references test-tree model' setupSchemaSetMocks('test-tree.yang') when: 'save data method is invoked with an empty list' - def jsonData = '{"branch": []}' - objectUnderTest.saveListElements(dataspaceName, anchorName, '/test-tree', jsonData, observedTimestamp) + objectUnderTest.saveListElements(dataspaceName, anchorName, '/test-tree', data, observedTimestamp, contentType) then: 'invalid data exception is thrown' thrown(DataValidationException) + where: + data | contentType + '{"branch": []}' | ContentType.JSON + '<test-tree><branch></branch></test-tree>' | ContentType.XML } def 'Get all data nodes #scenario.'() { @@ -360,11 +369,11 @@ class CpsDataServiceImplSpec extends Specification { 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName) } - def 'Replace data node using singular data node: #scenario.'() { + def 'Replace data node using singular JSON data node: #scenario.'() { given: 'schema set for given anchor and dataspace references test-tree model' setupSchemaSetMocks('test-tree.yang') when: 'replace data method is invoked with json data #jsonData and parent node xpath #parentNodeXpath' - objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, jsonData, observedTimestamp) + objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, jsonData, observedTimestamp, ContentType.JSON) then: 'the persistence service method is invoked with correct parameters' 1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, { dataNode -> dataNode.xpath == expectedNodeXpath}) @@ -377,30 +386,63 @@ class CpsDataServiceImplSpec extends Specification { 'json list' | '/test-tree' | '{"branch": [{"name":"Name1"}, {"name":"Name2"}]}' || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"] } - def 'Replace data node using multiple data nodes: #scenario.'() { + def 'Replace data node using singular XML data node: #scenario.'() { + given: 'schema set for given anchor and dataspace references test-tree model' + setupSchemaSetMocks('test-tree.yang') + when: 'replace data method is invoked with XML data #xmlData and parent node xpath #parentNodeXpath' + objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, xmlData, observedTimestamp, ContentType.XML) + then: 'the persistence service method is invoked with correct parameters' + 1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, + { dataNode -> dataNode.xpath == expectedNodeXpath }) + and: 'the CpsValidator is called on the dataspaceName and AnchorName' + 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName) + where: 'following parameters were used' + scenario | parentNodeXpath | xmlData || expectedNodeXpath + 'level 2 node' | '/test-tree' | '<branch><name>Name</name></branch>' || ['/test-tree/branch[@name=\'Name\']'] + 'xml list' | '/test-tree' | '<test-tree xmlns="org:onap:cps:test:test-tree"><branch><name>Name1</name></branch>' + '<branch><name>Name2</name></branch></test-tree>' || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"] + } + + def 'Replace data node using multiple JSON data nodes: #scenario.'() { given: 'schema set for given anchor and dataspace references test-tree model' setupSchemaSetMocks('test-tree.yang') when: 'replace data method is invoked with a map of xpaths and json data' - objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, nodesJsonData, observedTimestamp) + objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, nodeDataPerXPath, observedTimestamp, ContentType.JSON) then: 'the persistence service method is invoked with correct parameters' 1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, { dataNode -> dataNode.xpath == expectedNodeXpath}) and: 'the CpsValidator is called on the dataspaceName and AnchorName' 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName) where: 'following parameters were used' - scenario | nodesJsonData || expectedNodeXpath + scenario | nodeDataPerXPath || expectedNodeXpath 'top level node' | ['/' : '{"test-tree": {"branch": []}}', '/test-tree' : '{"branch": [{"name":"Name"}]}'] || ["/test-tree", "/test-tree/branch[@name='Name']"] 'level 2 node' | ['/test-tree' : '{"branch": [{"name":"Name"}]}', '/test-tree/branch[@name=\'Name\']':'{"nest":{"name":"nestName"}}'] || ["/test-tree/branch[@name='Name']", "/test-tree/branch[@name='Name']/nest"] 'json list' | ['/test-tree' : '{"branch": [{"name":"Name1"}, {"name":"Name2"}]}'] || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"] } + def 'Replace data node using multiple XML data nodes: #scenario.'() { + given: 'schema set for given anchor and dataspace references test-tree model' + setupSchemaSetMocks('test-tree.yang') + when: 'replace data method is invoked with a map of xpaths and XML data' + objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, nodeXmlDataPerXPath, observedTimestamp, ContentType.XML) + then: 'the persistence service method is invoked with correct parameters' + 1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, + { dataNode -> dataNode.xpath == expectedNodeXpath }) + and: 'the CpsValidator is called on the dataspaceName and AnchorName' + 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName) + where: 'following parameters were used' + scenario | nodeXmlDataPerXPath || expectedNodeXpath + 'top level node' | ['/test-tree': '<branch><name>Name</name></branch>'] || ["/test-tree/branch[@name='Name']"] + 'level 2 node' | ['/test-tree': '<branch><name>Name</name></branch>', '/test-tree/branch[@name=\'Name\']': '<nest><name>nestName</name></nest>'] || ["/test-tree/branch[@name='Name']", "/test-tree/branch[@name='Name']/nest"] + 'xml list' | ['/test-tree': '<test-tree xmlns="org:onap:cps:test:test-tree"><branch><name>Name1</name></branch>' + '<branch><name>Name2</name></branch></test-tree>'] || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"] + } + def 'Replace data node with concurrency exception in persistence layer.'() { given: 'the persistence layer throws an concurrency exception' def originalException = new ConcurrencyException('message', 'details') mockCpsDataPersistenceService.updateDataNodesAndDescendants(*_) >> { throw originalException } setupSchemaSetMocks('test-tree.yang') when: 'attempt to replace data node' - objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, ['/' : '{"test-tree": {}}'] , observedTimestamp) + objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, ['/' : '{"test-tree": {}}'] , observedTimestamp, ContentType.JSON) then: 'the same exception is thrown up' def thrownUp = thrown(ConcurrencyException) assert thrownUp == originalException @@ -489,15 +531,19 @@ class CpsDataServiceImplSpec extends Specification { def 'Delete all data nodes for given dataspace and multiple anchors.'() { given: 'schema set for given anchors and dataspace references test tree model' setupSchemaSetMocks('test-tree.yang') - mockCpsAnchorService.getAnchors(dataspaceName, ['anchor1', 'anchor2']) >> - [new Anchor(name: 'anchor1', dataspaceName: dataspaceName), - new Anchor(name: 'anchor2', dataspaceName: dataspaceName)] + def anchor1 = new Anchor(name: 'anchor1', dataspaceName: dataspaceName) + def anchor2 = new Anchor(name: 'anchor2', dataspaceName: dataspaceName) + mockCpsAnchorService.getAnchors(dataspaceName, ['anchor1', 'anchor2']) >> [anchor1, anchor2] when: 'delete data node method is invoked with correct parameters' objectUnderTest.deleteDataNodes(dataspaceName, ['anchor1', 'anchor2'], observedTimestamp) then: 'the CpsValidator is called on the dataspace name and the anchor names' - 2 * mockCpsValidator.validateNameCharacters(_) + 1 * mockCpsValidator.validateNameCharacters(dataspaceName) + 1 * mockCpsValidator.validateNameCharacters(['anchor1', 'anchor2']) and: 'the persistence service method is invoked with the correct parameters' 1 * mockCpsDataPersistenceService.deleteDataNodes(dataspaceName, _ as Collection<String>) + and: 'a data update event is sent for each anchor' + 1 * mockDataUpdateEventsService.publishCpsDataUpdateEvent(anchor1, '/', DELETE, observedTimestamp) + 1 * mockDataUpdateEventsService.publishCpsDataUpdateEvent(anchor2, '/', DELETE, observedTimestamp) } def 'Start session.'() { diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataspaceServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataspaceServiceImplSpec.groovy index 8e17594bd1..ac7d4c0aa7 100644 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataspaceServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataspaceServiceImplSpec.groovy @@ -20,9 +20,9 @@ package org.onap.cps.api.impl +import org.onap.cps.impl.utils.CpsValidator import org.onap.cps.spi.CpsAdminPersistenceService import org.onap.cps.spi.model.Dataspace -import org.onap.cps.spi.utils.CpsValidator import spock.lang.Specification class CpsDataspaceServiceImplSpec extends Specification { diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDeltaServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDeltaServiceImplSpec.groovy index 42d75f3eab..f12afe61ec 100644 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDeltaServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDeltaServiceImplSpec.groovy @@ -51,8 +51,8 @@ class CpsDeltaServiceImplSpec extends Specification{ def 'Get delta between data nodes for ADDED data'() { when: 'attempt to get delta between 2 data nodes' def result = objectUnderTest.getDeltaReports([], targetDataNodeWithLeafData) - then: 'the delta report contains expected "add" action' - assert result[0].action.equals('add') + then: 'the delta report contains expected "create" action' + assert result[0].action.equals('create') and: 'the delta report contains expected xpath' assert result[0].xpath == '/parent' and: 'the delta report contains no source data' @@ -68,12 +68,12 @@ class CpsDeltaServiceImplSpec extends Specification{ when: 'attempt to get delta between 2 data nodes' def result = objectUnderTest.getDeltaReports(sourceDataNode, targetDataNode) then: 'the delta report contains expected details for parent node' - assert result[0].action.equals('update') + assert result[0].action.equals('replace') assert result[0].xpath == '/parent' assert result[0].sourceData == ['parent-leaf': 'parent-payload'] assert result[0].targetData == ['parent-leaf': 'parent-payload-updated'] and: 'the delta report contains expected details for child node' - assert result[1].action.equals('update') + assert result[1].action.equals('replace') assert result[1].xpath == '/parent/child' assert result[1].sourceData == ['child-leaf': 'child-payload'] assert result[1].targetData == ['child-leaf': 'child-payload-updated'] @@ -82,8 +82,8 @@ class CpsDeltaServiceImplSpec extends Specification{ def 'Delta report between leaves, #scenario'() { when: 'attempt to get delta between 2 data nodes' def result = objectUnderTest.getDeltaReports(sourceDataNode, targetDataNode) - then: 'the delta report contains expected "update" action' - assert result[0].action.equals('update') + then: 'the delta report contains expected "replace" action' + assert result[0].action.equals('replace') and: 'the delta report contains expected xpath' assert result[0].xpath == '/parent' and: 'the delta report contains expected source and target data' @@ -100,7 +100,7 @@ class CpsDeltaServiceImplSpec extends Specification{ def 'Get delta between data nodes for updated data, where source and target data nodes have no leaves '() { when: 'attempt to get delta between 2 data nodes' def result = objectUnderTest.getDeltaReports(sourceDataNodeWithoutLeafData, targetDataNodeWithoutLeafData) - then: 'the delta report contains "update" action with right data' + then: 'the delta report is empty' assert result.isEmpty() } } diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy index 0bad0de6ac..1831506563 100644 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy @@ -23,19 +23,15 @@ package org.onap.cps.api.impl -import org.onap.cps.api.CpsAnchorService - -import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED -import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED - import org.onap.cps.TestUtils +import org.onap.cps.api.CpsAnchorService +import org.onap.cps.impl.utils.CpsValidator import org.onap.cps.spi.CpsModulePersistenceService import org.onap.cps.spi.exceptions.DuplicatedYangResourceException import org.onap.cps.spi.exceptions.ModelValidationException import org.onap.cps.spi.exceptions.SchemaSetInUseException -import org.onap.cps.spi.model.ModuleDefinition -import org.onap.cps.spi.utils.CpsValidator import org.onap.cps.spi.model.Anchor +import org.onap.cps.spi.model.ModuleDefinition import org.onap.cps.spi.model.ModuleReference import org.onap.cps.spi.model.SchemaSet import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder @@ -43,6 +39,9 @@ import org.onap.cps.yang.YangTextSchemaSourceSet import org.onap.cps.yang.YangTextSchemaSourceSetBuilder import spock.lang.Specification +import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED +import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED + class CpsModuleServiceImplSpec extends Specification { def mockCpsModulePersistenceService = Mock(CpsModulePersistenceService) @@ -134,7 +133,7 @@ class CpsModuleServiceImplSpec extends Specification { def 'Delete schema-set when cascade is allowed.'() { given: '#numberOfAnchors anchors are associated with schemaset' def associatedAnchors = createAnchors(numberOfAnchors) - mockCpsAnchorService.getAnchors('my-dataspace', 'my-schemaset') >> associatedAnchors + mockCpsAnchorService.getAnchorsBySchemaSetName('my-dataspace', 'my-schemaset') >> associatedAnchors when: 'schema set deletion is requested with cascade allowed' objectUnderTest.deleteSchemaSet('my-dataspace', 'my-schemaset', CASCADE_DELETE_ALLOWED) then: 'anchor deletion is called #numberOfAnchors times' @@ -153,7 +152,7 @@ class CpsModuleServiceImplSpec extends Specification { def 'Delete schema-set when cascade is prohibited.'() { given: 'no anchors are associated with schemaset' - mockCpsAnchorService.getAnchors('my-dataspace', 'my-schemaset') >> Collections.emptyList() + mockCpsAnchorService.getAnchorsBySchemaSetName('my-dataspace', 'my-schemaset') >> Collections.emptyList() when: 'schema set deletion is requested with cascade allowed' objectUnderTest.deleteSchemaSet('my-dataspace', 'my-schemaset', CASCADE_DELETE_PROHIBITED) then: 'no anchors are deleted' @@ -170,7 +169,7 @@ class CpsModuleServiceImplSpec extends Specification { def 'Delete schema-set when cascade is prohibited and schema-set has anchors.'() { given: '2 anchors are associated with schemaset' - mockCpsAnchorService.getAnchors('my-dataspace', 'my-schemaset') >> createAnchors(2) + mockCpsAnchorService.getAnchorsBySchemaSetName('my-dataspace', 'my-schemaset') >> createAnchors(2) when: 'schema set deletion is requested with cascade allowed' objectUnderTest.deleteSchemaSet('my-dataspace', 'my-schemaset', CASCADE_DELETE_PROHIBITED) then: 'Schema-Set in Use exception is thrown' @@ -179,7 +178,7 @@ class CpsModuleServiceImplSpec extends Specification { def 'Delete multiple schema-sets when cascade is allowed.'() { given: '#numberOfAnchors anchors are associated with each schemaset' - mockCpsAnchorService.getAnchors('my-dataspace', ['my-schemaset1', 'my-schemaset2']) >> createAnchors(numberOfAnchors * 2) + mockCpsAnchorService.getAnchorsBySchemaSetNames('my-dataspace', ['my-schemaset1', 'my-schemaset2']) >> createAnchors(numberOfAnchors * 2) when: 'schema set deletion is requested with cascade allowed' objectUnderTest.deleteSchemaSetsWithCascade('my-dataspace', ['my-schemaset1', 'my-schemaset2']) then: 'anchor deletion is called #numberOfAnchors times' @@ -238,6 +237,23 @@ class CpsModuleServiceImplSpec extends Specification { 1 * mockCpsModulePersistenceService.identifyNewModuleReferences(moduleReferencesToCheck) } + def 'Get module references when queried by attributes'() { + given: 'a valid dataspace name and anchor name' + def dataspaceName = 'someDataspace' + def anchorName = 'someAnchor' + and: 'a set of parent attributes and child attributes used for filtering' + def parentAttributes = ['some-property-key1': 'some-property-val1'] + def childAttributes = ['some-property-key2': 'some-property-val2'] + and: 'a list of expected module references returned by the persistence service' + def expectedModuleReferences = [new ModuleReference(moduleName: 'some-name', revision: 'some-revision')] + mockCpsModulePersistenceService.getModuleReferencesByAttribute(dataspaceName, anchorName, parentAttributes, childAttributes) >> expectedModuleReferences + when: 'the method is invoked to retrieve module references by attributes' + def actualModuleReferences = objectUnderTest.getModuleReferencesByAttribute(dataspaceName, anchorName, parentAttributes, childAttributes) + then: 'the retrieved module references should match the expected module references' + assert actualModuleReferences == expectedModuleReferences + } + + def 'Getting module definitions with module name'() { given: 'module persistence service returns module definitions for module name' def moduleDefinitionsFromPersistenceService = [ new ModuleDefinition('name', 'revision', 'content' ) ] diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsQueryServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsQueryServiceImplSpec.groovy index 1ad5017919..3b10669ddb 100644 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsQueryServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsQueryServiceImplSpec.groovy @@ -21,10 +21,10 @@ package org.onap.cps.api.impl +import org.onap.cps.impl.utils.CpsValidator import org.onap.cps.spi.CpsDataPersistenceService import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.PaginationOption -import org.onap.cps.spi.utils.CpsValidator import spock.lang.Specification class CpsQueryServiceImplSpec extends Specification { diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy index 9e55e8f10a..05c8983fc2 100755 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy @@ -28,13 +28,13 @@ import org.onap.cps.TestUtils import org.onap.cps.api.CpsAnchorService
import org.onap.cps.api.CpsDeltaService
import org.onap.cps.events.CpsDataUpdateEventsService
+import org.onap.cps.impl.utils.CpsValidator
import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.CpsModulePersistenceService
import org.onap.cps.spi.model.Anchor
-import org.onap.cps.spi.utils.CpsValidator
+import org.onap.cps.utils.ContentType
import org.onap.cps.utils.JsonObjectMapper
import org.onap.cps.utils.PrefixResolver
-import org.onap.cps.utils.ContentType
import org.onap.cps.utils.YangParser
import org.onap.cps.utils.YangParserHelper
import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy index a9f50ee5b0..189e28521b 100644 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy @@ -22,6 +22,7 @@ package org.onap.cps.api.impl import org.onap.cps.TestUtils +import org.onap.cps.impl.utils.CpsValidator import org.onap.cps.spi.CpsModulePersistenceService import org.onap.cps.yang.YangTextSchemaSourceSet import org.onap.cps.yang.YangTextSchemaSourceSetBuilder @@ -34,8 +35,6 @@ import org.springframework.cache.annotation.EnableCaching import org.springframework.cache.caffeine.CaffeineCacheManager import org.springframework.test.context.ContextConfiguration import spock.lang.Specification -import org.onap.cps.spi.utils.CpsValidator - @SpringBootTest @EnableCaching diff --git a/cps-service/src/test/groovy/org/onap/cps/cache/AnchorDataCacheConfigSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/cache/AnchorDataCacheConfigSpec.groovy deleted file mode 100644 index 010308c42f..0000000000 --- a/cps-service/src/test/groovy/org/onap/cps/cache/AnchorDataCacheConfigSpec.groovy +++ /dev/null @@ -1,80 +0,0 @@ -/* - * ============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.cache - -import com.hazelcast.config.Config -import com.hazelcast.core.Hazelcast -import com.hazelcast.map.IMap -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.ContextConfiguration -import spock.lang.Specification - -@SpringBootTest -@ContextConfiguration(classes = [AnchorDataCacheConfig]) -class AnchorDataCacheConfigSpec extends Specification { - - @Autowired - private IMap<String, AnchorDataCacheEntry> anchorDataCache - - def 'Embedded (hazelcast) cache for Anchor Data.'() { - expect: 'system is able to create an instance of the Anchor data cache' - assert null != anchorDataCache - and: 'there is at least 1 instance' - assert Hazelcast.allHazelcastInstances.size() > 0 - and: 'anchorDataCache is present' - assert Hazelcast.allHazelcastInstances.name.contains('hazelCastInstanceCpsCore') - } - - def 'Verify configs for Distributed Caches'(){ - given: 'the Anchor Data Cache config' - def anchorDataCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelCastInstanceCpsCore').config - def anchorDataCacheMapConfig = anchorDataCacheConfig.mapConfigs.get('anchorDataCacheMapConfig') - expect: 'system created instance with correct config' - assert anchorDataCacheConfig.clusterName == 'cps-and-ncmp-test-caches' - assert anchorDataCacheMapConfig.backupCount == 1 - assert anchorDataCacheMapConfig.asyncBackupCount == 0 - } - - def 'Verify deployment network configs for Distributed Caches'() { - given: 'the Anchor Data Cache config' - def anchorDataCacheNetworkConfig = Hazelcast.getHazelcastInstanceByName('hazelCastInstanceCpsCore').config.networkConfig - expect: 'system created instance with correct config' - assert anchorDataCacheNetworkConfig.join.autoDetectionConfig.enabled - assert !anchorDataCacheNetworkConfig.join.kubernetesConfig.enabled - } - - def 'Verify network config'() { - given: 'Synchronization config object and test configuration' - def objectUnderTest = new AnchorDataCacheConfig() - def testConfig = new Config() - when: 'kubernetes properties are enabled' - objectUnderTest.cacheKubernetesEnabled = true - objectUnderTest.cacheKubernetesServiceName = 'test-service-name' - and: 'method called to update the discovery mode' - objectUnderTest.updateDiscoveryMode(testConfig) - then: 'applied properties are reflected' - assert testConfig.networkConfig.join.kubernetesConfig.enabled - assert testConfig.networkConfig.join.kubernetesConfig.properties.get('service-name') == 'test-service-name' - - } - -} diff --git a/cps-service/src/test/groovy/org/onap/cps/cache/AnchorDataCacheEntrySpec.groovy b/cps-service/src/test/groovy/org/onap/cps/cache/AnchorDataCacheEntrySpec.groovy deleted file mode 100644 index f38b45d17c..0000000000 --- a/cps-service/src/test/groovy/org/onap/cps/cache/AnchorDataCacheEntrySpec.groovy +++ /dev/null @@ -1,40 +0,0 @@ -/* - * ============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.cache - - -import spock.lang.Specification - -class AnchorDataCacheEntrySpec extends Specification { - - def objectUnderTest = new AnchorDataCacheEntry() - - def 'Anchor Data Cache Properties Management.'() { - when: 'a property named "sample" is added to the cache' - objectUnderTest.setProperty('sample', 123) - then: 'the cache has that property' - assert objectUnderTest.hasProperty('sample') - and: 'the value is correct' - assert objectUnderTest.getProperty('sample') == 123 - and: 'the cache does not have an an object called "something else"' - assert objectUnderTest.hasProperty('something else') == false - } -} diff --git a/cps-service/src/test/groovy/org/onap/cps/cache/HazelcastCacheConfigSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/cache/HazelcastCacheConfigSpec.groovy deleted file mode 100644 index 022cd74ea6..0000000000 --- a/cps-service/src/test/groovy/org/onap/cps/cache/HazelcastCacheConfigSpec.groovy +++ /dev/null @@ -1,76 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 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.cache - -import com.hazelcast.config.Config -import com.hazelcast.config.RestEndpointGroup -import spock.lang.Specification - -class HazelcastCacheConfigSpec extends Specification { - - def objectUnderTest = new HazelcastCacheConfig() - - def 'Create Hazelcast instance with a #scenario'() { - given: 'a cluster name' - objectUnderTest.clusterName = 'my cluster' - when: 'an hazelcast instance is created (name has to be unique)' - def result = objectUnderTest.createHazelcastInstance(scenario, config) - then: 'the instance is created and has the correct name' - assert result.name == scenario - and: 'if applicable it has a map config with the expected name' - if (expectMapConfig) { - assert result.config.mapConfigs.values()[0].name == 'my map config' - } else { - assert result.config.mapConfigs.isEmpty() - } - and: 'if applicable it has a queue config with the expected name' - if (expectQueueConfig) { - assert result.config.queueConfigs.values()[0].name == 'my queue config' - } else { - assert result.config.queueConfigs.isEmpty() - } - and: 'if applicable it has a set config with the expected name' - if (expectSetConfig) { - assert result.config.setConfigs.values()[0].name == 'my set config' - } else { - assert result.config.setConfigs.isEmpty() - } - where: 'the following configs are used' - scenario | config || expectMapConfig | expectQueueConfig | expectSetConfig - 'Map Config' | HazelcastCacheConfig.createMapConfig('my map config') || true | false | false - 'Queue Config' | HazelcastCacheConfig.createQueueConfig('my queue config') || false | true | false - 'Set Config' | HazelcastCacheConfig.createSetConfig('my set config') || false | false | true - } - - def 'Verify Hazelcast Cluster Information'() { - given: 'a test configuration' - def testConfig = new Config() - when: 'cluster information is exposed' - objectUnderTest.exposeClusterInformation(testConfig) - then: 'REST api configs are enabled' - assert testConfig.networkConfig.restApiConfig.enabled - and: 'only health check and cluster read are enabled' - def enabledGroups = testConfig.networkConfig.restApiConfig.enabledGroups - assert enabledGroups.size() == 2 - assert enabledGroups.containsAll([RestEndpointGroup.CLUSTER_READ, RestEndpointGroup.HEALTH_CHECK]) - } - -} diff --git a/cps-service/src/test/groovy/org/onap/cps/spi/model/DeltaReportBuilderSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/spi/model/DeltaReportBuilderSpec.groovy index e19d120421..00b5499c2f 100644 --- a/cps-service/src/test/groovy/org/onap/cps/spi/model/DeltaReportBuilderSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/spi/model/DeltaReportBuilderSpec.groovy @@ -24,20 +24,20 @@ import spock.lang.Specification class DeltaReportBuilderSpec extends Specification{ - def 'Generating delta report with for add action'() { + def 'Generating delta report for "create" action'() { when: 'delta report is generated' def result = new DeltaReportBuilder() - .actionAdd() + .actionCreate() .withXpath('/xpath') .withTargetData(['data':'leaf-data']) .build() - then: 'the delta report contains the "add" action with expected target data' - assert result.action == 'add' + then: 'the delta report contains the "create" action with expected target data' + assert result.action == 'create' assert result.xpath == '/xpath' assert result.targetData == ['data': 'leaf-data'] } - def 'Generating delta report with attributes for remove action'() { + def 'Generating delta report with attributes for "remove" action'() { when: 'delta report is generated' def result = new DeltaReportBuilder() .actionRemove() diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy index 8cbd493550..09d45b92c0 100644 --- a/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy @@ -42,7 +42,7 @@ class JsonObjectMapperSpec extends Specification { def contentMap = new JsonSlurper().parseText(new String(content)) and: 'the parsed content is as expected' assert contentMap.'test:bookstore'.'bookstore-name' == 'Chapters/Easons' - where: 'the following data stores are used' + where: 'the following content types are used' type << ['String', 'bytes'] } diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/PrefixResolverSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/PrefixResolverSpec.groovy index b975de6555..13b042f1ae 100644 --- a/cps-service/src/test/groovy/org/onap/cps/utils/PrefixResolverSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/utils/PrefixResolverSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation + * Copyright (C) 2021-2024 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2021-2022 Bell Canada. * ================================================================================ @@ -22,11 +22,8 @@ package org.onap.cps.utils -import com.hazelcast.map.IMap import org.onap.cps.TestUtils -import org.onap.cps.api.CpsAnchorService import org.onap.cps.api.impl.YangTextSchemaSourceSetCache -import org.onap.cps.cache.AnchorDataCacheEntry import org.onap.cps.spi.model.Anchor import org.onap.cps.yang.YangTextSchemaSourceSet import org.onap.cps.yang.YangTextSchemaSourceSetBuilder @@ -34,13 +31,9 @@ import spock.lang.Specification class PrefixResolverSpec extends Specification { - def mockCpsAnchorService = Mock(CpsAnchorService) - def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache) - def mockAnchorDataCache = Mock(IMap<String, AnchorDataCacheEntry>) - - def objectUnderTest = new PrefixResolver(mockCpsAnchorService, mockYangTextSchemaSourceSetCache, mockAnchorDataCache) + def objectUnderTest = new PrefixResolver(mockYangTextSchemaSourceSetCache) def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet) @@ -48,29 +41,16 @@ class PrefixResolverSpec extends Specification { def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext() - def setup() { - given: 'an anchor for the test-tree model' - def anchor = new Anchor(dataspaceName: 'testDataspace', name: 'testAnchor') - and: 'the system can get this anchor' - mockCpsAnchorService.getAnchor('testDataspace', 'testAnchor') >> anchor - and: 'the schema source cache contains the schema context for the test-tree module' - mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext - } + def anchor = new Anchor(dataspaceName: 'testDataspace', name: 'testAnchor') def 'get xpath prefix using node schema context'() { + given: 'the schema source cache contains the schema context for the test-tree module' + mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext + mockYangTextSchemaSourceSetCache.get(*_) >> mockYangTextSchemaSourceSet when: 'the prefix of the yang module is retrieved' - def result = objectUnderTest.getPrefix('testDataspace', 'testAnchor', xpath) + def result = objectUnderTest.getPrefix(anchor, xpath) then: 'the expected prefix is returned' result == expectedPrefix - and: 'the cache is updated for the given anchor with a map of prefixes per top level container (just one one this case)' - 1 * mockAnchorDataCache.put('testAnchor',_ , _ ,_) >> { args -> { - def prefixPerContainerName = args[1].getProperty("prefixPerContainerName") - assert prefixPerContainerName.size() == 1 - assert prefixPerContainerName.get('test-tree') == 'tree' - } - } - and: 'schema source cache is used (i.e. need to build schema context)' - 1 * mockYangTextSchemaSourceSetCache.get(*_) >> mockYangTextSchemaSourceSet where: 'the following scenarios are applied' xpath || expectedPrefix '/test-tree' || 'tree' @@ -82,37 +62,4 @@ class PrefixResolverSpec extends Specification { '/not-defined' || '' } - def 'get prefix with populated anchor data cache with #scenario cache entry'() { - given: 'anchor data cache is populated for the anchor with a prefix for top level container named #cachedTopLevelContainerName' - def anchorDataCacheEntry = new AnchorDataCacheEntry() - def prefixPerContainerName = [(cachedTopLevelContainerName): 'cachedPrefix'] - anchorDataCacheEntry.setProperty('prefixPerContainerName',prefixPerContainerName) - mockAnchorDataCache.containsKey('testAnchor') >> true - mockAnchorDataCache.get('testAnchor') >> anchorDataCacheEntry - when: 'the prefix of the yang module is retrieved' - def result = objectUnderTest.getPrefix('testDataspace', 'testAnchor', '/test-tree') - then: 'the expected prefix is returned' - result == expectedPrefix - and: 'schema source cache is not used (i.e. no need to build schema context)' - 0 * mockYangTextSchemaSourceSetCache.get(*_) - where: 'the following scenarios are applied' - scenario | cachedTopLevelContainerName || expectedPrefix - 'matching' | 'test-tree' || 'cachedPrefix' - 'non-matching' | 'other' || '' - } - - def 'get prefix with other (non relevant) data in anchor data cache'() { - given: 'anchor data cache is populated with non relevant other property' - def anchorDataCacheEntry = new AnchorDataCacheEntry() - anchorDataCacheEntry.setProperty('something else', 'does not matter') - mockAnchorDataCache.containsKey('testAnchor') >> true - mockAnchorDataCache.get('testAnchor') >> anchorDataCacheEntry - when: 'the prefix of the yang module is retrieved' - def result = objectUnderTest.getPrefix('testDataspace', 'testAnchor', '/test-tree') - then: 'the expected prefix is returned' - result == 'tree' - and: 'schema source cache is used (i.e. need to build schema context)' - 1 * mockYangTextSchemaSourceSetCache.get(*_) >> mockYangTextSchemaSourceSet - } - } diff --git a/cps-service/src/test/resources/application.yml b/cps-service/src/test/resources/application.yml index b666885f22..be71d37d2a 100644 --- a/cps-service/src/test/resources/application.yml +++ b/cps-service/src/test/resources/application.yml @@ -1,6 +1,6 @@ # ============LICENSE_START======================================================= # Copyright (c) 2021 Bell Canada. -# Modification Copyright (C) 2022 Nordix Foundation. +# Modification Copyright (C) 2022-2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -41,11 +41,3 @@ spring: logging: level: org.apache.kafka: ERROR - -# Custom Hazelcast Config. -hazelcast: - cluster-name: "cps-and-ncmp-test-caches" - mode: - kubernetes: - enabled: false - service-name: "cps-and-ncmp-service" |