diff options
21 files changed, 291 insertions, 102 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java index 3ebceed9d7..25c9f76660 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java @@ -42,6 +42,15 @@ public class NcmpServiceCmHandle { private String cmHandleId; @JsonSetter(nulls = Nulls.AS_EMPTY) + private String dmiServiceName; + + @JsonSetter(nulls = Nulls.AS_EMPTY) + private String dmiDataServiceName; + + @JsonSetter(nulls = Nulls.AS_EMPTY) + private String dmiModelServiceName; + + @JsonSetter(nulls = Nulls.AS_EMPTY) private Map<String, String> dmiProperties = Collections.emptyMap(); @JsonSetter(nulls = Nulls.AS_EMPTY) diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java index e13d3c2328..429a3790d4 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java @@ -34,8 +34,6 @@ import org.onap.cps.ncmp.api.datajobs.models.WriteOperation; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.models.RequiredDmiService; import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher; -import org.onap.cps.ncmp.impl.utils.YangDataConverter; -import org.onap.cps.spi.model.DataNode; import org.springframework.stereotype.Service; @Slf4j @@ -67,10 +65,8 @@ public class WriteRequestExaminer { final Map<ProducerKey, List<DmiWriteOperation>> dmiWriteOperationsPerProducerKey, final WriteOperation writeOperation) { log.debug("data job id for write operation is: {}", dataJobId); - final DataNode dataNode = alternateIdMatcher - .getCmHandleDataNodeByLongestMatchingAlternateId(writeOperation.path(), PATH_SEPARATOR); - - final YangModelCmHandle yangModelCmHandle = YangDataConverter.toYangModelCmHandle(dataNode); + final YangModelCmHandle yangModelCmHandle = alternateIdMatcher + .getYangModelCmHandleByLongestMatchingAlternateId(writeOperation.path(), PATH_SEPARATOR); final DmiWriteOperation dmiWriteOperation = createDmiWriteOperation(writeOperation, yangModelCmHandle); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameResolver.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameResolver.java new file mode 100644 index 0000000000..e9378daaec --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameResolver.java @@ -0,0 +1,92 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 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.ncmp.impl.dmi; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class DmiServiceNameResolver { + + /** + * Resolve a dmi service name. + * + * @param requiredService indicates what type of service is required + * @param yangModelCmHandle cm handle + * @return dmi service name + */ + public static String resolveDmiServiceName(final RequiredDmiService requiredService, + final YangModelCmHandle yangModelCmHandle) { + return resolveDmiServiceName(requiredService, + yangModelCmHandle.getDmiServiceName(), + yangModelCmHandle.getDmiDataServiceName(), + yangModelCmHandle.getDmiModelServiceName()); + } + + /** + * Resolve a dmi service name. + * + * @param requiredService indicates what type of service is required + * @param ncmpServiceCmHandle cm handle + * @return dmi service name + */ + public static String resolveDmiServiceName(final RequiredDmiService requiredService, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + return resolveDmiServiceName(requiredService, + ncmpServiceCmHandle.getDmiServiceName(), + ncmpServiceCmHandle.getDmiDataServiceName(), + ncmpServiceCmHandle.getDmiModelServiceName()); + } + + /** + * Resolve a dmi service name. + * + * @param requiredService indicates what type of service is required + * @param dmiPluginRegistration dmi plugin registration + * @return dmi service name + */ + public static String resolveDmiServiceName(final RequiredDmiService requiredService, + final DmiPluginRegistration dmiPluginRegistration) { + return resolveDmiServiceName(requiredService, + dmiPluginRegistration.getDmiPlugin(), + dmiPluginRegistration.getDmiDataPlugin(), + dmiPluginRegistration.getDmiModelPlugin()); + } + + private static String resolveDmiServiceName(final RequiredDmiService requiredService, + final String dmiServiceName, + final String dmiDataServiceName, + final String dmiModelServiceName) { + if (StringUtils.isBlank(dmiServiceName)) { + if (RequiredDmiService.DATA.equals(requiredService)) { + return dmiDataServiceName; + } + return dmiModelServiceName; + } + return dmiServiceName; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/AlternateIdChecker.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/AlternateIdChecker.java index 3600d6da32..8ebd456cda 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/AlternateIdChecker.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/AlternateIdChecker.java @@ -28,6 +28,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.springframework.stereotype.Service; @@ -96,8 +97,8 @@ public class AlternateIdChecker { .map(NcmpServiceCmHandle::getAlternateId) .filter(StringUtils::isNotBlank) .collect(Collectors.toSet()); - return inventoryPersistence.getCmHandleDataNodesByAlternateIds(alternateIdsToCheck).stream() - .map(dataNode -> (String) dataNode.getLeaves().get("alternate-id")) + return inventoryPersistence.getYangModelCmHandleByAlternateIds(alternateIdsToCheck).stream() + .map(YangModelCmHandle::getAlternateId) .collect(Collectors.toSet()); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java index e5dd937cc0..e39da06514 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java @@ -130,20 +130,20 @@ public interface InventoryPersistence extends NcmpPersistence { Collection<DataNode> getCmHandleDataNodeByCmHandleId(String cmHandleId); /** - * Get data node with the given alternate id. + * Get yang model cm handle with the given alternate id. * * @param alternateId alternate ID - * @return data node + * @return yang model cm handle */ - DataNode getCmHandleDataNodeByAlternateId(String alternateId); + YangModelCmHandle getYangModelCmHandleByAlternateId(String alternateId); /** - * Get data nodes for the given batch of alternate ids. + * Get yang model cm handles for the given batch of alternate ids. * * @param alternateIds alternate IDs - * @return data nodes + * @return yang model cm handles */ - Collection<DataNode> getCmHandleDataNodesByAlternateIds(Collection<String> alternateIds); + Collection<YangModelCmHandle> getYangModelCmHandleByAlternateIds(Collection<String> alternateIds); /** * Get collection of data nodes of given cm handles. @@ -168,7 +168,7 @@ public interface InventoryPersistence extends NcmpPersistence { * Check database if cm handle id exists if not return false. * * @param cmHandleId cmHandle Id - * @return Boolean + * @return boolean */ - Boolean isExistingCmHandleId(String cmHandleId); + boolean isExistingCmHandleId(String cmHandleId); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java index e468ed100a..f8a38100aa 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java @@ -189,24 +189,25 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv } @Override - public DataNode getCmHandleDataNodeByAlternateId(final String alternateId) { + public YangModelCmHandle getYangModelCmHandleByAlternateId(final String alternateId) { final String cpsPathForCmHandleByAlternateId = getCpsPathForCmHandleByAlternateId(alternateId); final Collection<DataNode> dataNodes = cmHandleQueryService .queryNcmpRegistryByCpsPath(cpsPathForCmHandleByAlternateId, OMIT_DESCENDANTS); if (dataNodes.isEmpty()) { throw new CmHandleNotFoundException(alternateId); } - return dataNodes.iterator().next(); + return YangDataConverter.toYangModelCmHandle(dataNodes.iterator().next()); } @Override - public Collection<DataNode> getCmHandleDataNodesByAlternateIds(final Collection<String> alternateIds) { + public Collection<YangModelCmHandle> getYangModelCmHandleByAlternateIds(final Collection<String> alternateIds) { if (alternateIds.isEmpty()) { return Collections.emptyList(); } final String cpsPathForCmHandlesByAlternateIds = getCpsPathForCmHandlesByAlternateIds(alternateIds); - return cmHandleQueryService.queryNcmpRegistryByCpsPath(cpsPathForCmHandlesByAlternateIds, - INCLUDE_ALL_DESCENDANTS); + final Collection<DataNode> dataNodes = cmHandleQueryService.queryNcmpRegistryByCpsPath( + cpsPathForCmHandlesByAlternateIds, INCLUDE_ALL_DESCENDANTS); + return YangDataConverter.toYangModelCmHandles(dataNodes); } @Override @@ -229,7 +230,7 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv } @Override - public Boolean isExistingCmHandleId(final String cmHandleId) { + public boolean isExistingCmHandleId(final String cmHandleId) { try { return !getCmHandleDataNodeByCmHandleId(cmHandleId).isEmpty(); } catch (final DataNodeNotFoundException exception) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java index 76ee286635..a262367e38 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java @@ -35,6 +35,7 @@ import lombok.Setter; import org.apache.commons.lang3.StringUtils; import org.onap.cps.ncmp.api.inventory.models.CompositeState; import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.dmi.DmiServiceNameResolver; import org.onap.cps.ncmp.impl.models.RequiredDmiService; /** @@ -129,8 +130,7 @@ public class YangModelCmHandle { yangModelCmHandle.setAlternateId(StringUtils.trimToEmpty(alternateId)); yangModelCmHandle.setDataProducerIdentifier(StringUtils.trimToEmpty(dataProducerIdentifier)); yangModelCmHandle.setDmiProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getDmiProperties())); - yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties( - ncmpServiceCmHandle.getPublicProperties())); + yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getPublicProperties())); yangModelCmHandle.setCompositeState(ncmpServiceCmHandle.getCompositeState()); return yangModelCmHandle; } @@ -138,17 +138,11 @@ public class YangModelCmHandle { /** * Resolve a dmi service name. * - * @param requiredService indicates what typo of service is required + * @param requiredService indicates what type of service is required * @return dmi service name */ public String resolveDmiServiceName(final RequiredDmiService requiredService) { - if (StringUtils.isBlank(dmiServiceName)) { - if (RequiredDmiService.DATA.equals(requiredService)) { - return dmiDataServiceName; - } - return dmiModelServiceName; - } - return dmiServiceName; + return DmiServiceNameResolver.resolveDmiServiceName(requiredService, this); } private static List<Property> asYangModelCmHandleProperties(final Map<String, String> propertiesAsMap) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java index a10e8ba308..b61e53854e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java @@ -23,6 +23,7 @@ package org.onap.cps.ncmp.impl.inventory.trustlevel; import com.hazelcast.map.IMap; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -31,6 +32,7 @@ import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; +import org.onap.cps.ncmp.impl.dmi.DmiServiceNameResolver; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.models.RequiredDmiService; @@ -60,12 +62,8 @@ public class TrustLevelManager { * @param dmiPluginRegistration a dmi plugin being registered */ public void registerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) { - final String dmiServiceName; - if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) { - dmiServiceName = dmiPluginRegistration.getDmiPlugin(); - } else { - dmiServiceName = dmiPluginRegistration.getDmiDataPlugin(); - } + final String dmiServiceName = DmiServiceNameResolver.resolveDmiServiceName(RequiredDmiService.DATA, + dmiPluginRegistration); trustLevelPerDmiPlugin.put(dmiServiceName, TrustLevel.COMPLETE); } @@ -146,9 +144,13 @@ public class TrustLevelManager { public void applyEffectiveTrustLevels(final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles) { final Set<String> cmHandleIds = getCmHandleIds(ncmpServiceCmHandles); final Map<String, TrustLevel> trustLevelPerCmHandleIdInBatch = trustLevelPerCmHandleId.getAll(cmHandleIds); + final Map<String, TrustLevel> trustLevelPerDmiPluginInBatch = new HashMap<>(trustLevelPerDmiPlugin); for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) { final String cmHandleId = ncmpServiceCmHandle.getCmHandleId(); - final TrustLevel dmiTrustLevel = TrustLevel.COMPLETE; // TODO: CPS-2375 + final String dmiDataServiceName = DmiServiceNameResolver.resolveDmiServiceName(RequiredDmiService.DATA, + ncmpServiceCmHandle); + final TrustLevel dmiTrustLevel = trustLevelPerDmiPluginInBatch.getOrDefault(dmiDataServiceName, + TrustLevel.NONE); final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandleIdInBatch.getOrDefault(cmHandleId, TrustLevel.NONE); final TrustLevel effectiveTrustLevel = dmiTrustLevel.getEffectiveTrustLevel(cmHandleTrustLevel); @@ -187,7 +189,7 @@ public class TrustLevelManager { private String getDmiServiceName(final String cmHandleId) { final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); - return yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA); + return DmiServiceNameResolver.resolveDmiServiceName(RequiredDmiService.DATA, yangModelCmHandle); } private void sendAvcNotificationIfRequired(final String notificationCandidateCmHandleId, diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java index 36c0cfa756..b97da2977a 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java @@ -21,15 +21,13 @@ package org.onap.cps.ncmp.impl.utils; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException; import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; -import org.onap.cps.spi.model.DataNode; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.springframework.stereotype.Service; -@Slf4j @Service @RequiredArgsConstructor public class AlternateIdMatcher { @@ -37,19 +35,21 @@ public class AlternateIdMatcher { private final InventoryPersistence inventoryPersistence; /** - * Get data node that matches longest alternate id by removing elements (as defined by the separator string) - * from right to left. If alternate id contains a hash then all elements after that hash are ignored. + * Get yang model cm handle that matches longest alternate id by removing elements + * (as defined by the separator string) from right to left. + * If alternate id contains a hash then all elements after that hash are ignored. * * @param alternateId alternate ID * @param separator a string that separates each element from the next. - * @return data node + * @return yang model cm handle */ - public DataNode getCmHandleDataNodeByLongestMatchingAlternateId(final String alternateId, final String separator) { + public YangModelCmHandle getYangModelCmHandleByLongestMatchingAlternateId(final String alternateId, + final String separator) { final String[] splitPath = alternateId.split("#", 2); String bestMatch = splitPath[0]; while (StringUtils.isNotEmpty(bestMatch)) { try { - return inventoryPersistence.getCmHandleDataNodeByAlternateId(bestMatch); + return inventoryPersistence.getYangModelCmHandleByAlternateId(bestMatch); } catch (final CmHandleNotFoundException ignored) { bestMatch = getParentPath(bestMatch, separator); } @@ -67,8 +67,7 @@ public class AlternateIdMatcher { if (inventoryPersistence.isExistingCmHandleId(cmHandleReference)) { return cmHandleReference; } else { - return inventoryPersistence.getCmHandleDataNodeByAlternateId(cmHandleReference) - .getLeaves().get("id").toString(); + return inventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference).getId(); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java index ac0c44e1c3..1842107f44 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java @@ -47,12 +47,14 @@ public class YangDataConverter { * @param yangModelCmHandle the yang model of the cm handle * @return ncmp service cm handle */ - public static NcmpServiceCmHandle toNcmpServiceCmHandle( - final YangModelCmHandle yangModelCmHandle) { + public static NcmpServiceCmHandle toNcmpServiceCmHandle(final YangModelCmHandle yangModelCmHandle) { final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); final List<YangModelCmHandle.Property> dmiProperties = yangModelCmHandle.getDmiProperties(); final List<YangModelCmHandle.Property> publicProperties = yangModelCmHandle.getPublicProperties(); ncmpServiceCmHandle.setCmHandleId(yangModelCmHandle.getId()); + ncmpServiceCmHandle.setDmiServiceName(yangModelCmHandle.getDmiServiceName()); + ncmpServiceCmHandle.setDmiDataServiceName(yangModelCmHandle.getDmiDataServiceName()); + ncmpServiceCmHandle.setDmiModelServiceName(yangModelCmHandle.getDmiModelServiceName()); ncmpServiceCmHandle.setCompositeState(yangModelCmHandle.getCompositeState()); ncmpServiceCmHandle.setModuleSetTag(yangModelCmHandle.getModuleSetTag()); ncmpServiceCmHandle.setAlternateId(yangModelCmHandle.getAlternateId()); diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy index 47b57669ca..6aa84d1c7f 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy @@ -1,3 +1,22 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 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.ncmp.impl.datajobs @@ -6,7 +25,6 @@ import org.onap.cps.ncmp.api.datajobs.models.WriteOperation import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher -import org.onap.cps.spi.model.DataNode import spock.lang.Specification class WriteRequestExaminerSpec extends Specification { @@ -15,14 +33,14 @@ class WriteRequestExaminerSpec extends Specification { def objectUnderTest = new WriteRequestExaminer(mockAlternateIdMatcher) def setup() { - def ch1 = new DataNode(leaves: [id: 'ch1', 'dmi-service-name': 'dmiA', 'data-producer-identifier': 'p1']) - def ch2 = new DataNode(leaves: [id: 'ch2', 'dmi-service-name': 'dmiA', 'data-producer-identifier': 'p1']) - def ch3 = new DataNode(leaves: [id: 'ch3', 'dmi-service-name': 'dmiA', 'data-producer-identifier': 'p2']) - def ch4 = new DataNode(leaves: [id: 'ch4', 'dmi-service-name': 'dmiB', 'data-producer-identifier': 'p1']) - mockAlternateIdMatcher.getCmHandleDataNodeByLongestMatchingAlternateId('fdn1', '/') >> ch1 - mockAlternateIdMatcher.getCmHandleDataNodeByLongestMatchingAlternateId('fdn2', '/') >> ch2 - mockAlternateIdMatcher.getCmHandleDataNodeByLongestMatchingAlternateId('fdn3', '/') >> ch3 - mockAlternateIdMatcher.getCmHandleDataNodeByLongestMatchingAlternateId('fdn4', '/') >> ch4 + def ch1 = new YangModelCmHandle(id: 'ch1', dmiServiceName: 'dmiA', dataProducerIdentifier: 'p1', dmiProperties: []) + def ch2 = new YangModelCmHandle(id: 'ch2', dmiServiceName: 'dmiA', dataProducerIdentifier: 'p1', dmiProperties: []) + def ch3 = new YangModelCmHandle(id: 'ch3', dmiServiceName: 'dmiA', dataProducerIdentifier: 'p2', dmiProperties: []) + def ch4 = new YangModelCmHandle(id: 'ch4', dmiServiceName: 'dmiB', dataProducerIdentifier: 'p1', dmiProperties: []) + mockAlternateIdMatcher.getYangModelCmHandleByLongestMatchingAlternateId('fdn1', '/') >> ch1 + mockAlternateIdMatcher.getYangModelCmHandleByLongestMatchingAlternateId('fdn2', '/') >> ch2 + mockAlternateIdMatcher.getYangModelCmHandleByLongestMatchingAlternateId('fdn3', '/') >> ch3 + mockAlternateIdMatcher.getYangModelCmHandleByLongestMatchingAlternateId('fdn4', '/') >> ch4 } def 'Create a map of dmi write requests per producer key with #scenario.'() { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/AlternateIdCheckerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/AlternateIdCheckerSpec.groovy index b976ff4284..087265b51f 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/AlternateIdCheckerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/AlternateIdCheckerSpec.groovy @@ -23,7 +23,6 @@ package org.onap.cps.ncmp.impl.inventory import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.onap.cps.spi.exceptions.DataNodeNotFoundException -import org.onap.cps.spi.model.DataNode import spock.lang.Specification class AlternateIdCheckerSpec extends Specification { @@ -37,8 +36,8 @@ class AlternateIdCheckerSpec extends Specification { def batch = [new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: alt1), new NcmpServiceCmHandle(cmHandleId: 'ch-2', alternateId: alt2)] and: 'the database already contains cm handle(s) with these alternate ids: #altAlreadyInDb' - mockInventoryPersistenceService.getCmHandleDataNodesByAlternateIds(_ as Collection<String>) >> - { args -> args[0].stream().filter(altId -> altAlreadyInDb.contains(altId)).map(altId -> new DataNode(leaves: ["alternate-id": altId])).toList() } + mockInventoryPersistenceService.getYangModelCmHandleByAlternateIds(_ as Collection<String>) >> + { args -> args[0].stream().filter(altId -> altAlreadyInDb.contains(altId)).map(altId -> new YangModelCmHandle(alternateId: altId)).toList() } when: 'the batch of new cm handles is checked' def result = objectUnderTest.getIdsOfCmHandlesWithRejectedAlternateId(batch, AlternateIdChecker.Operation.CREATE) then: 'the result contains ids of the rejected cm handles' @@ -57,8 +56,8 @@ class AlternateIdCheckerSpec extends Specification { given: 'a batch of 1 existing cm handle to update alternate id to #proposedAlt' def batch = [new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: proposedAlt)] and: 'the database already contains a cm handle with alternate id: #altAlreadyInDb' - mockInventoryPersistenceService.getCmHandleDataNodesByAlternateIds(_ as Collection<String>) >> - { args -> args[0].stream().filter(altId -> altAlreadyInDb == altId).map(altId -> new DataNode(leaves: ["alternate-id": altId])).toList() } + mockInventoryPersistenceService.getYangModelCmHandleByAlternateIds(_ as Collection<String>) >> + { args -> args[0].stream().filter(altId -> altAlreadyInDb == altId).map(altId -> new YangModelCmHandle(alternateId: altId)).toList() } mockInventoryPersistenceService.getYangModelCmHandle(_) >> new YangModelCmHandle(alternateId: altAlreadyInDb) when: 'the batch of cm handle updates is checked' def result = objectUnderTest.getIdsOfCmHandlesWithRejectedAlternateId(batch, AlternateIdChecker.Operation.UPDATE) @@ -75,7 +74,7 @@ class AlternateIdCheckerSpec extends Specification { given: 'a batch of 1 non-existing cm handle to update alternate id' def batch = [new NcmpServiceCmHandle(cmHandleId: 'non-existing', alternateId: 'altId')] and: 'the database does not contain any cm handles' - mockInventoryPersistenceService.getCmHandleDataNodesByAlternateIds(_) >> [] + mockInventoryPersistenceService.getYangModelCmHandleByAlternateIds(_) >> [] mockInventoryPersistenceService.getYangModelCmHandle(_) >> { throwDataNodeNotFoundException() } when: 'the batch of cm handle updates is checked' def result = objectUnderTest.getIdsOfCmHandlesWithRejectedAlternateId(batch, AlternateIdChecker.Operation.UPDATE) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy index 4d8855c4b2..ab7ed98800 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy @@ -31,6 +31,7 @@ import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.impl.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle +import org.onap.cps.ncmp.impl.utils.YangDataConverter import org.onap.cps.spi.CascadeDeleteAllowed import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.model.DataNode @@ -67,6 +68,8 @@ class InventoryPersistenceImplSpec extends Specification { def mockCmHandleQueries = Mock(CmHandleQueryService) + def mockYangDataConverter = Mock(YangDataConverter) + def objectUnderTest = new InventoryPersistenceImpl(spiedJsonObjectMapper, mockCpsDataService, mockCpsModuleService, mockCpsValidator, mockCpsAnchorService, mockCmHandleQueries) @@ -312,29 +315,31 @@ class InventoryPersistenceImplSpec extends Specification { 1 * mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, expectedXPath, INCLUDE_ALL_DESCENDANTS) } - def 'Get cm handle data node by alternate id'() { + def 'Get yang model cm handle by alternate id'() { given: 'expected xPath to get cmHandle data node' def expectedXPath = '/dmi-registry/cm-handles[@alternate-id=\'alternate id\']' + def expectedDataNode = new DataNode(xpath: expectedXPath, leaves: [id: 'id', alternateId: 'alternate id']) and: 'query service is invoked with expected xpath' - mockCmHandleQueries.queryNcmpRegistryByCpsPath(expectedXPath, OMIT_DESCENDANTS) >> [new DataNode()] - expect: 'getting the cm handle data node' - assert objectUnderTest.getCmHandleDataNodeByAlternateId('alternate id') == new DataNode() + mockCmHandleQueries.queryNcmpRegistryByCpsPath(expectedXPath, OMIT_DESCENDANTS) >> [expectedDataNode] + mockYangDataConverter.toYangModelCmHandle(expectedDataNode) >> new YangModelCmHandle(id: 'id') + expect: 'getting the yang model cm handle' + assert objectUnderTest.getYangModelCmHandleByAlternateId('alternate id') == new YangModelCmHandle(id: 'id') } - def 'Attempt to get non existing cm handle data node by alternate id'() { + def 'Attempt to get non existing yang model cm handle by alternate id'() { given: 'query service is invoked and returns empty collection of data nodes' mockCmHandleQueries.queryNcmpRegistryByCpsPath(*_) >> [] - when: 'getting the cm handle data node' - objectUnderTest.getCmHandleDataNodeByAlternateId('alternate id') + when: 'getting the yang model cm handle' + objectUnderTest.getYangModelCmHandleByAlternateId('alternate id') then: 'no data found exception thrown' def thrownException = thrown(CmHandleNotFoundException) assert thrownException.getMessage().contains('Cm handle not found') assert thrownException.getDetails().contains('No cm handles found with reference alternate id') } - def 'Get multiple cm handle data nodes by alternate ids, passing empty collection'() { - when: 'getting the cm handle data node for no alternate ids' - objectUnderTest.getCmHandleDataNodesByAlternateIds([]) + def 'Get multiple yang model cm handles by alternate ids, passing empty collection'() { + when: 'getting the yang model cm handle for no alternate ids' + objectUnderTest.getYangModelCmHandleByAlternateIds([]) then: 'query service is not invoked' 0 * mockCmHandleQueries.queryNcmpRegistryByCpsPath(_, _) } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy index bf79fe35d3..1088ca8e06 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy @@ -177,25 +177,23 @@ class TrustLevelManagerSpec extends Specification { def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'ch-1') when: 'effective trust level selected' objectUnderTest.applyEffectiveTrustLevel(ncmpServiceCmHandle) - then: 'effective trust level is trusted' - // FIXME CPS-2375: the expected behaviour is to return the lower TrustLevel (NONE) - assert ncmpServiceCmHandle.currentTrustLevel == TrustLevel.COMPLETE + then: 'effective trust level is none' + assert ncmpServiceCmHandle.currentTrustLevel == TrustLevel.NONE } def 'Apply effective trust levels from CmHandle batch'() { - given: 'a non trusted dmi' - trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE) + given: 'a trusted dmi' + trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) and: 'a trusted CmHandle' trustLevelPerCmHandleId.put('ch-1', TrustLevel.COMPLETE) and: 'a not trusted CmHandle' trustLevelPerCmHandleId.put('ch-2', TrustLevel.NONE) and: 'cm handle objects' - def ncmpServiceCmHandle1 = new NcmpServiceCmHandle(cmHandleId: 'ch-1') - def ncmpServiceCmHandle2 = new NcmpServiceCmHandle(cmHandleId: 'ch-2') + def ncmpServiceCmHandle1 = new NcmpServiceCmHandle(cmHandleId: 'ch-1', dmiServiceName: 'my-dmi') + def ncmpServiceCmHandle2 = new NcmpServiceCmHandle(cmHandleId: 'ch-2', dmiDataServiceName: 'my-dmi') when: 'effective trust level selected' objectUnderTest.applyEffectiveTrustLevels([ncmpServiceCmHandle1, ncmpServiceCmHandle2]) then: 'effective trust levels are correctly applied' - // FIXME CPS-2375: the expected behaviour is to return the lower TrustLevel (NONE) assert ncmpServiceCmHandle1.currentTrustLevel == TrustLevel.COMPLETE assert ncmpServiceCmHandle2.currentTrustLevel == TrustLevel.NONE } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy index 0a58039d8a..a6d21afd30 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy @@ -23,7 +23,7 @@ package org.onap.cps.ncmp.impl.utils import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException import org.onap.cps.ncmp.impl.inventory.InventoryPersistence -import org.onap.cps.spi.model.DataNode +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import spock.lang.Specification class AlternateIdMatcherSpec extends Specification { @@ -33,14 +33,14 @@ class AlternateIdMatcherSpec extends Specification { def setup() { given: 'cm handle in the registry with alternate id /a/b' - mockInventoryPersistence.getCmHandleDataNodeByAlternateId('/a/b') >> new DataNode() + mockInventoryPersistence.getYangModelCmHandleByAlternateId('/a/b') >> new YangModelCmHandle() and: 'no other cm handle' - mockInventoryPersistence.getCmHandleDataNodeByAlternateId(_) >> { throw new CmHandleNotFoundException('') } + mockInventoryPersistence.getYangModelCmHandleByAlternateId(_) >> { throw new CmHandleNotFoundException('') } } def 'Finding longest alternate id matches.'() { expect: 'querying for alternate id a matching result found' - assert objectUnderTest.getCmHandleDataNodeByLongestMatchingAlternateId(targetAlternateId, '/') != null + assert objectUnderTest.getYangModelCmHandleByLongestMatchingAlternateId(targetAlternateId, '/') != null where: 'the following parameters are used' scenario | targetAlternateId 'exact match' | '/a/b' @@ -55,7 +55,7 @@ class AlternateIdMatcherSpec extends Specification { def 'Attempt to find longest alternate id match without any matches.'() { when: 'attempt to find alternateId' - objectUnderTest.getCmHandleDataNodeByLongestMatchingAlternateId(targetAlternateId, '/') + objectUnderTest.getYangModelCmHandleByLongestMatchingAlternateId(targetAlternateId, '/') then: 'no alternate id match found exception thrown' def thrown = thrown(NoAlternateIdMatchFoundException) and: 'the exception has the relevant details from the error response' @@ -73,12 +73,12 @@ class AlternateIdMatcherSpec extends Specification { def result = objectUnderTest.getCmHandleId(cmHandleReference) then: 'the inventory persistence service returns a cm handle (or not)' mockInventoryPersistence.isExistingCmHandleId(cmHandleReference) >> existingCmHandleIdResponse - mockInventoryPersistence.getCmHandleDataNodeByAlternateId(cmHandleReference) >> alternateIdGetResponse + mockInventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference) >> alternateIdGetResponse and: 'correct result is returned' assert result == cmHandleReference - where: + where: 'the following parameters are used' cmHandleReference | existingCmHandleIdResponse | alternateIdGetResponse 'ch-1' | true | '' - 'alt-1' | false | new DataNode(leaves: [id:'alt-1']) + 'alt-1' | false | new YangModelCmHandle(id: 'alt-1') } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy index bb45e8ad96..1b8a33fea9 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy @@ -31,11 +31,15 @@ class YangDataConverterSpec extends Specification{ leaves: ['name': 'dmiProp1', 'value': 'dmiValue1']) def dataNodePublicProperties = new DataNode(xpath:'/public-properties[@name="pubProp1"]', leaves: ['name': 'pubProp1', 'value': 'pubValue1']) - def dataNodeCmHandle = new DataNode(leaves:['id':'sample-id'], childDataNodes:[dataNodeAdditionalProperties, dataNodePublicProperties]) + def dataNodeCmHandle = new DataNode(leaves:['id':'sample-id', 'alternate-id': 'alt-id', 'module-set-tag': 'my-tag', 'dmi-service-name': 'my-dmi', 'data-producer-identifier': 'my-dpi'], childDataNodes:[dataNodeAdditionalProperties, dataNodePublicProperties]) when: 'the dataNode is converted' def yangModelCmHandle = YangDataConverter.toYangModelCmHandle(dataNodeCmHandle) - then: 'the converted object has the correct id' + then: 'the converted object has the fields' assert yangModelCmHandle.id == 'sample-id' + assert yangModelCmHandle.alternateId == 'alt-id' + assert yangModelCmHandle.dmiServiceName == 'my-dmi' + assert yangModelCmHandle.moduleSetTag == 'my-tag' + assert yangModelCmHandle.dataProducerIdentifier == 'my-dpi' and: 'the additional (dmi, private) properties are included' assert yangModelCmHandle.dmiProperties[0].name == 'dmiProp1' assert yangModelCmHandle.dmiProperties[0].value == 'dmiValue1' diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java b/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java index edd2d2ad32..34dcbb9e32 100644 --- a/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java +++ b/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020-2022 Nordix Foundation + * Copyright (C) 2020-2024 Nordix Foundation * Modifications Copyright (C) 2022-2023 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +22,7 @@ package org.onap.cps.api; import java.util.Collection; +import java.util.Set; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.PaginationOption; import org.onap.cps.spi.model.DataNode; @@ -44,6 +45,18 @@ public interface CpsQueryService { Collection<DataNode> queryDataNodes(String dataspaceName, String anchorName, String cpsPath, FetchDescendantsOption fetchDescendantsOption); + + /** + * Get data leaf for the given dataspace and anchor by cps path. + * + * @param dataspaceName dataspace name + * @param anchorName anchor name + * @param cpsPath cps path + * @param targetClass class of the expected data type + * @return a collection of data objects of expected type + */ + <T> Set<T> queryDataLeaf(String dataspaceName, String anchorName, String cpsPath, Class<T> targetClass); + /** * Get data nodes for the given dataspace across all anchors by cps path. * 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 d1c98986e6..1de7c1733e 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 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation + * Copyright (C) 2021-2024 Nordix Foundation * Modifications Copyright (C) 2022-2023 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +23,7 @@ package org.onap.cps.api.impl; import io.micrometer.core.annotation.Timed; import java.util.Collection; +import java.util.Set; import lombok.RequiredArgsConstructor; import org.onap.cps.api.CpsQueryService; import org.onap.cps.impl.utils.CpsValidator; @@ -43,15 +44,23 @@ public class CpsQueryServiceImpl implements CpsQueryService { @Timed(value = "cps.data.service.datanode.query", description = "Time taken to query data nodes") public Collection<DataNode> queryDataNodes(final String dataspaceName, final String anchorName, - final String cpsPath, final FetchDescendantsOption fetchDescendantsOption) { + final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption) { cpsValidator.validateNameCharacters(dataspaceName, anchorName); return cpsDataPersistenceService.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption); } @Override - public Collection<DataNode> queryDataNodesAcrossAnchors(final String dataspaceName, - final String cpsPath, final FetchDescendantsOption fetchDescendantsOption, - final PaginationOption paginationOption) { + public <T> Set<T> queryDataLeaf(final String dataspaceName, final String anchorName, final String cpsPath, + final Class<T> targetClass) { + cpsValidator.validateNameCharacters(dataspaceName, anchorName); + throw new UnsupportedOperationException("Query by attribute-axis not implemented yet!"); + } + + @Override + public Collection<DataNode> queryDataNodesAcrossAnchors(final String dataspaceName, final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption, + final PaginationOption paginationOption) { cpsValidator.validateNameCharacters(dataspaceName); cpsValidator.validatePaginationOption(paginationOption); return cpsDataPersistenceService.queryDataNodesAcrossAnchors(dataspaceName, cpsPath, 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 3b10669ddb..74127e095f 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 @@ -71,4 +71,12 @@ class CpsQueryServiceImplSpec extends Specification { then: 'the persistence service is called once with the correct parameters' 1 * mockCpsDataPersistenceService.countAnchorsForDataspaceAndCpsPath("some-dataspace", "/cps-path") } + + // TODO will be implemented in CPS-2416 + def 'Query data leaf.'() { + when: 'a query for a specific leaf is executed' + objectUnderTest.queryDataLeaf('some-dataspace', 'some-anchor', '/cps-path/@id', Object.class) + then: 'solution is not implemented yet' + thrown(UnsupportedOperationException) + } } diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy index 3b49cfc415..23e41c4178 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy @@ -27,6 +27,7 @@ import org.onap.cps.integration.base.FunctionalSpecBase import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.PaginationOption import org.onap.cps.spi.exceptions.CpsPathException +import spock.lang.Ignore import static org.onap.cps.spi.FetchDescendantsOption.DIRECT_CHILDREN_ONLY import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS @@ -56,6 +57,44 @@ class QueryServiceIntegrationSpec extends FunctionalSpecBase { 'the AND is used where result does not exist' | '//books[@lang="English" and @price=1000]' || 0 | [] } + @Ignore // TODO will be implemented in CPS-2416 + def 'Query data leaf using CPS path for #scenario.'() { + when: 'query data leaf for bookstore container' + def result = objectUnderTest.queryDataLeaf(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, cpsPath, Object.class) + then: 'the result contains the expected number of leaf values' + assert result.size() == expectedUniqueBooksTitles + where: + scenario | cpsPath || expectedUniqueBooksTitles + 'all books' | '//books/@title' || 19 + 'all books in a category' | '/bookstore/categories[@code=5]/books/@title' || 10 + 'non-existing path' | '/non-existing/@title' || 0 + } + + @Ignore + def 'Query data leaf with type #leafType using CPS path.'() { + given: 'a cps path query for two books, returning only #leafName' + def cpsPath = '//books[@title="Matilda" or @title="Good Omens"]/@' + leafName + when: 'query data leaf for bookstore container' + def results = objectUnderTest.queryDataLeaf(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, cpsPath, leafType) + then: 'the result contains the expected leaf values' + assert results == expectedResults as Set + where: + leafName | leafType || expectedResults + 'lang' | String.class || ['English'] + 'price' | Number.class || [13, 20] + 'editions' | List.class || [[1988, 2000], [2006]] + } + + @Ignore + def 'Query data leaf using CPS path with ancestor axis.'() { + given: 'a cps path query that will return the names of the categories of two books' + def cpsPath = '//books[@title="Matilda" or @title="Good Omens"]/ancestor::categories/@name' + when: 'query data leaf for bookstore container' + def result = objectUnderTest.queryDataLeaf(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, cpsPath, String.class) + then: 'the result contains the expected leaf values' + assert result == ['Children', 'Comedy'] as Set + } + def 'Cps Path query using comparative and boolean operators.'() { given: 'a cps path query in the discount category' def cpsPath = "/bookstore/categories[@code='5']/books" + leafCondition diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmHandleQueryByAlternateIdPerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmHandleQueryByAlternateIdPerfTest.groovy index a2d3a4aeac..b00893b718 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmHandleQueryByAlternateIdPerfTest.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmHandleQueryByAlternateIdPerfTest.groovy @@ -41,7 +41,7 @@ class CmHandleQueryByAlternateIdPerfTest extends NcmpPerfTestBase { when: 'an alternate id as cps path query' resourceMeter.start() def cpsPath = "/a/b/c/d-5/e/f/g/h/i" - def dataNodes = objectUnderTest.getCmHandleDataNodeByLongestMatchingAlternateId(cpsPath, '/') + def dataNodes = objectUnderTest.getYangModelCmHandleByLongestMatchingAlternateId(cpsPath, '/') and: 'the ids of the result are extracted and converted to xpath' def cpsXpaths = dataNodes.stream().map(dataNode -> "/dmi-registry/cm-handles[@id='${dataNode.leaves.id}']".toString() ).collect(Collectors.toSet()) and: 'a single get is executed to get all the parent objects and their descendants' |