diff options
Diffstat (limited to 'cps-ri/src')
3 files changed, 179 insertions, 215 deletions
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") } } |