Merge "Use recursive SQL to fetch descendants in CpsPath queries (CPS-1664 #4)"
authorSourabh Sourabh <sourabh.sourabh@est.tech>
Mon, 8 May 2023 09:57:37 +0000 (09:57 +0000)
committerGerrit Code Review <gerrit@onap.org>
Mon, 8 May 2023 09:57:37 +0000 (09:57 +0000)
1  2 
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java

@@@ -65,7 -65,6 +65,6 @@@ import org.onap.cps.spi.model.DataNode
  import org.onap.cps.spi.model.DataNodeBuilder;
  import org.onap.cps.spi.repository.AnchorRepository;
  import org.onap.cps.spi.repository.DataspaceRepository;
- import org.onap.cps.spi.repository.FragmentQueryBuilder;
  import org.onap.cps.spi.repository.FragmentRepository;
  import org.onap.cps.spi.utils.SessionManager;
  import org.onap.cps.utils.JsonObjectMapper;
@@@ -83,7 -82,7 +82,7 @@@ public class CpsDataPersistenceServiceI
      private final JsonObjectMapper jsonObjectMapper;
      private final SessionManager sessionManager;
  
 -    private static final String REG_EX_FOR_OPTIONAL_LIST_INDEX = "(\\[@[\\s\\S]+?])?)";
 +    private static final String REG_EX_FOR_OPTIONAL_LIST_INDEX = "(\\[@.+?])?)";
      private static final String QUERY_ACROSS_ANCHORS = null;
      private static final AnchorEntity ALL_ANCHORS = null;
  
          }
      }
  
 -    @Override
 -    public void storeDataNode(final String dataspaceName, final String anchorName, final DataNode dataNode) {
 -        storeDataNodes(dataspaceName, anchorName, Collections.singletonList(dataNode));
 -    }
 -
      @Override
      public void storeDataNodes(final String dataspaceName, final String anchorName,
                                 final Collection<DataNode> dataNodes) {
          return fragmentEntity;
      }
  
-     private Collection<FragmentEntity> buildFragmentEntitiesFromFragmentExtracts(final AnchorEntity anchorEntity,
-                                                                                  final String normalizedXpath) {
-         final List<FragmentExtract> fragmentExtracts =
-             fragmentRepository.findByAnchorAndParentXpath(anchorEntity, normalizedXpath);
-         return FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts);
-     }
      @Override
      @Timed(value = "cps.data.persistence.service.datanode.query",
              description = "Time taken to query data nodes")
          }
  
          Collection<FragmentEntity> fragmentEntities;
-         if (canUseRegexQuickFind(fetchDescendantsOption, cpsPathQuery)) {
-             return getDataNodesUsingRegexQuickFind(fetchDescendantsOption, dataspaceEntity, anchorEntity, cpsPathQuery);
-         }
          if (anchorEntity == ALL_ANCHORS) {
              fragmentEntities = fragmentRepository.findByDataspaceAndCpsPath(dataspaceEntity, cpsPathQuery);
          } else {
              fragmentEntities = fragmentRepository.findByAnchorAndCpsPath(anchorEntity, cpsPathQuery);
          }
          if (cpsPathQuery.hasAncestorAxis()) {
              final Collection<String> ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery);
              if (anchorEntity == ALL_ANCHORS) {
                  fragmentEntities = fragmentRepository.findByAnchorAndXpathIn(anchorEntity, ancestorXpaths);
              }
          }
-         return createDataNodesFromProxiedFragmentEntities(fetchDescendantsOption, anchorEntity, fragmentEntities);
+         fragmentEntities = prefetchDescendantsForFragmentEntities(fetchDescendantsOption, anchorEntity,
+             fragmentEntities);
+         return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities);
      }
  
      @Override
          return queryDataNodes(dataspaceName, QUERY_ACROSS_ANCHORS, cpsPath, fetchDescendantsOption);
      }
  
-     private static boolean canUseRegexQuickFind(final FetchDescendantsOption fetchDescendantsOption,
-                                                 final CpsPathQuery cpsPathQuery) {
-         return fetchDescendantsOption.equals(FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
-             && !cpsPathQuery.hasAncestorAxis()
-             && !cpsPathQuery.hasLeafConditions()
-             && !cpsPathQuery.hasTextFunctionCondition()
-             && !cpsPathQuery.hasContainsFunctionCondition();
-     }
+     private Collection<FragmentEntity> prefetchDescendantsForFragmentEntities(
+                                             final FetchDescendantsOption fetchDescendantsOption,
+                                             final AnchorEntity anchorEntity,
+                                             final Collection<FragmentEntity> proxiedFragmentEntities) {
+         if (FetchDescendantsOption.OMIT_DESCENDANTS.equals(fetchDescendantsOption)) {
+             return proxiedFragmentEntities;
+         }
  
-     private List<DataNode> getDataNodesUsingRegexQuickFind(final FetchDescendantsOption fetchDescendantsOption,
-                                                            final DataspaceEntity dataspaceEntity,
-                                                            final AnchorEntity anchorEntity,
-                                                            final CpsPathQuery cpsPathQuery) {
-         final String xpathRegex = FragmentQueryBuilder.getXpathSqlRegexForQuickFindWithDescendants(cpsPathQuery);
-         final List<FragmentExtract> fragmentExtracts = (anchorEntity == ALL_ANCHORS)
-             ? fragmentRepository.quickFindWithDescendantsAcrossAnchors(dataspaceEntity.getId(), xpathRegex)
-             : fragmentRepository.quickFindWithDescendants(anchorEntity.getId(), xpathRegex);
-         final Collection<FragmentEntity> fragmentEntities =
-             createFragmentEntitiesFromFragmentExtracts(anchorEntity, fragmentExtracts);
-         return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities);
-     }
+         final List<Long> fragmentEntityIds = proxiedFragmentEntities.stream()
+             .map(FragmentEntity::getId).collect(Collectors.toList());
+         final List<FragmentExtract> fragmentExtracts =
+             fragmentRepository.findExtractsWithDescendantsByIds(fragmentEntityIds, fetchDescendantsOption.getDepth());
  
-     private Collection<FragmentEntity> createFragmentEntitiesFromFragmentExtracts(
-                     final AnchorEntity anchorEntity, final Collection<FragmentExtract> fragmentExtracts) {
          if (anchorEntity == ALL_ANCHORS) {
              final Collection<Integer> anchorIds = fragmentExtracts.stream()
                  .map(FragmentExtract::getAnchorId).collect(Collectors.toSet());
          return FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts);
      }
  
-     private List<DataNode> createDataNodesFromProxiedFragmentEntities(
-                                             final FetchDescendantsOption fetchDescendantsOption,
-                                             final AnchorEntity anchorEntity,
-                                             final Collection<FragmentEntity> proxiedFragmentEntities) {
-         final List<DataNode> dataNodes = new ArrayList<>(proxiedFragmentEntities.size());
-         for (final FragmentEntity proxiedFragmentEntity : proxiedFragmentEntities) {
-             if (FetchDescendantsOption.OMIT_DESCENDANTS.equals(fetchDescendantsOption)) {
-                 dataNodes.add(toDataNode(proxiedFragmentEntity, fetchDescendantsOption));
-             } else {
-                 final String normalizedXpath = getNormalizedXpath(proxiedFragmentEntity.getXpath());
-                 final AnchorEntity anchorEntityForFragmentExtract = (anchorEntity == ALL_ANCHORS)
-                         ? proxiedFragmentEntity.getAnchor() : anchorEntity;
-                 final Collection<FragmentEntity> unproxiedFragmentEntities =
-                     buildFragmentEntitiesFromFragmentExtracts(anchorEntityForFragmentExtract, normalizedXpath);
-                 for (final FragmentEntity unproxiedFragmentEntity : unproxiedFragmentEntities) {
-                     dataNodes.add(toDataNode(unproxiedFragmentEntity, fetchDescendantsOption));
-                 }
-             }
-         }
-         return Collections.unmodifiableList(dataNodes);
-     }
      private List<DataNode> createDataNodesFromFragmentEntities(final FetchDescendantsOption fetchDescendantsOption,
                                                                 final Collection<FragmentEntity> fragmentEntities) {
          final List<DataNode> dataNodes = new ArrayList<>(fragmentEntities.size());
                                                      final CpsPathQuery cpsPathQuery) {
          final Set<String> ancestorXpath = new HashSet<>();
          final Pattern pattern =
 -                Pattern.compile("([\\s\\S]*/" + Pattern.quote(cpsPathQuery.getAncestorSchemaNodeIdentifier())
 -                        + REG_EX_FOR_OPTIONAL_LIST_INDEX + "/[\\s\\S]*");
 +                Pattern.compile("(.*/" + Pattern.quote(cpsPathQuery.getAncestorSchemaNodeIdentifier())
 +                        + REG_EX_FOR_OPTIONAL_LIST_INDEX + "/.*");
          for (final FragmentEntity fragmentEntity : fragmentEntities) {
              final Matcher matcher = pattern.matcher(fragmentEntity.getXpath());
              if (matcher.matches()) {