CPS-475: Fix Sonar Qube Violations
[cps.git] / cps-ri / src / main / java / org / onap / cps / spi / impl / CpsDataPersistenceServiceImpl.java
index f924c70..c616c8f 100644 (file)
@@ -91,7 +91,8 @@ 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 Pattern REG_EX_PATTERN_FOR_LIST_ELEMENT_KEY_PREDICATE =
+            Pattern.compile("\\[(\\@([^\\/]{0,9999}))\\]$");
 
     @Override
     public void addChildDataNode(final String dataspaceName, final String anchorName, final String parentXpath,
@@ -108,7 +109,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<DataNode> dataNodes) {
         final FragmentEntity parentFragment = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath);
         final List<FragmentEntity> newFragmentEntities =
@@ -296,23 +297,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<String, FragmentEntity> existingChildrenByXpath = existingFragmentEntity.getChildFragments()
             .stream().collect(Collectors.toMap(FragmentEntity::getXpath, childFragmentEntity -> childFragmentEntity));
 
-        final Collection updatedChildFragments = new HashSet<FragmentEntity>();
+        final Collection<FragmentEntity> 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 +323,19 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
 
     @Override
     @Transactional
-    public void replaceListDataNodes(final String dataspaceName, final String anchorName, final String parentNodeXpath,
-                                     final Collection<DataNode> replacementDataNodes) {
+    public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
+                                   final Collection<DataNode> newListElements) {
         final FragmentEntity parentEntity = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath);
-        final String listNodeXpathPrefix = getListNodeXpathPrefix(replacementDataNodes);
+        final String listElementXpathPrefix = getListElementXpathPrefix(newListElements);
         final Map<String, FragmentEntity> existingListElementFragmentEntitiesByXPath =
-            extractListElementFragmentEntitiesByXPath(parentEntity.getChildFragments(), listNodeXpathPrefix);
-        removeExistingListElements(parentEntity.getChildFragments(), existingListElementFragmentEntitiesByXPath);
+            extractListElementFragmentEntitiesByXPath(parentEntity.getChildFragments(), listElementXpathPrefix);
+        deleteListElements(parentEntity.getChildFragments(), existingListElementFragmentEntitiesByXPath);
         final Set<FragmentEntity> 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 +343,110 @@ 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 = REG_EX_PATTERN_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<FragmentEntity> fragmentEntities,
         final Map<String, FragmentEntity> existingListElementFragmentEntitiesByXPath) {
         fragmentEntities.removeAll(existingListElementFragmentEntitiesByXPath.values());
     }
 
-    private static String getListNodeXpathPrefix(final Collection<DataNode> replacementDataNodes) {
-        final String firstChildNodeXpath = replacementDataNodes.iterator().next().getXpath();
+    private static String getListElementXpathPrefix(final Collection<DataNode> 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<String, FragmentEntity> existingListNodeElementsByXpath) {
-        return !existingListNodeElementsByXpath.containsKey(replacementDataNode.getXpath());
+                                         final Map<String, FragmentEntity> 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<String, FragmentEntity> extractListElementFragmentEntitiesByXPath(
-        final Set<FragmentEntity> childEntities, final String listNodeXpathPrefix) {
+        final Set<FragmentEntity> 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);
     }