+ return createDataNodesFromProxiedFragmentEntities(fetchDescendantsOption, anchorEntity, fragmentEntities);
+ }
+
+ private static boolean canUseRegexQuickFind(final FetchDescendantsOption fetchDescendantsOption,
+ final CpsPathQuery cpsPathQuery) {
+ return fetchDescendantsOption.equals(FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
+ && !cpsPathQuery.hasLeafConditions()
+ && !cpsPathQuery.hasTextFunctionCondition();
+ }
+
+ private List<DataNode> getDataNodesUsingRegexQuickFind(final FetchDescendantsOption fetchDescendantsOption,
+ final AnchorEntity anchorEntity,
+ final CpsPathQuery cpsPathQuery) {
+ Collection<FragmentEntity> fragmentEntities;
+ final String xpathRegex = FragmentQueryBuilder.getXpathSqlRegex(cpsPathQuery, true);
+ final List<FragmentExtract> fragmentExtracts =
+ fragmentRepository.quickFindWithDescendants(anchorEntity.getId(), xpathRegex);
+ fragmentEntities = FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts);
+ if (cpsPathQuery.hasAncestorAxis()) {
+ fragmentEntities = getAncestorFragmentEntities(anchorEntity.getId(), cpsPathQuery, fragmentEntities);
+ }
+ return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities);
+ }
+
+ private Collection<FragmentEntity> getAncestorFragmentEntities(final int anchorId,
+ final CpsPathQuery cpsPathQuery,
+ final Collection<FragmentEntity> fragmentEntities) {
+ final Collection<String> ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery);
+ return ancestorXpaths.isEmpty() ? Collections.emptyList()
+ : fragmentRepository.findByAnchorAndMultipleCpsPaths(anchorId, ancestorXpaths);
+ }
+
+ 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 Collection<FragmentEntity> unproxiedFragmentEntities =
+ buildFragmentEntitiesFromFragmentExtracts(anchorEntity, 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());
+ for (final FragmentEntity fragmentEntity : fragmentEntities) {
+ dataNodes.add(toDataNode(fragmentEntity, fetchDescendantsOption));
+ }
+ return Collections.unmodifiableList(dataNodes);
+ }
+
+ private static String getNormalizedXpath(final String xpathSource) {
+ final String normalizedXpath;
+ try {
+ normalizedXpath = CpsPathUtil.getNormalizedXpath(xpathSource);
+ } catch (final PathParsingException e) {
+ throw new CpsPathException(e.getMessage());
+ }
+ return normalizedXpath;