Package com.epam.ta.reportportal.dao
Interface TestItemRepository
-
- All Superinterfaces:
org.springframework.data.repository.CrudRepository<TestItem,java.lang.Long>,FilterableRepository<TestItem>,org.springframework.data.jpa.repository.JpaRepository<TestItem,java.lang.Long>,org.springframework.data.repository.PagingAndSortingRepository<TestItem,java.lang.Long>,org.springframework.data.repository.query.QueryByExampleExecutor<TestItem>,ReportPortalRepository<TestItem,java.lang.Long>,org.springframework.data.repository.Repository<TestItem,java.lang.Long>,TestItemRepositoryCustom
public interface TestItemRepository extends ReportPortalRepository<TestItem,java.lang.Long>, TestItemRepositoryCustom
-
-
Method Summary
All Methods Instance Methods Abstract Methods Deprecated Methods Modifier and Type Method Description voiddeleteAllByItemIdIn(java.util.Collection<java.lang.Long> ids)voiddeleteTestItem(java.lang.Long itemId)java.util.Optional<TestItem>findByPath(java.lang.String path)FindsTestItemwith specifiedpathjava.util.Optional<TestItem>findByUuid(java.lang.String uuid)java.util.Optional<java.lang.Long>findIdByUuidForUpdate(java.lang.String uuid)FindsTestItem.getItemId()byTestItem.getUuid()and sets a lock on the found 'item' row in the database.java.util.List<java.lang.Long>findIdsByHasChildrenAndLaunchIdAndStatusOrderedByPathLevel(java.lang.Long launchId, StatusEnum status, java.lang.Integer limit, java.lang.Long offset)Retrieve theListof theTestItem.getItemId()by launch ID,Enum.name()andTestItem.isHasChildren()== true ordered (DESCENDING) by 'nlevel' of theTestItem.getPath()java.util.List<java.lang.Long>findIdsByHasChildrenAndParentPathAndStatusOrderedByPathLevel(java.lang.String parentPath, StatusEnum status, java.lang.Integer limit, java.lang.Long offset)Retrieve theStreamof theTestItem.getItemId()under parentTestItem.getPath(),Enum.name()andTestItem.isHasChildren()== true ordered (DESCENDING) by 'nlevel' of theTestItem.getPath()java.util.List<java.lang.Long>findIdsByNotHasChildrenAndLaunchIdAndStatus(java.lang.Long launchId, StatusEnum status, java.lang.Integer limit, java.lang.Long offset)Retrieve theListof theTestItem.getItemId()by launch ID,Enum.name()andTestItem.isHasChildren()== falsejava.util.List<java.lang.Long>findIdsByNotHasChildrenAndParentPathAndStatus(java.lang.String parentPath, StatusEnum status, java.lang.Integer limit, java.lang.Long offset)Retrieve theStreamof theTestItem.getItemId()under parentTestItem.getPath(),Enum.name()andTestItem.isHasChildren()== falsejava.util.Optional<java.lang.Long>findLatestIdByTestCaseHashAndLaunchIdAndParentId(java.lang.Integer testCaseHash, java.lang.Long launchId, java.lang.Long parentId)java.util.Optional<java.lang.Long>findLatestIdByTestCaseHashAndLaunchIdWithoutParents(java.lang.Integer testCaseHash, java.lang.Long launchId)java.util.Optional<java.lang.Long>findLatestIdByUniqueIdAndLaunchIdAndParentId(java.lang.String uniqueId, java.lang.Long launchId, java.lang.Long parentId)java.util.Optional<java.lang.Long>findLatestIdByUniqueIdAndLaunchIdAndParentIdAndItemIdNotEqual(java.lang.String uniqueId, java.lang.Long launchId, java.lang.Long parentId, java.lang.Long itemId)java.util.Optional<TestItem>findParentByChildId(java.lang.Long childId)java.util.List<TestItem>findTestItemsByLaunchId(java.lang.Long launchId)java.util.List<TestItem>findTestItemsByLaunchIdOrderByStartTimeAsc(java.lang.Long launchId)Finds allTestItemby specified launch idjava.util.List<TestItem>findTestItemsByUniqueId(java.lang.String uniqueId)voidhandleRetries(java.lang.Long itemId)Deprecated.handleRetry(Long, Long)should be used insteadvoidhandleRetry(java.lang.Long itemId, java.lang.Long retryParent)Execute sql-function that changes a structure of retries assigningTestItem.getRetryOf()value of the previously inserted retries and previous retries' parent to the new inserted parent idbooleanhasChildren(java.lang.Long itemId, java.lang.String itemPath)Checks does test item have children.booleanhasChildrenWithStats(java.lang.Long itemId)Checks does test item have children withTestItem.isHasStats()== true.booleanhasDescendantsNotInStatus(java.lang.Long parentId, java.lang.String... statuses)Check for existence of descendants with statuses NOT EQUAL to provided statusbooleanhasDescendantsNotInStatusExcludingById(java.lang.Long parentId, java.lang.Long stepId, java.lang.String... statuses)Checks if all children of test item with id =parentId, except item with id =stepId, has status not in providedstatusesbooleanhasItemsInStatusByParent(java.lang.Long parentId, java.lang.String parentPath, java.lang.String... statuses)True if the parent item has any child items with provided status.booleanhasItemsWithIssueByLaunch(java.lang.Long launchId)True if the launch has any items with issue.booleanhasParentWithStatus(java.lang.Long itemId, java.lang.String itemPath, StatusEnum status)Checks does test item have parent with provided status.voidinterruptInProgressItems(java.lang.Long launchId)Interrupts allStatusEnum.IN_PROGRESSchildren items of the launch with provided launchId.java.util.List<java.lang.Long>selectAllDescendantsIds(java.lang.String path)Finds all descendants ids ofTestItemwithpathinclude its own id-
Methods inherited from interface org.springframework.data.repository.CrudRepository
count, delete, deleteAll, deleteAll, deleteById, existsById, findById, save
-
Methods inherited from interface com.epam.ta.reportportal.dao.FilterableRepository
findByFilter, findByFilter
-
Methods inherited from interface org.springframework.data.jpa.repository.JpaRepository
deleteAllInBatch, deleteInBatch, findAll, findAll, findAll, findAll, findAllById, flush, getOne, saveAll, saveAndFlush
-
Methods inherited from interface org.springframework.data.repository.PagingAndSortingRepository
findAll
-
Methods inherited from interface org.springframework.data.repository.query.QueryByExampleExecutor
count, exists, findAll, findOne
-
Methods inherited from interface com.epam.ta.reportportal.dao.ReportPortalRepository
exists, refresh
-
Methods inherited from interface com.epam.ta.reportportal.dao.TestItemRepositoryCustom
accumulateStatisticsByFilter, accumulateStatisticsByFilterNotFromBaseline, findAllInIssueGroupByLaunch, findAllNestedStepsByIds, findAllNotFromBaseline, findAllNotInIssueByLaunch, findAllNotInIssueGroupByLaunch, findByFilter, findIdByFilter, findIndexTestItemByLaunchId, findTestItemIdsByLaunchId, getTypeByItemId, hasItemsInStatusAddedLately, hasItemsInStatusByLaunch, hasLogs, loadItemsHistoryPage, loadItemsHistoryPage, loadItemsHistoryPage, loadItemsHistoryPage, loadItemsHistoryPage, selectAllDescendants, selectAllDescendantsWithChildren, selectIdsByAnalyzedWithLevelGte, selectIdsByFilter, selectIdsByHasDescendants, selectIdsByRegexLogMessage, selectIdsByStringLogMessage, selectIdsNotInIssueByLaunch, selectIdsNotInIssueGroupByLaunch, selectIdsUnderByRegexLogMessage, selectIdsUnderByStringLogMessage, selectIdsWithIssueByLaunch, selectIssueLocatorsByProject, selectIssueTypeByLocator, selectItemsInIssueByLaunch, selectItemsInStatusByLaunch, selectItemsInStatusByParent, selectPath, selectPathNames, selectRetries, updateStatusAndEndTimeById, updateStatusAndEndTimeByRetryOfId
-
-
-
-
Method Detail
-
findParentByChildId
@Query(value="SELECT * FROM test_item WHERE item_id = (SELECT parent_id FROM test_item WHERE item_id = :childId)", nativeQuery=true) java.util.Optional<TestItem> findParentByChildId(@Param("childId") java.lang.Long childId)
-
findIdsByNotHasChildrenAndLaunchIdAndStatus
@Query(value="SELECT test_item.item_id FROM test_item JOIN test_item_results result ON test_item.item_id = result.result_id WHERE test_item.launch_id = :launchId AND NOT test_item.has_children AND result.status = CAST(:#{#status.name()} AS STATUS_ENUM) ORDER BY test_item.item_id LIMIT :pageSize OFFSET :pageOffset", nativeQuery=true) java.util.List<java.lang.Long> findIdsByNotHasChildrenAndLaunchIdAndStatus(@Param("launchId") java.lang.Long launchId, @Param("status") StatusEnum status, @Param("pageSize") java.lang.Integer limit, @Param("pageOffset") java.lang.Long offset)Retrieve theListof theTestItem.getItemId()by launch ID,Enum.name()andTestItem.isHasChildren()== false- Parameters:
launchId-Launch.getId()status-Enum.name()- Returns:
- the
Listof theTestItem.getItemId()
-
findIdsByHasChildrenAndLaunchIdAndStatusOrderedByPathLevel
@Query(value="SELECT test_item.item_id FROM test_item JOIN test_item_results result ON test_item.item_id = result.result_id WHERE test_item.launch_id = :launchId AND test_item.has_children AND result.status = CAST(:#{#status.name()} AS STATUS_ENUM) ORDER BY nlevel(test_item.path) DESC, test_item.item_id LIMIT :pageSize OFFSET :pageOffset", nativeQuery=true) java.util.List<java.lang.Long> findIdsByHasChildrenAndLaunchIdAndStatusOrderedByPathLevel(@Param("launchId") java.lang.Long launchId, @Param("status") StatusEnum status, @Param("pageSize") java.lang.Integer limit, @Param("pageOffset") java.lang.Long offset)Retrieve theListof theTestItem.getItemId()by launch ID,Enum.name()andTestItem.isHasChildren()== true ordered (DESCENDING) by 'nlevel' of theTestItem.getPath()- Parameters:
launchId-Launch.getId()status-Enum.name()- Returns:
- the
Listof theTestItem.getItemId() - See Also:
- https://www.postgresql.org/docs/current/ltree.html
-
findIdsByNotHasChildrenAndParentPathAndStatus
@Query(value="SELECT test_item.item_id FROM test_item JOIN test_item_results result ON test_item.item_id = result.result_id WHERE CAST(:parentPath AS LTREE) @> test_item.path AND CAST(:parentPath AS LTREE) != test_item.path AND NOT test_item.has_children AND result.status = CAST(:#{#status.name()} AS STATUS_ENUM) ORDER BY test_item.item_id LIMIT :pageSize OFFSET :pageOffset", nativeQuery=true) java.util.List<java.lang.Long> findIdsByNotHasChildrenAndParentPathAndStatus(@Param("parentPath") java.lang.String parentPath, @Param("status") StatusEnum status, @Param("pageSize") java.lang.Integer limit, @Param("pageOffset") java.lang.Long offset)Retrieve theStreamof theTestItem.getItemId()under parentTestItem.getPath(),Enum.name()andTestItem.isHasChildren()== false- Parameters:
parentPath-TestItem.getPath()of the parent itemstatus-Enum.name()- Returns:
- the
Listof theTestItem.getItemId()
-
findIdsByHasChildrenAndParentPathAndStatusOrderedByPathLevel
@Query(value="SELECT test_item.item_id FROM test_item JOIN test_item_results result ON test_item.item_id = result.result_id WHERE CAST(:parentPath AS LTREE) @> test_item.path AND CAST(:parentPath AS LTREE) != test_item.path AND test_item.has_children AND result.status = CAST(:#{#status.name()} AS STATUS_ENUM) ORDER BY nlevel(test_item.path) DESC, test_item.item_id LIMIT :pageSize OFFSET :pageOffset", nativeQuery=true) java.util.List<java.lang.Long> findIdsByHasChildrenAndParentPathAndStatusOrderedByPathLevel(@Param("parentPath") java.lang.String parentPath, @Param("status") StatusEnum status, @Param("pageSize") java.lang.Integer limit, @Param("pageOffset") java.lang.Long offset)Retrieve theStreamof theTestItem.getItemId()under parentTestItem.getPath(),Enum.name()andTestItem.isHasChildren()== true ordered (DESCENDING) by 'nlevel' of theTestItem.getPath()- Parameters:
parentPath-TestItem.getPath()of the parent itemstatus-Enum.name()- Returns:
- the
Listof theTestItem.getItemId() - See Also:
- https://www.postgresql.org/docs/current/ltree.html
-
findTestItemsByUniqueId
java.util.List<TestItem> findTestItemsByUniqueId(java.lang.String uniqueId)
-
findTestItemsByLaunchId
java.util.List<TestItem> findTestItemsByLaunchId(java.lang.Long launchId)
-
findByUuid
java.util.Optional<TestItem> findByUuid(java.lang.String uuid)
-
findIdByUuidForUpdate
@Query(value="SELECT ti.item_id FROM test_item ti WHERE ti.uuid = :uuid FOR UPDATE", nativeQuery=true) java.util.Optional<java.lang.Long> findIdByUuidForUpdate(@Param("uuid") java.lang.String uuid)FindsTestItem.getItemId()byTestItem.getUuid()and sets a lock on the found 'item' row in the database. Required for fetching 'item' from the concurrent environment to provide synchronization between dependant entities- Parameters:
uuid-TestItem.getUuid()- Returns:
OptionalwithTestItemobject
-
findTestItemsByLaunchIdOrderByStartTimeAsc
java.util.List<TestItem> findTestItemsByLaunchIdOrderByStartTimeAsc(java.lang.Long launchId)
Finds allTestItemby specified launch id- Parameters:
launchId-Launch.getId()- Returns:
ListofTestItemordered byTestItem.getStartTime()ascending
-
handleRetries
@Deprecated @Query(value="SELECT handle_retries(:itemId)", nativeQuery=true) void handleRetries(@Param("itemId") java.lang.Long itemId)Deprecated.handleRetry(Long, Long)should be used insteadExecute sql-function that changes a structure of retries according to the MAXTestItem.getStartTime(). If the new-insertedTestItemwith specifiedTestItem.getItemId()is a retry and it hasTestItem.getStartTime()greater than MAXTestItem.getStartTime()of the otherTestItemwith the sameTestItem.getUniqueId()then all those test items become retries of the new-inserted one: theirsTestItem.isHasRetries()flag is set to 'false' andTestItem.getRetryOf()gets the new-insertedTestItem.getItemId()value. The same operation applies to the new-insertedTestItemif itsTestItem.getStartTime()is less than MAXTestItem.getStartTime()of the otherTestItemwith the sameTestItem.getUniqueId()- Parameters:
itemId- The new-insertedTestItem.getItemId()
-
handleRetry
@Query(value="SELECT handle_retry(:itemId, :retryParent)", nativeQuery=true) void handleRetry(@Param("itemId") java.lang.Long itemId, @Param("retryParent") java.lang.Long retryParent)Execute sql-function that changes a structure of retries assigningTestItem.getRetryOf()value of the previously inserted retries and previous retries' parent to the new inserted parent id- Parameters:
itemId- Previous retries' parentTestItem.getItemId()retryParent- The new-insertedTestItem.getItemId()
-
deleteTestItem
@Query(value="DELETE FROM test_item WHERE test_item.item_id = :itemId", nativeQuery=true) void deleteTestItem(@Param("itemId") java.lang.Long itemId)
-
hasChildren
@Query(value="SELECT EXISTS(SELECT 1 FROM test_item t WHERE t.path <@ CAST(:itemPath AS LTREE) AND t.item_id != :itemId LIMIT 1)", nativeQuery=true) boolean hasChildren(@Param("itemId") java.lang.Long itemId, @Param("itemPath") java.lang.String itemPath)Checks does test item have children.- Parameters:
itemPath- Current item path in a tree- Returns:
- True if has
-
hasChildrenWithStats
@Query(value="SELECT exists(SELECT 1 FROM test_item t WHERE t.parent_id = :itemId AND t.has_stats)", nativeQuery=true) boolean hasChildrenWithStats(@Param("itemId") java.lang.Long itemId)Checks does test item have children withTestItem.isHasStats()== true.- Parameters:
itemId- Parent item id- Returns:
- True if has
-
hasParentWithStatus
@Query(value="SELECT EXISTS(SELECT 1 FROM test_item ti JOIN test_item_results tir ON ti.item_id = tir.result_id WHERE ti.path @> CAST(:itemPath AS LTREE) AND ti.has_stats = TRUE AND ti.item_id != :itemId AND tir.status = CAST(:#{#status.name()} AS STATUS_ENUM) LIMIT 1)", nativeQuery=true) boolean hasParentWithStatus(@Param("itemId") java.lang.Long itemId, @Param("itemPath") java.lang.String itemPath, @Param("status") StatusEnum status)Checks does test item have parent with provided status.- Parameters:
itemId- Cuttent item iditemPath- Current item path in a treestatus-StatusEnum- Returns:
- 'True' if has, otherwise 'false'
-
hasDescendantsNotInStatus
@Query(value="SELECT EXISTS(SELECT 1 FROM test_item ti JOIN test_item_results tir ON ti.item_id = tir.result_id WHERE ti.parent_id = :parentId AND ti.retry_of IS NULL AND CAST(tir.status AS VARCHAR) NOT IN (:statuses))", nativeQuery=true) boolean hasDescendantsNotInStatus(@Param("parentId") java.lang.Long parentId, @Param("statuses") java.lang.String... statuses)Check for existence of descendants with statuses NOT EQUAL to provided status- Parameters:
parentId-TestItem#getParent()IDstatuses-Enum.name()Array- Returns:
- 'true' if items with statuses NOT EQUAL to provided status exist, otherwise 'false'
-
hasItemsInStatusByParent
@Query(value="SELECT EXISTS(SELECT 1 FROM test_item ti JOIN test_item_results tir ON ti.item_id = tir.result_id WHERE ti.path <@ CAST(:parentPath AS LTREE) AND ti.item_id != :parentId AND CAST(tir.status AS VARCHAR) IN (:statuses))", nativeQuery=true) boolean hasItemsInStatusByParent(@Param("parentId") java.lang.Long parentId, @Param("parentPath") java.lang.String parentPath, @Param("statuses") java.lang.String... statuses)True if the parent item has any child items with provided status.- Parameters:
parentId- parent itemTestItem.getItemId()parentPath- parent itemTestItem.getPath()statuses- child itemTestItemResults.getStatus()- Returns:
- True if contains, false if not
-
hasItemsWithIssueByLaunch
@Query(value="SELECT EXISTS(SELECT 1 FROM test_item ti JOIN issue i ON ti.item_id = i.issue_id WHERE ti.launch_id = :launchId)", nativeQuery=true) boolean hasItemsWithIssueByLaunch(@Param("launchId") java.lang.Long launchId)True if the launch has any items with issue.- Parameters:
launchId- parent itemTestItem.getItemId()- Returns:
- True if contains, false if not
-
interruptInProgressItems
@Modifying @Query(value="UPDATE test_item_results SET status = \'INTERRUPTED\', end_time = CURRENT_TIMESTAMP, duration = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - i.start_time)FROM test_item i WHERE i.item_id = result_id AND i.launch_id = :launchId AND status = \'IN_PROGRESS\'", nativeQuery=true) void interruptInProgressItems(@Param("launchId") java.lang.Long launchId)Interrupts allStatusEnum.IN_PROGRESSchildren items of the launch with provided launchId. Sets themStatusEnum.INTERRUPTEDstatus- Parameters:
launchId- Launch id
-
hasDescendantsNotInStatusExcludingById
@Query(value="SELECT EXISTS(SELECT 1 FROM test_item JOIN test_item_results result ON test_item.item_id = result.result_id WHERE test_item.parent_id = :parentId AND test_item.item_id != :stepId AND test_item.retry_of IS NULL AND CAST(result.status AS VARCHAR) NOT IN (:statuses))", nativeQuery=true) boolean hasDescendantsNotInStatusExcludingById(@Param("parentId") java.lang.Long parentId, @Param("stepId") java.lang.Long stepId, @Param("statuses") java.lang.String... statuses)Checks if all children of test item with id =parentId, except item with id =stepId, has status not in providedstatuses- Parameters:
parentId- Id of parent test itemstepId- Id of test item that should be ignored during the checkingstatuses-Enum.name()Array- Returns:
- True if has
-
findByPath
@Query(value="SELECT * FROM test_item t WHERE t.path = CAST(:path AS LTREE)", nativeQuery=true) java.util.Optional<TestItem> findByPath(@Param("path") java.lang.String path)FindsTestItemwith specifiedpath
-
findLatestIdByUniqueIdAndLaunchIdAndParentId
@Query(value="SELECT t.item_id FROM test_item t WHERE t.unique_id = :uniqueId AND t.launch_id = :launchId AND t.parent_id = :parentId AND t.has_stats AND t.retry_of IS NULL ORDER BY t.start_time DESC, t.item_id DESC LIMIT 1 FOR UPDATE", nativeQuery=true) java.util.Optional<java.lang.Long> findLatestIdByUniqueIdAndLaunchIdAndParentId(@Param("uniqueId") java.lang.String uniqueId, @Param("launchId") java.lang.Long launchId, @Param("parentId") java.lang.Long parentId)- Parameters:
uniqueId-TestItem.getUniqueId()launchId-TestItem.getLaunchId()parentId-TestItem.getParentId()- Returns:
OptionalofTestItemif exists otherwiseOptional.empty()
-
findLatestIdByUniqueIdAndLaunchIdAndParentIdAndItemIdNotEqual
@Query(value="SELECT t.item_id FROM test_item t WHERE t.unique_id = :uniqueId AND t.launch_id = :launchId AND t.parent_id = :parentId AND t.item_id != :itemId AND t.has_stats AND t.retry_of IS NULL ORDER BY t.start_time DESC, t.item_id DESC LIMIT 1 FOR UPDATE", nativeQuery=true) java.util.Optional<java.lang.Long> findLatestIdByUniqueIdAndLaunchIdAndParentIdAndItemIdNotEqual(@Param("uniqueId") java.lang.String uniqueId, @Param("launchId") java.lang.Long launchId, @Param("parentId") java.lang.Long parentId, @Param("itemId") java.lang.Long itemId)- Parameters:
uniqueId-TestItem.getUniqueId()launchId-TestItem.getLaunchId()parentId-TestItem.getParentId()itemId-TestItem.getItemId()()}- Returns:
OptionalofTestItemif exists otherwiseOptional.empty()
-
selectAllDescendantsIds
@Query(value="SELECT item_id FROM test_item WHERE path <@ CAST(:path AS LTREE)", nativeQuery=true) java.util.List<java.lang.Long> selectAllDescendantsIds(@Param("path") java.lang.String path)Finds all descendants ids ofTestItemwithpathinclude its own id- Parameters:
path- Path ofTestItem- Returns:
Listof test item ids
-
deleteAllByItemIdIn
void deleteAllByItemIdIn(java.util.Collection<java.lang.Long> ids)
-
findLatestIdByTestCaseHashAndLaunchIdWithoutParents
@Query(value="SELECT t.item_id FROM test_item t WHERE t.test_case_hash = :testCaseHash AND t.launch_id = :launchId AND t.parent_id IS NULL ORDER BY t.start_time DESC, t.item_id DESC LIMIT 1 FOR UPDATE", nativeQuery=true) java.util.Optional<java.lang.Long> findLatestIdByTestCaseHashAndLaunchIdWithoutParents(@Param("testCaseHash") java.lang.Integer testCaseHash, @Param("launchId") java.lang.Long launchId)- Parameters:
testCaseHash-TestItem.getTestCaseHash()launchId-TestItem.getLaunchId()- Returns:
OptionalofTestItem.getItemId()if exists otherwiseOptional.empty()
-
findLatestIdByTestCaseHashAndLaunchIdAndParentId
@Query(value="SELECT t.item_id FROM test_item t WHERE t.test_case_hash = :testCaseHash AND t.launch_id = :launchId AND t.parent_id = :parentId AND t.has_stats AND t.retry_of IS NULL ORDER BY t.start_time DESC, t.item_id DESC LIMIT 1 FOR UPDATE", nativeQuery=true) java.util.Optional<java.lang.Long> findLatestIdByTestCaseHashAndLaunchIdAndParentId(@Param("testCaseHash") java.lang.Integer testCaseHash, @Param("launchId") java.lang.Long launchId, @Param("parentId") java.lang.Long parentId)- Parameters:
testCaseHash-TestItem.getTestCaseHash()launchId-TestItem.getLaunchId()parentId-TestItem.getParentId()- Returns:
OptionalofTestItem.getItemId()if exists otherwiseOptional.empty()
-
-