+ @Query(value = "DELETE FROM fragment WHERE anchor_id = ANY (:anchorIds)", nativeQuery = true)\r
+ void deleteByAnchorIdIn(@Param("anchorIds") long[] anchorIds);\r
+\r
+ default void deleteByAnchorIn(final Collection<AnchorEntity> anchorEntities) {\r
+ deleteByAnchorIdIn(anchorEntities.stream().map(AnchorEntity::getId).mapToLong(id -> id).toArray());\r
+ }\r
+\r
+ @Modifying\r
+ @Query(value = "DELETE FROM fragment WHERE anchor_id = :anchorId AND xpath = ANY (:xpaths)", nativeQuery = true)\r
+ void deleteByAnchorIdAndXpaths(@Param("anchorId") long anchorId, @Param("xpaths") String[] xpaths);\r
+\r
+ default void deleteByAnchorIdAndXpaths(final long anchorId, final Collection<String> xpaths) {\r
+ deleteByAnchorIdAndXpaths(anchorId, xpaths.toArray(new String[0]));\r
+ }\r
+\r
+ @Modifying\r
+ @Query(value = "DELETE FROM fragment f WHERE anchor_id = :anchorId AND xpath LIKE ANY (:xpathPatterns)",\r
+ nativeQuery = true)\r
+ void deleteByAnchorIdAndXpathLikeAny(@Param("anchorId") long anchorId,\r
+ @Param("xpathPatterns") String[] xpathPatterns);\r
+\r
+ default void deleteListsByAnchorIdAndXpaths(long anchorId, Collection<String> xpaths) {\r
+ final String[] listXpathPatterns = xpaths.stream().map(xpath -> xpath + "[%").toArray(String[]::new);\r
+ deleteByAnchorIdAndXpathLikeAny(anchorId, listXpathPatterns);\r
+ }\r
+\r
+ @Query(value = "SELECT xpath FROM fragment WHERE anchor_id = :anchorId AND xpath = ANY (:xpaths)",\r
+ nativeQuery = true)\r
+ List<String> findAllXpathByAnchorIdAndXpathIn(@Param("anchorId") long anchorId,\r
+ @Param("xpaths") String[] xpaths);\r
+\r
+ default List<String> findAllXpathByAnchorAndXpathIn(final AnchorEntity anchorEntity,\r
+ final Collection<String> xpaths) {\r
+ return findAllXpathByAnchorIdAndXpathIn(anchorEntity.getId(), xpaths.toArray(new String[0]));\r
+ }\r
+\r
+ boolean existsByAnchorAndXpathStartsWith(AnchorEntity anchorEntity, String xpath);\r
+\r
+ @Query("SELECT xpath FROM FragmentEntity WHERE anchor = :anchor AND parentId IS NULL")\r
+ List<String> findAllXpathByAnchorAndParentIdIsNull(@Param("anchor") AnchorEntity anchorEntity);\r
+\r
+ @Query(value\r
+ = "WITH RECURSIVE parent_search AS ("\r
+ + " SELECT id, 0 AS depth "\r
+ + " FROM fragment "\r
+ + " WHERE anchor_id = :anchorId AND xpath = ANY (:xpaths) "\r
+ + " UNION "\r
+ + " SELECT c.id, depth + 1 "\r
+ + " FROM fragment c INNER JOIN parent_search p ON c.parent_id = p.id"\r
+ + " WHERE depth < (SELECT CASE WHEN :maxDepth = -1 THEN " + Integer.MAX_VALUE + " ELSE :maxDepth END) "\r
+ + ") "\r
+ + "SELECT f.id, anchor_id AS anchorId, xpath, f.parent_id AS parentId, CAST(attributes AS TEXT) AS attributes "\r
+ + "FROM fragment f INNER JOIN parent_search p ON f.id = p.id",\r
+ nativeQuery = true\r
+ )\r
+ List<FragmentExtract> findExtractsWithDescendants(@Param("anchorId") long anchorId,\r
+ @Param("xpaths") String[] xpaths,\r
+ @Param("maxDepth") int maxDepth);\r
+\r
+ default List<FragmentExtract> findExtractsWithDescendants(final long anchorId, final Collection<String> xpaths,\r
+ final int maxDepth) {\r
+ return findExtractsWithDescendants(anchorId, xpaths.toArray(new String[0]), maxDepth);\r
+ }\r
+\r
+ @Query(value\r
+ = "WITH RECURSIVE parent_search AS ("\r
+ + " SELECT id, 0 AS depth "\r
+ + " FROM fragment "\r
+ + " WHERE id = ANY (:ids) "\r
+ + " UNION "\r
+ + " SELECT c.id, depth + 1 "\r
+ + " FROM fragment c INNER JOIN parent_search p ON c.parent_id = p.id"\r
+ + " WHERE depth < (SELECT CASE WHEN :maxDepth = -1 THEN " + Integer.MAX_VALUE + " ELSE :maxDepth END) "\r
+ + ") "\r
+ + "SELECT f.id, anchor_id AS anchorId, xpath, f.parent_id AS parentId, CAST(attributes AS TEXT) AS attributes "\r
+ + "FROM fragment f INNER JOIN parent_search p ON f.id = p.id",\r
+ nativeQuery = true\r
+ )\r
+ List<FragmentExtract> findExtractsWithDescendantsByIds(@Param("ids") long[] ids,\r
+ @Param("maxDepth") int maxDepth);\r
+\r
+ default List<FragmentExtract> findExtractsWithDescendantsByIds(final Collection<Long> ids, final int maxDepth) {\r
+ return findExtractsWithDescendantsByIds(ids.stream().mapToLong(id -> id).toArray(), maxDepth);\r
+ }\r