Read Performance Improvement - Using Native Query
[cps.git] / cps-ri / src / main / java / org / onap / cps / spi / impl / CpsDataPersistenceServiceImpl.java
index 06c12a8..2a4a192 100644 (file)
@@ -51,6 +51,8 @@ import org.onap.cps.spi.cache.AnchorDataCacheEntry;
 import org.onap.cps.spi.entities.AnchorEntity;
 import org.onap.cps.spi.entities.DataspaceEntity;
 import org.onap.cps.spi.entities.FragmentEntity;
+import org.onap.cps.spi.entities.FragmentEntityArranger;
+import org.onap.cps.spi.entities.FragmentExtract;
 import org.onap.cps.spi.entities.SchemaSetEntity;
 import org.onap.cps.spi.entities.YangResourceEntity;
 import org.onap.cps.spi.exceptions.AlreadyDefinedException;
@@ -120,7 +122,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
 
     private void addNewChildDataNode(final String dataspaceName, final String anchorName,
                                      final String parentNodeXpath, final DataNode newChild) {
-        final FragmentEntity parentFragmentEntity = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath);
+        final FragmentEntity parentFragmentEntity =
+            getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, parentNodeXpath);
         final FragmentEntity newChildAsFragmentEntity =
                 convertToFragmentWithAllDescendants(parentFragmentEntity.getDataspace(),
                         parentFragmentEntity.getAnchor(), newChild);
@@ -135,7 +138,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
 
     private void addChildrenDataNodes(final String dataspaceName, final String anchorName, final String parentNodeXpath,
                                       final Collection<DataNode> newChildren) {
-        final FragmentEntity parentFragmentEntity = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath);
+        final FragmentEntity parentFragmentEntity =
+            getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, parentNodeXpath);
         final List<FragmentEntity> fragmentEntities = new ArrayList<>(newChildren.size());
         try {
             newChildren.forEach(newChildAsDataNode -> {
@@ -219,19 +223,25 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
     @Override
     public DataNode getDataNode(final String dataspaceName, final String anchorName, final String xpath,
                                 final FetchDescendantsOption fetchDescendantsOption) {
-        final FragmentEntity fragmentEntity = getFragmentByXpath(dataspaceName, anchorName, xpath);
+        final FragmentEntity fragmentEntity = getFragmentByXpath(dataspaceName, anchorName, xpath,
+            fetchDescendantsOption);
         final DataNode dataNode = toDataNode(fragmentEntity, fetchDescendantsOption);
         dataNode.setModuleNamePrefix(getRootModuleNamePrefix(fragmentEntity.getAnchor()));
         return dataNode;
     }
 
+    private FragmentEntity getFragmentWithoutDescendantsByXpath(final String dataspaceName,
+                                                                final String anchorName,
+                                                                final String xpath) {
+        return getFragmentByXpath(dataspaceName, anchorName, xpath, FetchDescendantsOption.OMIT_DESCENDANTS);
+    }
+
     private FragmentEntity getFragmentByXpath(final String dataspaceName, final String anchorName,
-                                              final String xpath) {
+                                              final String xpath, final FetchDescendantsOption fetchDescendantsOption) {
         final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
         final AnchorEntity anchorEntity = anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName);
         if (isRootXpath(xpath)) {
-            return fragmentRepository.findFirstRootByDataspaceAndAnchor(
-                    dataspaceEntity, anchorEntity);
+            return fragmentRepository.findFirstRootByDataspaceAndAnchor(dataspaceEntity, anchorEntity);
         } else {
             final String normalizedXpath;
             try {
@@ -239,9 +249,21 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
             } catch (final PathParsingException e) {
                 throw new CpsPathException(e.getMessage());
             }
-
-            return fragmentRepository.getByDataspaceAndAnchorAndXpath(
-                    dataspaceEntity, anchorEntity, normalizedXpath);
+            final FragmentEntity fragmentEntity;
+            if (FetchDescendantsOption.OMIT_DESCENDANTS.equals(fetchDescendantsOption)) {
+                fragmentEntity =
+                    fragmentRepository.getByDataspaceAndAnchorAndXpath(dataspaceEntity, anchorEntity, normalizedXpath);
+            } else {
+                final List<FragmentExtract> fragmentExtracts =
+                    fragmentRepository.findByAnchorIdAndParentXpath(anchorEntity.getId(), normalizedXpath);
+                log.debug("Fetched {} fragment entities by anchor {} and cps path {}.",
+                    fragmentExtracts.size(), anchorName, xpath);
+                fragmentEntity = FragmentEntityArranger.toFragmentEntityTree(anchorEntity, fragmentExtracts);
+            }
+            if (fragmentEntity == null) {
+                throw new DataNodeNotFoundException(dataspaceEntity.getName(), anchorEntity.getName(), xpath);
+            }
+            return fragmentEntity;
         }
     }
 
@@ -316,7 +338,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
     }
 
     private String getRootModuleNamePrefix(final AnchorEntity anchorEntity) {
-        final String cachedModuleNamePrefix = getModuleNamePrefixFromCache(anchorEntity);
+        final String cachedModuleNamePrefix = getModuleNamePrefixFromCache(anchorEntity.getName());
         if (cachedModuleNamePrefix != null) {
             return cachedModuleNamePrefix;
         }
@@ -344,9 +366,9 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
         }
     }
 
-    private String getModuleNamePrefixFromCache(final AnchorEntity anchorEntity) {
-        if (anchorDataCache.containsKey(anchorEntity.getName())) {
-            final AnchorDataCacheEntry anchorDataCacheEntry = anchorDataCache.get(anchorEntity.getName());
+    private String getModuleNamePrefixFromCache(final String anchorName) {
+        if (anchorDataCache.containsKey(anchorName)) {
+            final AnchorDataCacheEntry anchorDataCacheEntry = anchorDataCache.get(anchorName);
             return anchorDataCacheEntry.hasProperty(TOP_LEVEL_MODULE_PREFIX_PROPERTY_NAME)
                     ? anchorDataCacheEntry.getProperty(TOP_LEVEL_MODULE_PREFIX_PROPERTY_NAME).toString() : null;
         }
@@ -366,7 +388,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
     @Override
     public void updateDataLeaves(final String dataspaceName, final String anchorName, final String xpath,
                                  final Map<String, Object> leaves) {
-        final FragmentEntity fragmentEntity = getFragmentByXpath(dataspaceName, anchorName, xpath);
+        final FragmentEntity fragmentEntity = getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, xpath);
         fragmentEntity.setAttributes(jsonObjectMapper.asJsonString(leaves));
         fragmentRepository.save(fragmentEntity);
     }
@@ -374,7 +396,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
     @Override
     public void updateDataNodeAndDescendants(final String dataspaceName, final String anchorName,
                                              final DataNode dataNode) {
-        final FragmentEntity fragmentEntity = getFragmentByXpath(dataspaceName, anchorName, dataNode.getXpath());
+        final FragmentEntity fragmentEntity =
+            getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, dataNode.getXpath());
         updateFragmentEntityAndDescendantsWithDataNode(fragmentEntity, dataNode);
         try {
             fragmentRepository.save(fragmentEntity);
@@ -393,7 +416,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
         final Map<DataNode, FragmentEntity> dataNodeFragmentEntityMap = dataNodes.stream()
                 .collect(Collectors.toMap(
                         dataNode -> dataNode,
-                        dataNode -> getFragmentByXpath(dataspaceName, anchorName, dataNode.getXpath())));
+                        dataNode ->
+                            getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, dataNode.getXpath())));
         dataNodeFragmentEntityMap.forEach(
                 (dataNode, fragmentEntity) -> updateFragmentEntityAndDescendantsWithDataNode(fragmentEntity, dataNode));
         try {
@@ -453,7 +477,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
     @Transactional
     public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
                                    final Collection<DataNode> newListElements) {
-        final FragmentEntity parentEntity = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath);
+        final FragmentEntity parentEntity =
+            getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, parentNodeXpath);
         final String listElementXpathPrefix = getListElementXpathPrefix(newListElements);
         final Map<String, FragmentEntity> existingListElementFragmentEntitiesByXPath =
                 extractListElementFragmentEntitiesByXPath(parentEntity.getChildFragments(), listElementXpathPrefix);
@@ -507,7 +532,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
             } else {
                 parentNodeXpath = targetXpath.substring(0, targetXpath.lastIndexOf('/'));
             }
-            parentFragmentEntity = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath);
+            parentFragmentEntity = getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, parentNodeXpath);
             final String lastXpathElement = targetXpath.substring(targetXpath.lastIndexOf('/'));
             final boolean isListElement = REG_EX_PATTERN_FOR_LIST_ELEMENT_KEY_PREDICATE
                     .matcher(lastXpathElement).find();