From a79c9f1bdf335843c29a425da53c15b5e353e5a3 Mon Sep 17 00:00:00 2001 From: DylanB95EST Date: Fri, 29 Oct 2021 17:33:06 +0100 Subject: Clean Up Code around List Nodes Make sure code refers clearly to List (whole) nodes or List elements incl. method names, parameter names, test descriptions etc. Issue-ID: CPS-756 Change-Id: Ic9dae6565c0e84c1ba4c2d6e891d3ea307f589da Signed-off-by: DylanB95EST --- .../spi/impl/CpsDataPersistenceServiceImpl.java | 170 ++++++++++++--------- 1 file changed, 98 insertions(+), 72 deletions(-) (limited to 'cps-ri/src/main/java') diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java index 2397d31792..8dc6c2f69c 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java @@ -91,7 +91,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService private static final Gson GSON = new GsonBuilder().create(); private static final String REG_EX_FOR_OPTIONAL_LIST_INDEX = "(\\[@[\\s\\S]+?]){0,1})"; - private static final String REG_EX_FOR_LIST_NODE_KEY = "\\[(\\@([^/]*?)){0,99}( and)*\\]$"; + private static final String REG_EX_FOR_LIST_ELEMENT_KEY_PREDICATE = "\\[(\\@([^/]*?)){0,99}( and)*\\]$"; @Override public void addChildDataNode(final String dataspaceName, final String anchorName, final String parentXpath, @@ -108,7 +108,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } @Override - public void addListDataNodes(final String dataspaceName, final String anchorName, final String parentNodeXpath, + public void addListElements(final String dataspaceName, final String anchorName, final String parentNodeXpath, final Collection dataNodes) { final FragmentEntity parentFragment = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath); final List newFragmentEntities = @@ -296,23 +296,23 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } private static void replaceDataNodeTree(final FragmentEntity existingFragmentEntity, - final DataNode submittedDataNode) { + final DataNode newDataNode) { - existingFragmentEntity.setAttributes(GSON.toJson(submittedDataNode.getLeaves())); + existingFragmentEntity.setAttributes(GSON.toJson(newDataNode.getLeaves())); final Map existingChildrenByXpath = existingFragmentEntity.getChildFragments() .stream().collect(Collectors.toMap(FragmentEntity::getXpath, childFragmentEntity -> childFragmentEntity)); final Collection updatedChildFragments = new HashSet<>(); - for (final DataNode submittedChildDataNode : submittedDataNode.getChildDataNodes()) { + for (final DataNode newDataNodeChild : newDataNode.getChildDataNodes()) { final FragmentEntity childFragment; - if (isNewDataNode(submittedChildDataNode, existingChildrenByXpath)) { + if (isNewDataNode(newDataNodeChild, existingChildrenByXpath)) { childFragment = convertToFragmentWithAllDescendants( - existingFragmentEntity.getDataspace(), existingFragmentEntity.getAnchor(), submittedChildDataNode); + existingFragmentEntity.getDataspace(), existingFragmentEntity.getAnchor(), newDataNodeChild); } else { - childFragment = existingChildrenByXpath.get(submittedChildDataNode.getXpath()); - replaceDataNodeTree(childFragment, submittedChildDataNode); + childFragment = existingChildrenByXpath.get(newDataNodeChild.getXpath()); + replaceDataNodeTree(childFragment, newDataNodeChild); } updatedChildFragments.add(childFragment); } @@ -322,19 +322,19 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService @Override @Transactional - public void replaceListDataNodes(final String dataspaceName, final String anchorName, final String parentNodeXpath, - final Collection replacementDataNodes) { + public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath, + final Collection newListElements) { final FragmentEntity parentEntity = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath); - final String listNodeXpathPrefix = getListNodeXpathPrefix(replacementDataNodes); + final String listElementXpathPrefix = getListElementXpathPrefix(newListElements); final Map existingListElementFragmentEntitiesByXPath = - extractListElementFragmentEntitiesByXPath(parentEntity.getChildFragments(), listNodeXpathPrefix); - removeExistingListElements(parentEntity.getChildFragments(), existingListElementFragmentEntitiesByXPath); + extractListElementFragmentEntitiesByXPath(parentEntity.getChildFragments(), listElementXpathPrefix); + deleteListElements(parentEntity.getChildFragments(), existingListElementFragmentEntitiesByXPath); final Set updatedChildFragmentEntities = new HashSet<>(); - for (final DataNode replacementDataNode : replacementDataNodes) { - final FragmentEntity existingListNodeElementEntity = - existingListElementFragmentEntitiesByXPath.get(replacementDataNode.getXpath()); - final FragmentEntity entityToBeAdded = getFragmentForReplacement(parentEntity, replacementDataNode, - existingListNodeElementEntity); + for (final DataNode newListElement : newListElements) { + final FragmentEntity existingListElementEntity = + existingListElementFragmentEntitiesByXPath.get(newListElement.getXpath()); + final FragmentEntity entityToBeAdded = getFragmentForReplacement(parentEntity, newListElement, + existingListElementEntity); updatedChildFragmentEntities.add(entityToBeAdded); } @@ -342,85 +342,111 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService fragmentRepository.save(parentEntity); } - private static void removeExistingListElements( + + @Override + @Transactional + public void deleteListDataNode(final String dataspaceName, final String anchorName, + final String targetXpath) { + deleteDataNode(dataspaceName, anchorName, targetXpath, true); + } + + @Override + @Transactional + public void deleteDataNode(final String dataspaceName, final String anchorName, final String targetXpath) { + deleteDataNode(dataspaceName, anchorName, targetXpath, false); + } + + private void deleteDataNode(final String dataspaceName, final String anchorName, final String targetXpath, + final boolean onlySupportListNodeDeletion) { + final String parentNodeXpath = targetXpath.substring(0, targetXpath.lastIndexOf('/')); + final FragmentEntity parentFragmentEntity = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath); + final String lastXpathElement = targetXpath.substring(targetXpath.lastIndexOf('/')); + final boolean isListElement = Pattern.compile(REG_EX_FOR_LIST_ELEMENT_KEY_PREDICATE) + .matcher(lastXpathElement).find(); + boolean targetExist; + if (isListElement) { + targetExist = deleteDataNode(parentFragmentEntity, targetXpath); + } else { + targetExist = deleteAllListElements(parentFragmentEntity, targetXpath); + final boolean tryToDeleteDataNode = !targetExist && !onlySupportListNodeDeletion; + if (tryToDeleteDataNode) { + targetExist = deleteDataNode(parentFragmentEntity, targetXpath); + } + } + if (!targetExist) { + final String additionalInformation = onlySupportListNodeDeletion + ? "The target is probably not a List." : ""; + throw new DataNodeNotFoundException(parentFragmentEntity.getDataspace().getName(), + parentFragmentEntity.getAnchor().getName(), targetXpath, additionalInformation); + } + } + + private boolean deleteDataNode(final FragmentEntity parentFragmentEntity, final String targetXpath) { + if (parentFragmentEntity.getChildFragments() + .removeIf(fragment -> fragment.getXpath().equals(targetXpath))) { + fragmentRepository.save(parentFragmentEntity); + return true; + } + return false; + } + + + private boolean deleteAllListElements(final FragmentEntity parentFragmentEntity, final String listXpath) { + final String deleteTargetXpathPrefix = listXpath + "["; + if (parentFragmentEntity.getChildFragments() + .removeIf(fragment -> fragment.getXpath().startsWith(deleteTargetXpathPrefix))) { + fragmentRepository.save(parentFragmentEntity); + return true; + } + return false; + } + + private static void deleteListElements( final Collection fragmentEntities, final Map existingListElementFragmentEntitiesByXPath) { fragmentEntities.removeAll(existingListElementFragmentEntitiesByXPath.values()); } - private static String getListNodeXpathPrefix(final Collection replacementDataNodes) { - final String firstChildNodeXpath = replacementDataNodes.iterator().next().getXpath(); + private static String getListElementXpathPrefix(final Collection newListElements) { + final String firstChildNodeXpath = newListElements.iterator().next().getXpath(); return firstChildNodeXpath.substring(0, firstChildNodeXpath.lastIndexOf("[") + 1); } private static FragmentEntity getFragmentForReplacement(final FragmentEntity parentEntity, - final DataNode replacementDataNode, - final FragmentEntity existingListNodeElementEntity) { - if (existingListNodeElementEntity == null) { + final DataNode newListElement, + final FragmentEntity existingListElementEntity) { + if (existingListElementEntity == null) { return convertToFragmentWithAllDescendants( - parentEntity.getDataspace(), parentEntity.getAnchor(), replacementDataNode); + parentEntity.getDataspace(), parentEntity.getAnchor(), newListElement); } - if (replacementDataNode.getChildDataNodes().isEmpty()) { - copyAttributesFromReplacementDataNode(existingListNodeElementEntity, replacementDataNode); - existingListNodeElementEntity.getChildFragments().clear(); + if (newListElement.getChildDataNodes().isEmpty()) { + copyAttributesFromNewListElement(existingListElementEntity, newListElement); + existingListElementEntity.getChildFragments().clear(); } else { - replaceDataNodeTree(existingListNodeElementEntity, replacementDataNode); + replaceDataNodeTree(existingListElementEntity, newListElement); } - return existingListNodeElementEntity; + return existingListElementEntity; } private static boolean isNewDataNode(final DataNode replacementDataNode, - final Map existingListNodeElementsByXpath) { - return !existingListNodeElementsByXpath.containsKey(replacementDataNode.getXpath()); + final Map existingListElementsByXpath) { + return !existingListElementsByXpath.containsKey(replacementDataNode.getXpath()); } - private static void copyAttributesFromReplacementDataNode(final FragmentEntity existingListNodeElementEntity, - final DataNode replacementDataNode) { + private static void copyAttributesFromNewListElement(final FragmentEntity existingListElementEntity, + final DataNode newListElement) { final FragmentEntity replacementFragmentEntity = - FragmentEntity.builder().attributes(GSON.toJson(replacementDataNode.getLeaves())).build(); - existingListNodeElementEntity.setAttributes(replacementFragmentEntity.getAttributes()); + FragmentEntity.builder().attributes(GSON.toJson(newListElement.getLeaves())).build(); + existingListElementEntity.setAttributes(replacementFragmentEntity.getAttributes()); } private static Map extractListElementFragmentEntitiesByXPath( - final Set childEntities, final String listNodeXpathPrefix) { + final Set childEntities, final String listElementXpathPrefix) { return childEntities.stream() - .filter(fragmentEntity -> fragmentEntity.getXpath().startsWith(listNodeXpathPrefix)) + .filter(fragmentEntity -> fragmentEntity.getXpath().startsWith(listElementXpathPrefix)) .collect(Collectors.toMap(FragmentEntity::getXpath, fragmentEntity -> fragmentEntity)); } - @Override - @Transactional - public void deleteListDataNodes(final String dataspaceName, final String anchorName, final String listNodeXpath) { - final String parentNodeXpath = listNodeXpath.substring(0, listNodeXpath.lastIndexOf('/')); - final FragmentEntity parentEntity = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath); - final String descendantNode = listNodeXpath.substring(listNodeXpath.lastIndexOf('/')); - final Matcher descendantNodeHasListNodeKey = Pattern.compile(REG_EX_FOR_LIST_NODE_KEY).matcher(descendantNode); - - final boolean xpathPointsToAValidChildNodeWithKey = parentEntity.getChildFragments().stream().anyMatch( - fragment -> fragment.getXpath().equals(listNodeXpath)); - - final boolean xpathPointsToAValidChildNodeWithoutKey = parentEntity.getChildFragments().stream().anyMatch( - fragment -> fragment.getXpath().replaceAll(REG_EX_FOR_LIST_NODE_KEY, "").equals(listNodeXpath)); - - if ((descendantNodeHasListNodeKey.find() && xpathPointsToAValidChildNodeWithKey) - || - (!descendantNodeHasListNodeKey.find() && xpathPointsToAValidChildNodeWithoutKey)) { - removeListNodeDescendants(parentEntity, listNodeXpath); - } else { - throw new DataNodeNotFoundException(parentEntity.getDataspace().getName(), - parentEntity.getAnchor().getName(), listNodeXpath); - } - } - - private void removeListNodeDescendants(final FragmentEntity parentFragmentEntity, final String listNodeXpath) { - final Matcher descendantNodeHasListNodeKey = Pattern.compile(REG_EX_FOR_LIST_NODE_KEY).matcher(listNodeXpath); - final String listNodeXpathPrefix = listNodeXpath + (descendantNodeHasListNodeKey.find() ? "" : "["); - if (parentFragmentEntity.getChildFragments() - .removeIf(fragment -> fragment.getXpath().startsWith(listNodeXpathPrefix))) { - fragmentRepository.save(parentFragmentEntity); - } - } - private static boolean isRootXpath(final String xpath) { return "/".equals(xpath) || "".equals(xpath); } -- cgit 1.2.3-korg