aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy1
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy6
-rw-r--r--cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java16
-rw-r--r--cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy8
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java379
-rwxr-xr-xcps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepository.java13
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/ri/CpsDataPersistenceServiceImplSpec.groovy2
-rw-r--r--csit/plans/cps/test.properties2
-rw-r--r--docker-compose/docker-compose.yml2
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy4
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy2
12 files changed, 201 insertions, 236 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java
index a056efd6ce..2d45103904 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java
@@ -34,7 +34,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.inventory.models.YangResource;
import org.onap.cps.ncmp.impl.dmi.DmiProperties;
import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
@@ -50,7 +49,6 @@ import org.springframework.stereotype.Service;
/**
* Operations class for DMI Model.
*/
-@Slf4j
@RequiredArgsConstructor
@Service
public class DmiModelOperations {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
index e479fffe87..d00d3ab8f6 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
@@ -44,7 +44,6 @@ abstract class DmiOperationsBaseSpec extends Specification {
ObjectMapper spyObjectMapper = Spy()
def yangModelCmHandle = new YangModelCmHandle()
- def otherYangModelCmHandle = new YangModelCmHandle()
def static dmiServiceName = 'myServiceName'
def static cmHandleId = 'some-cm-handle'
def static alternateId = 'alt-id-' + cmHandleId
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy
index 2f13a9a483..f5c4ea4369 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy
@@ -91,7 +91,7 @@ class ModuleSyncServiceSpec extends Specification {
def yangModelCmHandle = createAdvisedCmHandle(moduleSetTag)
and: 'the service returns a list of module references when queried with the specified attributes'
mockCpsModuleService.getModuleReferencesByAttribute(*_) >> [new ModuleReference('module1', '1')]
- and: 'exception occurs when try to store result'
+ and: 'exception occurs when trying to store result'
def testException = new RuntimeException('test')
mockCpsModuleService.createSchemaSetFromModules(*_) >> { throw testException }
when: 'module sync is triggered'
@@ -110,7 +110,7 @@ class ModuleSyncServiceSpec extends Specification {
def 'Sync models for a cm handle with previously cached module set tag.'() {
given: 'a cm handle to be synced'
def yangModelCmHandle = createAdvisedCmHandle('cached-tag')
- and: 'The module set tag exist in the private cache'
+ and: 'The module set tag exists in the private cache'
def moduleReferences = [ new ModuleReference('module1','1') ]
def cachedModuleDelta = new ModuleDelta(moduleReferences, [:])
objectUnderTest.privateModuleSetCache.put('cached-tag', cachedModuleDelta)
@@ -125,7 +125,7 @@ class ModuleSyncServiceSpec extends Specification {
def 'Attempt to sync using a module set tag already being processed by a different instance or thread.'() {
given: 'a cm handle to be synced'
def yangModelCmHandle = createAdvisedCmHandle('duplicateTag')
- and: 'The module set tag already exist in the processing semaphore set'
+ and: 'The module set tag already exists in the processing semaphore set'
mockModuleSetTagsBeingProcessed.add('duplicate-processing-tag') > false
when: 'module sync is triggered'
objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle)
diff --git a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
index ed7dbecc18..b67d70847c 100644
--- a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
+++ b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
@@ -180,12 +180,12 @@ public class CpsPathBuilder extends CpsPathBaseListener {
if (!isStartOfExpression) {
currentNormalizedPathBuilder.append(" ").append(getLastElement(booleanOperators)).append(" ");
}
- currentNormalizedPathBuilder.append("@")
- .append(name)
- .append(operator)
- .append("'")
- .append(value.toString().replace("'", "''"))
- .append("'");
+ currentNormalizedPathBuilder.append("@").append(name).append(operator);
+ if (operator.equals("=")) {
+ currentNormalizedPathBuilder.append(wrapValueInSingleQuotes(value));
+ } else {
+ currentNormalizedPathBuilder.append(value);
+ }
}
private static String getLastElement(final List<String> listOfStrings) {
@@ -202,6 +202,10 @@ public class CpsPathBuilder extends CpsPathBaseListener {
}
}
+ private static String wrapValueInSingleQuotes(final Object value) {
+ return "'" + value.toString().replace("'", "''") + "'";
+ }
+
private static String stripFirstAndLastCharacter(final String wrappedString) {
return wrappedString.substring(1, wrappedString.length() - 1);
}
diff --git a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
index 16430d2fa5..a1bf28977a 100644
--- a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
+++ b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
@@ -87,10 +87,10 @@ class CpsPathQuerySpec extends Specification {
'yang container' | '/cps-path' || '/cps-path'
'descendant anywhere' | '//cps-path' || '//cps-path'
'descendant with leaf condition' | '//cps-path[@key=1]' || "//cps-path[@key='1']"
- 'descendant with leaf condition has ">" operator' | '//cps-path[@key>9]' || "//cps-path[@key>'9']"
- 'descendant with leaf condition has "<" operator' | '//cps-path[@key<10]' || "//cps-path[@key<'10']"
- 'descendant with leaf condition has ">=" operator' | '//cps-path[@key>=8]' || "//cps-path[@key>='8']"
- 'descendant with leaf condition has "<=" operator' | '//cps-path[@key<=12]' || "//cps-path[@key<='12']"
+ 'descendant with leaf condition has ">" operator' | '//cps-path[@key>9]' || "//cps-path[@key>9]"
+ 'descendant with leaf condition has "<" operator' | '//cps-path[@key<10]' || "//cps-path[@key<10]"
+ 'descendant with leaf condition has ">=" operator' | '//cps-path[@key>=8]' || "//cps-path[@key>=8]"
+ 'descendant with leaf condition has "<=" operator' | '//cps-path[@key<=12]' || "//cps-path[@key<=12]"
'descendant with leaf value and ancestor' | '//cps-path[@key=1]/ancestor::parent[@key=1]' || "//cps-path[@key='1']/ancestor::parent[@key='1']"
'parent & child' | '/parent/child' || '/parent/child'
'parent leaf of type Integer & child' | '/parent/child[@code=1]/child2' || "/parent/child[@code='1']/child2"
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java
index ecbe447226..bdbdc7cf36 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java
@@ -116,26 +116,6 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
}
}
- /**
- * Convert DataNode object into Fragment and places the result in the fragments placeholder. Performs same action
- * for all DataNode children recursively.
- *
- * @param anchorEntity anchorEntity
- * @param dataNodeToBeConverted dataNode
- * @return a Fragment built from current DataNode
- */
- private FragmentEntity convertToFragmentWithAllDescendants(final AnchorEntity anchorEntity,
- final DataNode dataNodeToBeConverted) {
- final FragmentEntity parentFragment = toFragmentEntity(anchorEntity, dataNodeToBeConverted);
- final Builder<FragmentEntity> childFragmentsImmutableSetBuilder = ImmutableSet.builder();
- for (final DataNode childDataNode : dataNodeToBeConverted.getChildDataNodes()) {
- final FragmentEntity childFragment = convertToFragmentWithAllDescendants(anchorEntity, childDataNode);
- childFragmentsImmutableSetBuilder.add(childFragment);
- }
- parentFragment.setChildFragments(childFragmentsImmutableSetBuilder.build());
- return parentFragment;
- }
-
@Override
public void addListElements(final String dataspaceName, final String anchorName, final String parentNodeXpath,
final Collection<DataNode> newListElements) {
@@ -150,53 +130,6 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
addChildrenDataNodes(anchorEntity, parentNodeXpath, dataNodes);
}
- private void addChildrenDataNodes(final AnchorEntity anchorEntity, final String parentNodeXpath,
- final Collection<DataNode> newChildren) {
- final FragmentEntity parentFragmentEntity = getFragmentEntity(anchorEntity, parentNodeXpath);
- final List<FragmentEntity> fragmentEntities = new ArrayList<>(newChildren.size());
- try {
- for (final DataNode newChildAsDataNode : newChildren) {
- final FragmentEntity newChildAsFragmentEntity =
- convertToFragmentWithAllDescendants(anchorEntity, newChildAsDataNode);
- newChildAsFragmentEntity.setParentId(parentFragmentEntity.getId());
- fragmentEntities.add(newChildAsFragmentEntity);
- }
- fragmentRepository.saveAll(fragmentEntities);
- } catch (final DataIntegrityViolationException dataIntegrityViolationException) {
- log.warn("Exception occurred : {} , While saving : {} children, retrying using individual save operations",
- dataIntegrityViolationException, fragmentEntities.size());
- retrySavingEachChildIndividually(anchorEntity, parentNodeXpath, newChildren);
- }
- }
-
- private void addNewChildDataNode(final AnchorEntity anchorEntity, final String parentNodeXpath,
- final DataNode newChild) {
- final FragmentEntity parentFragmentEntity = getFragmentEntity(anchorEntity, parentNodeXpath);
- final FragmentEntity newChildAsFragmentEntity = convertToFragmentWithAllDescendants(anchorEntity, newChild);
- newChildAsFragmentEntity.setParentId(parentFragmentEntity.getId());
- try {
- fragmentRepository.save(newChildAsFragmentEntity);
- } catch (final DataIntegrityViolationException dataIntegrityViolationException) {
- throw AlreadyDefinedException.forDataNodes(Collections.singletonList(newChild.getXpath()),
- anchorEntity.getName());
- }
- }
-
- private void retrySavingEachChildIndividually(final AnchorEntity anchorEntity, final String parentNodeXpath,
- final Collection<DataNode> newChildren) {
- final Collection<String> failedXpaths = new HashSet<>();
- for (final DataNode newChild : newChildren) {
- try {
- addNewChildDataNode(anchorEntity, parentNodeXpath, newChild);
- } catch (final AlreadyDefinedException alreadyDefinedException) {
- failedXpaths.add(newChild.getXpath());
- }
- }
- if (!failedXpaths.isEmpty()) {
- throw AlreadyDefinedException.forDataNodes(failedXpaths, anchorEntity.getName());
- }
- }
-
@Override
public void batchUpdateDataLeaves(final String dataspaceName, final String anchorName,
final Map<String, Map<String, Serializable>> updatedLeavesPerXPath) {
@@ -246,19 +179,6 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
}
}
- private void logMissingXPaths(final Collection<String> xpaths, final Collection<FragmentEntity>
- existingFragmentEntities) {
- final Set<String> existingXPaths = existingFragmentEntities.stream().map(FragmentEntity::getXpath)
- .collect(Collectors.toSet());
-
- final Set<String> missingXPaths = xpaths.stream().filter(xpath -> !existingXPaths.contains(xpath))
- .collect(Collectors.toSet());
-
- if (!missingXPaths.isEmpty()) {
- log.warn("Cannot update data nodes: Target XPaths {} not found in DB.", missingXPaths);
- }
- }
-
private void retryUpdateDataNodesIndividually(final AnchorEntity anchorEntity,
final Collection<FragmentEntity> fragmentEntities) {
final Collection<String> failedXpaths = new HashSet<>();
@@ -306,14 +226,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
description = "Time taken to query data nodes")
public List<DataNode> queryDataNodes(final String dataspaceName, final String anchorName, final String cpsPath,
final FetchDescendantsOption fetchDescendantsOption) {
- final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
- final AnchorEntity anchorEntity = anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName);
- final CpsPathQuery cpsPathQuery;
- try {
- cpsPathQuery = CpsPathUtil.getCpsPathQuery(cpsPath);
- } catch (final PathParsingException pathParsingException) {
- throw new CpsPathException(pathParsingException.getMessage());
- }
+ final AnchorEntity anchorEntity = getAnchorEntity(dataspaceName, anchorName);
+ final CpsPathQuery cpsPathQuery = getCpsPathQuery(cpsPath);
Collection<FragmentEntity> fragmentEntities;
fragmentEntities = fragmentRepository.findByAnchorAndCpsPath(anchorEntity, cpsPathQuery);
@@ -321,8 +235,6 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
final Collection<String> ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery);
fragmentEntities = fragmentRepository.findByAnchorAndXpathIn(anchorEntity, ancestorXpaths);
}
- fragmentEntities = fragmentRepository.prefetchDescendantsOfFragmentEntities(fetchDescendantsOption,
- fragmentEntities);
return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities);
}
@@ -333,12 +245,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
final FetchDescendantsOption fetchDescendantsOption,
final PaginationOption paginationOption) {
final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
- final CpsPathQuery cpsPathQuery;
- try {
- cpsPathQuery = CpsPathUtil.getCpsPathQuery(cpsPath);
- } catch (final PathParsingException e) {
- throw new CpsPathException(e.getMessage());
- }
+ final CpsPathQuery cpsPathQuery = getCpsPathQuery(cpsPath);
final List<Long> anchorIds;
if (paginationOption == NO_PAGINATION) {
@@ -359,22 +266,10 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
} else {
fragmentEntities = fragmentRepository.findByAnchorIdsAndXpathIn(anchorIds, ancestorXpaths);
}
-
}
- fragmentEntities = fragmentRepository.prefetchDescendantsOfFragmentEntities(fetchDescendantsOption,
- fragmentEntities);
return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities);
}
- private List<DataNode> createDataNodesFromFragmentEntities(final FetchDescendantsOption fetchDescendantsOption,
- final Collection<FragmentEntity> fragmentEntities) {
- final List<DataNode> dataNodes = new ArrayList<>(fragmentEntities.size());
- for (final FragmentEntity fragmentEntity : fragmentEntities) {
- dataNodes.add(toDataNode(fragmentEntity, fetchDescendantsOption));
- }
- return Collections.unmodifiableList(dataNodes);
- }
-
@Override
public String startSession() {
return sessionManager.startSession();
@@ -394,41 +289,11 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
@Override
public Integer countAnchorsForDataspaceAndCpsPath(final String dataspaceName, final String cpsPath) {
final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
- final CpsPathQuery cpsPathQuery;
- try {
- cpsPathQuery = CpsPathUtil.getCpsPathQuery(cpsPath);
- } catch (final PathParsingException e) {
- throw new CpsPathException(e.getMessage());
- }
+ final CpsPathQuery cpsPathQuery = getCpsPathQuery(cpsPath);
final List<Long> anchorIdList = getAnchorIdsForPagination(dataspaceEntity, cpsPathQuery, NO_PAGINATION);
return anchorIdList.size();
}
- private DataNode toDataNode(final FragmentEntity fragmentEntity,
- final FetchDescendantsOption fetchDescendantsOption) {
- final List<DataNode> childDataNodes = getChildDataNodes(fragmentEntity, fetchDescendantsOption);
- Map<String, Serializable> leaves = new HashMap<>();
- if (fragmentEntity.getAttributes() != null) {
- leaves = jsonObjectMapper.convertJsonString(fragmentEntity.getAttributes(), Map.class);
- }
- return new DataNodeBuilder()
- .withXpath(fragmentEntity.getXpath())
- .withLeaves(leaves)
- .withDataspace(fragmentEntity.getAnchor().getDataspace().getName())
- .withAnchor(fragmentEntity.getAnchor().getName())
- .withChildDataNodes(childDataNodes).build();
- }
-
- private FragmentEntity toFragmentEntity(final AnchorEntity anchorEntity, final DataNode dataNode) {
- return FragmentEntity.builder()
- .anchor(anchorEntity)
- .xpath(dataNode.getXpath())
- .attributes(jsonObjectMapper.asJsonString(dataNode.getLeaves()))
- .build();
- }
-
-
-
@Override
@Transactional
public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
@@ -487,18 +352,18 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
final Collection<String> deleteChecklist = getNormalizedXpaths(xpathsToDelete);
final Collection<String> xpathsToExistingContainers =
- fragmentRepository.findAllXpathByAnchorAndXpathIn(anchorEntity, deleteChecklist);
+ fragmentRepository.findAllXpathByAnchorAndXpathIn(anchorEntity, deleteChecklist);
if (onlySupportListDeletion) {
final Collection<String> xpathsToExistingListElements = xpathsToExistingContainers.stream()
- .filter(CpsPathUtil::isPathToListElement).toList();
+ .filter(CpsPathUtil::isPathToListElement).toList();
deleteChecklist.removeAll(xpathsToExistingListElements);
} else {
deleteChecklist.removeAll(xpathsToExistingContainers);
}
final Collection<String> xpathsToExistingLists = deleteChecklist.stream()
- .filter(xpath -> fragmentRepository.existsByAnchorAndXpathStartsWith(anchorEntity, xpath + "["))
- .toList();
+ .filter(xpath -> fragmentRepository.existsByAnchorAndXpathStartsWith(anchorEntity, xpath + "["))
+ .toList();
deleteChecklist.removeAll(xpathsToExistingLists);
if (!deleteChecklist.isEmpty()) {
@@ -531,7 +396,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
final String normalizedXpath = getNormalizedXpath(targetXpath);
try {
deleteDataNodes(dataspaceName, anchorName, Collections.singletonList(normalizedXpath),
- onlySupportListNodeDeletion);
+ onlySupportListNodeDeletion);
} catch (final DataNodeNotFoundExceptionBatch dataNodeNotFoundExceptionBatch) {
throw new DataNodeNotFoundException(dataspaceName, anchorName, targetXpath);
}
@@ -559,18 +424,110 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
final Collection<String> xpaths,
final FetchDescendantsOption fetchDescendantsOption) {
final AnchorEntity anchorEntity = getAnchorEntity(dataspaceName, anchorName);
- Collection<FragmentEntity> fragmentEntities = getFragmentEntities(anchorEntity, xpaths);
- fragmentEntities = fragmentRepository.prefetchDescendantsOfFragmentEntities(fetchDescendantsOption,
- fragmentEntities);
+ final Collection<FragmentEntity> fragmentEntities = getFragmentEntities(anchorEntity, xpaths);
return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities);
}
+
+ private void addChildrenDataNodes(final AnchorEntity anchorEntity, final String parentNodeXpath,
+ final Collection<DataNode> newChildren) {
+ final FragmentEntity parentFragmentEntity = getFragmentEntity(anchorEntity, parentNodeXpath);
+ final List<FragmentEntity> fragmentEntities = new ArrayList<>(newChildren.size());
+ try {
+ for (final DataNode newChildAsDataNode : newChildren) {
+ final FragmentEntity newChildAsFragmentEntity =
+ convertToFragmentWithAllDescendants(anchorEntity, newChildAsDataNode);
+ newChildAsFragmentEntity.setParentId(parentFragmentEntity.getId());
+ fragmentEntities.add(newChildAsFragmentEntity);
+ }
+ fragmentRepository.saveAll(fragmentEntities);
+ } catch (final DataIntegrityViolationException dataIntegrityViolationException) {
+ log.warn("Exception occurred : {} , While saving : {} children, retrying using individual save operations",
+ dataIntegrityViolationException, fragmentEntities.size());
+ retrySavingEachChildIndividually(anchorEntity, parentNodeXpath, newChildren);
+ }
+ }
+
+ private void addNewChildDataNode(final AnchorEntity anchorEntity, final String parentNodeXpath,
+ final DataNode newChild) {
+ final FragmentEntity parentFragmentEntity = getFragmentEntity(anchorEntity, parentNodeXpath);
+ final FragmentEntity newChildAsFragmentEntity = convertToFragmentWithAllDescendants(anchorEntity, newChild);
+ newChildAsFragmentEntity.setParentId(parentFragmentEntity.getId());
+ try {
+ fragmentRepository.save(newChildAsFragmentEntity);
+ } catch (final DataIntegrityViolationException dataIntegrityViolationException) {
+ throw AlreadyDefinedException.forDataNodes(Collections.singletonList(newChild.getXpath()),
+ anchorEntity.getName());
+ }
+ }
+
+ private void retrySavingEachChildIndividually(final AnchorEntity anchorEntity, final String parentNodeXpath,
+ final Collection<DataNode> newChildren) {
+ final Collection<String> failedXpaths = new HashSet<>();
+ for (final DataNode newChild : newChildren) {
+ try {
+ addNewChildDataNode(anchorEntity, parentNodeXpath, newChild);
+ } catch (final AlreadyDefinedException alreadyDefinedException) {
+ failedXpaths.add(newChild.getXpath());
+ }
+ }
+ if (!failedXpaths.isEmpty()) {
+ throw AlreadyDefinedException.forDataNodes(failedXpaths, anchorEntity.getName());
+ }
+ }
+
+ private FragmentEntity convertToFragmentWithAllDescendants(final AnchorEntity anchorEntity,
+ final DataNode dataNodeToBeConverted) {
+ final FragmentEntity parentFragment = toFragmentEntity(anchorEntity, dataNodeToBeConverted);
+ final Builder<FragmentEntity> childFragmentsImmutableSetBuilder = ImmutableSet.builder();
+ for (final DataNode childDataNode : dataNodeToBeConverted.getChildDataNodes()) {
+ final FragmentEntity childFragment = convertToFragmentWithAllDescendants(anchorEntity, childDataNode);
+ childFragmentsImmutableSetBuilder.add(childFragment);
+ }
+ parentFragment.setChildFragments(childFragmentsImmutableSetBuilder.build());
+ return parentFragment;
+ }
+
+ private FragmentEntity toFragmentEntity(final AnchorEntity anchorEntity, final DataNode dataNode) {
+ return FragmentEntity.builder()
+ .anchor(anchorEntity)
+ .xpath(dataNode.getXpath())
+ .attributes(jsonObjectMapper.asJsonString(dataNode.getLeaves()))
+ .build();
+ }
+
+ private List<DataNode> createDataNodesFromFragmentEntities(final FetchDescendantsOption fetchDescendantsOption,
+ final Collection<FragmentEntity> fragmentEntities) {
+ final Collection<FragmentEntity> fragmentEntitiesWithDescendants =
+ fragmentRepository.prefetchDescendantsOfFragmentEntities(fetchDescendantsOption, fragmentEntities);
+ final List<DataNode> dataNodes = new ArrayList<>(fragmentEntitiesWithDescendants.size());
+ for (final FragmentEntity fragmentEntity : fragmentEntitiesWithDescendants) {
+ dataNodes.add(toDataNode(fragmentEntity, fetchDescendantsOption));
+ }
+ return Collections.unmodifiableList(dataNodes);
+ }
+
+ private DataNode toDataNode(final FragmentEntity fragmentEntity,
+ final FetchDescendantsOption fetchDescendantsOption) {
+ final List<DataNode> childDataNodes = getChildDataNodes(fragmentEntity, fetchDescendantsOption);
+ Map<String, Serializable> leaves = new HashMap<>();
+ if (fragmentEntity.getAttributes() != null) {
+ leaves = jsonObjectMapper.convertJsonString(fragmentEntity.getAttributes(), Map.class);
+ }
+ return new DataNodeBuilder()
+ .withXpath(fragmentEntity.getXpath())
+ .withLeaves(leaves)
+ .withDataspace(fragmentEntity.getAnchor().getDataspace().getName())
+ .withAnchor(fragmentEntity.getAnchor().getName())
+ .withChildDataNodes(childDataNodes).build();
+ }
+
private List<DataNode> getChildDataNodes(final FragmentEntity fragmentEntity,
final FetchDescendantsOption fetchDescendantsOption) {
if (fetchDescendantsOption.hasNext()) {
return fragmentEntity.getChildFragments().stream()
.map(childFragmentEntity -> toDataNode(childFragmentEntity, fetchDescendantsOption.next()))
- .collect(Collectors.toList());
+ .toList();
}
return Collections.emptyList();
}
@@ -585,36 +542,9 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
return fragmentRepository.findAnchorIdsForPagination(dataspaceEntity, cpsPathQuery, paginationOption);
}
- private static String getNormalizedXpath(final String xpathSource) {
- if (isRootXpath(xpathSource)) {
- return xpathSource;
- }
- try {
- return CpsPathUtil.getNormalizedXpath(xpathSource);
- } catch (final PathParsingException pathParsingException) {
- throw new CpsPathException(pathParsingException.getMessage());
- }
- }
-
- private static Collection<String> getNormalizedXpaths(final Collection<String> xpaths) {
- final Collection<String> normalizedXpaths = new HashSet<>(xpaths.size());
- for (final String xpath : xpaths) {
- try {
- normalizedXpaths.add(getNormalizedXpath(xpath));
- } catch (final CpsPathException cpsPathException) {
- log.warn("Error parsing xpath \"{}\": {}", xpath, cpsPathException.getMessage());
- }
- }
- return normalizedXpaths;
- }
-
private FragmentEntity getFragmentEntity(final AnchorEntity anchorEntity, final String xpath) {
- final FragmentEntity fragmentEntity;
- if (isRootXpath(xpath)) {
- fragmentEntity = fragmentRepository.findOneByAnchorId(anchorEntity.getId()).orElse(null);
- } else {
- fragmentEntity = fragmentRepository.getByAnchorAndXpath(anchorEntity, getNormalizedXpath(xpath));
- }
+ final FragmentEntity fragmentEntity =
+ fragmentRepository.findByAnchorIdAndXpath(anchorEntity.getId(), getNormalizedXpath(xpath));
if (fragmentEntity == null) {
throw new DataNodeNotFoundException(anchorEntity.getDataspace().getName(), anchorEntity.getName(), xpath);
}
@@ -628,7 +558,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
final boolean haveRootXpath = normalizedXpaths.removeIf(CpsDataPersistenceServiceImpl::isRootXpath);
final List<FragmentEntity> fragmentEntities = fragmentRepository.findByAnchorAndXpathIn(anchorEntity,
- normalizedXpaths);
+ normalizedXpaths);
for (final FragmentEntity fragmentEntity : fragmentEntities) {
normalizedXpaths.remove(fragmentEntity.getXpath());
@@ -647,15 +577,6 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
return fragmentEntities;
}
- private static String getListElementXpathPrefix(final Collection<DataNode> newListElements) {
- if (newListElements.isEmpty()) {
- throw new CpsAdminException("Invalid list replacement",
- "Cannot replace list elements with empty collection");
- }
- final String firstChildNodeXpath = newListElements.iterator().next().getXpath();
- return firstChildNodeXpath.substring(0, firstChildNodeXpath.lastIndexOf('[') + 1);
- }
-
private FragmentEntity getFragmentForReplacement(final FragmentEntity parentEntity,
final DataNode newListElement,
final FragmentEntity existingListElementEntity) {
@@ -671,6 +592,28 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
return existingListElementEntity;
}
+ private String mergeLeaves(final Map<String, Serializable> updateLeaves, final String currentLeavesAsString) {
+ Map<String, Serializable> currentLeavesAsMap = new HashMap<>();
+ if (currentLeavesAsString != null) {
+ currentLeavesAsMap = jsonObjectMapper.convertJsonString(currentLeavesAsString, Map.class);
+ currentLeavesAsMap.putAll(updateLeaves);
+ }
+
+ if (currentLeavesAsMap.isEmpty()) {
+ return "";
+ }
+ return jsonObjectMapper.asJsonString(currentLeavesAsMap);
+ }
+
+ private void copyAttributesFromNewDataNode(final FragmentEntity existingFragmentEntity,
+ final DataNode newDataNode) {
+ final String oldOrderedLeavesAsJson = getOrderedLeavesAsJson(existingFragmentEntity.getAttributes());
+ final String newOrderedLeavesAsJson = getOrderedLeavesAsJson(newDataNode.getLeaves());
+ if (!oldOrderedLeavesAsJson.equals(newOrderedLeavesAsJson)) {
+ existingFragmentEntity.setAttributes(jsonObjectMapper.asJsonString(newDataNode.getLeaves()));
+ }
+ }
+
private String getOrderedLeavesAsJson(final Map<String, Serializable> currentLeaves) {
final Map<String, Serializable> sortedLeaves = new TreeMap<>(String::compareTo);
sortedLeaves.putAll(currentLeaves);
@@ -686,6 +629,38 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
return jsonObjectMapper.asJsonString(sortedLeaves);
}
+ private static String getNormalizedXpath(final String xpathSource) {
+ if (isRootXpath(xpathSource)) {
+ return xpathSource;
+ }
+ try {
+ return CpsPathUtil.getNormalizedXpath(xpathSource);
+ } catch (final PathParsingException pathParsingException) {
+ throw new CpsPathException(pathParsingException.getMessage());
+ }
+ }
+
+ private static Collection<String> getNormalizedXpaths(final Collection<String> xpaths) {
+ final Collection<String> normalizedXpaths = new HashSet<>(xpaths.size());
+ for (final String xpath : xpaths) {
+ try {
+ normalizedXpaths.add(getNormalizedXpath(xpath));
+ } catch (final CpsPathException cpsPathException) {
+ log.warn("Error parsing xpath \"{}\": {}", xpath, cpsPathException.getMessage());
+ }
+ }
+ return normalizedXpaths;
+ }
+
+ private static String getListElementXpathPrefix(final Collection<DataNode> newListElements) {
+ if (newListElements.isEmpty()) {
+ throw new CpsAdminException("Invalid list replacement",
+ "Cannot replace list elements with empty collection");
+ }
+ final String firstChildNodeXpath = newListElements.iterator().next().getXpath();
+ return firstChildNodeXpath.substring(0, firstChildNodeXpath.lastIndexOf('[') + 1);
+ }
+
private static Map<String, FragmentEntity> extractListElementFragmentEntitiesByXPath(
final Set<FragmentEntity> childEntities, final String listElementXpathPrefix) {
return childEntities.stream()
@@ -717,25 +692,23 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
return !existingListElementsByXpath.containsKey(replacementDataNode.getXpath());
}
- private void copyAttributesFromNewDataNode(final FragmentEntity existingFragmentEntity,
- final DataNode newDataNode) {
- final String oldOrderedLeavesAsJson = getOrderedLeavesAsJson(existingFragmentEntity.getAttributes());
- final String newOrderedLeavesAsJson = getOrderedLeavesAsJson(newDataNode.getLeaves());
- if (!oldOrderedLeavesAsJson.equals(newOrderedLeavesAsJson)) {
- existingFragmentEntity.setAttributes(jsonObjectMapper.asJsonString(newDataNode.getLeaves()));
+ private static CpsPathQuery getCpsPathQuery(final String cpsPath) {
+ try {
+ return CpsPathUtil.getCpsPathQuery(cpsPath);
+ } catch (final PathParsingException e) {
+ throw new CpsPathException(e.getMessage());
}
}
- private String mergeLeaves(final Map<String, Serializable> updateLeaves, final String currentLeavesAsString) {
- Map<String, Serializable> currentLeavesAsMap = new HashMap<>();
- if (currentLeavesAsString != null) {
- currentLeavesAsMap = jsonObjectMapper.convertJsonString(currentLeavesAsString, Map.class);
- currentLeavesAsMap.putAll(updateLeaves);
- }
-
- if (currentLeavesAsMap.isEmpty()) {
- return "";
+ private static void logMissingXPaths(final Collection<String> xpaths,
+ final Collection<FragmentEntity> existingFragmentEntities) {
+ final Set<String> existingXPaths =
+ existingFragmentEntities.stream().map(FragmentEntity::getXpath).collect(Collectors.toSet());
+ final Set<String> missingXPaths =
+ xpaths.stream().filter(xpath -> !existingXPaths.contains(xpath)).collect(Collectors.toSet());
+ if (!missingXPaths.isEmpty()) {
+ log.warn("Cannot update data nodes: Target XPaths {} not found in DB.", missingXPaths);
}
- return jsonObjectMapper.asJsonString(currentLeavesAsMap);
}
+
}
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepository.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepository.java
index 9598230cdb..a8c1fd2d4e 100755
--- a/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepository.java
@@ -25,12 +25,10 @@ package org.onap.cps.ri.repository;
import java.util.Collection;
import java.util.List;
-import java.util.Optional;
import org.onap.cps.ri.models.AnchorEntity;
import org.onap.cps.ri.models.DataspaceEntity;
import org.onap.cps.ri.models.FragmentEntity;
import org.onap.cps.ri.utils.EscapeUtils;
-import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
@@ -41,12 +39,8 @@ import org.springframework.stereotype.Repository;
public interface FragmentRepository extends JpaRepository<FragmentEntity, Long>, FragmentRepositoryCpsPathQuery,
FragmentPrefetchRepository {
- Optional<FragmentEntity> findByAnchorAndXpath(AnchorEntity anchorEntity, String xpath);
-
- default FragmentEntity getByAnchorAndXpath(final AnchorEntity anchorEntity, final String xpath) {
- return findByAnchorAndXpath(anchorEntity, xpath).orElseThrow(() ->
- new DataNodeNotFoundException(anchorEntity.getDataspace().getName(), anchorEntity.getName(), xpath));
- }
+ @Query(value = "SELECT * FROM fragment WHERE anchor_id = :anchorId AND xpath = :xpath", nativeQuery = true)
+ FragmentEntity findByAnchorIdAndXpath(@Param("anchorId") long anchorId, @Param("xpath") String xpath);
@Query(value = "SELECT * FROM fragment WHERE anchor_id = :anchorId AND xpath IN (:xpaths)",
nativeQuery = true)
@@ -84,9 +78,6 @@ public interface FragmentRepository extends JpaRepository<FragmentEntity, Long>,
List<FragmentEntity> findByAnchorIdsAndXpathIn(@Param("anchorIds") Collection<Long> anchorIds,
@Param("xpaths") Collection<String> xpaths);
- @Query(value = "SELECT * FROM fragment WHERE anchor_id = :anchorId LIMIT 1", nativeQuery = true)
- Optional<FragmentEntity> findOneByAnchorId(@Param("anchorId") long anchorId);
-
@Modifying
@Query(value = "DELETE FROM fragment WHERE anchor_id IN (:anchorIds)", nativeQuery = true)
void deleteByAnchorIdIn(@Param("anchorIds") Collection<Long> anchorIds);
diff --git a/cps-ri/src/test/groovy/org/onap/cps/ri/CpsDataPersistenceServiceImplSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/ri/CpsDataPersistenceServiceImplSpec.groovy
index 36bf55e2db..500fe76a90 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/ri/CpsDataPersistenceServiceImplSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/ri/CpsDataPersistenceServiceImplSpec.groovy
@@ -246,7 +246,7 @@ class CpsDataPersistenceServiceImplSpec extends Specification {
def createDataNodeAndMockRepositoryMethodSupportingIt(xpath, scenario) {
def dataNode = new DataNodeBuilder().withXpath(xpath).build()
def fragmentEntity = new FragmentEntity(xpath: xpath, childFragments: [])
- mockFragmentRepository.getByAnchorAndXpath(_, xpath) >> fragmentEntity
+ mockFragmentRepository.findByAnchorIdAndXpath(_, xpath) >> fragmentEntity
if ('EXCEPTION' == scenario) {
mockFragmentRepository.save(fragmentEntity) >> { throw new StaleStateException("concurrent updates") }
}
diff --git a/csit/plans/cps/test.properties b/csit/plans/cps/test.properties
index e7b9519c2d..52e82bdb85 100644
--- a/csit/plans/cps/test.properties
+++ b/csit/plans/cps/test.properties
@@ -21,7 +21,7 @@ DMI_SERVICE_URL=http://$LOCAL_IP:$DMI_PORT
DOCKER_REPO=nexus3.onap.org:10003
CPS_VERSION=latest
-DMI_VERSION=1.5.1-SNAPSHOT-latest
+DMI_VERSION=latest
ADVISED_MODULES_SYNC_SLEEP_TIME_MS=2000
CMHANDLE_DATA_SYNC_SLEEP_TIME_MS=2000
diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml
index feb58d849d..ae34fc3606 100644
--- a/docker-compose/docker-compose.yml
+++ b/docker-compose/docker-compose.yml
@@ -142,7 +142,7 @@ services:
ncmp-dmi-plugin-demo-and-csit-stub:
container_name: ${NCMP_DMI_PLUGIN_DEMO_AND_CSIT_STUB_CONTAINER_NAME:-ncmp-dmi-plugin-demo-and-csit-stub}
- image: ${DOCKER_REPO:-nexus3.onap.org:10003}/onap/dmi-plugin-demo-and-csit-stub:${DMI_DEMO_STUB_VERSION:-latest}
+ image: ${DOCKER_REPO:-nexus3.onap.org:10003}/onap/dmi-stub:${DMI_DEMO_STUB_VERSION:-latest}
ports:
- ${DMI_DEMO_STUB_PORT:-8784}:8092
environment:
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
index 02a10cfa6b..aea5c10a93 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
@@ -266,9 +266,9 @@ abstract class CpsIntegrationSpecBase extends Specification {
def registerSequenceOfCmHandlesWithManyModuleReferencesButDoNotWaitForReady(dmiPlugin, moduleSetTag, numberOfCmHandles, offset) {
def cmHandles = []
def id = offset
- def moduleReferences = (1..200).collect { moduleSetTag + '_Module_' + it.toString() }
+ def moduleReferences = (1..200).collect { "${moduleSetTag}Module${it}" }
(1..numberOfCmHandles).each {
- def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'ch-'+id, moduleSetTag: moduleSetTag, alternateId: NO_ALTERNATE_ID)
+ def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: "ch-${id}", moduleSetTag: moduleSetTag, alternateId: NO_ALTERNATE_ID)
cmHandles.add(ncmpServiceCmHandle)
dmiDispatcher1.moduleNamesPerCmHandleId[ncmpServiceCmHandle.cmHandleId] = moduleReferences
dmiDispatcher2.moduleNamesPerCmHandleId[ncmpServiceCmHandle.cmHandleId] = moduleReferences
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy
index 963bc1fe61..20fa546eba 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy
@@ -132,7 +132,7 @@ class ModuleSyncWatchdogIntegrationSpec extends CpsIntegrationSpecBase {
}
def logInstrumentation(timer, description) {
- System.out.println('*** CPS-2478, ' + description + ' : ' + timer.count()+ ' times, total ' + timer.totalTime(TimeUnit.MILLISECONDS) + ' ms')
+ println "*** CPS-2478, $description : Invoked ${timer.count()} times, Total Time: ${timer.totalTime(TimeUnit.MILLISECONDS)} ms, Mean Time: ${timer.mean(TimeUnit.MILLISECONDS)} ms"
return true
}