diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java index 2f7adbcb4..a66f96831 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java @@ -160,6 +160,19 @@ public interface ArtifactManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) Page findBySoftwareModule(@NotNull Pageable pageReq, long swId); + /** + * Count local artifacts for a base software module. + * + * @param swId + * software module id + * @return count by software module + * + * @throws EntityNotFoundException + * if software module with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + long countBySoftwareModule(long swId); + /** * Loads {@link DbArtifact} from store for given {@link Artifact}. * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java index f84cb5dbe..9555ce4f2 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java @@ -331,7 +331,7 @@ public interface DeploymentManagement { /** * Retrieves all the {@link ActionStatus} entries of the given - * {@link Action} and {@link Target}. + * {@link Action}. * * @param pageReq * pagination parameter @@ -345,6 +345,19 @@ public interface DeploymentManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) Page findActionStatusByAction(@NotNull Pageable pageReq, long actionId); + /** + * Counts all the {@link ActionStatus} entries of the given {@link Action}. + * + * @param actionId + * to be filtered on + * @return count of {@link ActionStatus} entries + * + * @throws EntityNotFoundException + * if action with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) + long countActionStatusByAction(long actionId); + /** * Retrieves all messages for an {@link ActionStatus}. * @@ -358,6 +371,19 @@ public interface DeploymentManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) Page findMessagesByActionStatusId(@NotNull Pageable pageable, long actionStatusId); + /** + * Counts all messages for an {@link ActionStatus}. + * + * + * @param pageable + * the page request parameter for paging and sorting the result + * @param actionStatusId + * the id of {@link ActionStatus} to count the messages from + * @return count of messages by a specific {@link ActionStatus} id + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) + long countMessagesByActionStatusId(long actionStatusId); + /** * Get the {@link Action} entity for given actionId with all lazy attributes * (i.e. distributionSet, target, target.assignedDs). diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java index 4d908d0c7..85f94395a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java @@ -29,7 +29,6 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldExc import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetFilter; -import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; @@ -39,6 +38,7 @@ import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Target; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.security.access.prepost.PreAuthorize; /** @@ -244,6 +244,22 @@ public interface DistributionSetManagement @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) Page findMetaDataByDistributionSetId(@NotNull Pageable pageable, long setId); + /** + * Counts all meta data by the given distribution set id. + * + * @param pageable + * the page request to page the result + * @param setId + * the distribution set id to retrieve the meta data count from + * + * @return count of ds metadata + * + * @throws EntityNotFoundException + * if distribution set with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + long countMetaDataByDistributionSetId(long setId); + /** * Finds all meta data by the given distribution set id. * @@ -272,7 +288,7 @@ public interface DistributionSetManagement @NotNull String rsqlParam); /** - * Finds all {@link DistributionSet}s. + * Finds all {@link DistributionSet}s based on completeness. * * @param pageable * the pagination parameter @@ -284,7 +300,33 @@ public interface DistributionSetManagement * @return all found {@link DistributionSet}s */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findByCompleted(@NotNull Pageable pageable, Boolean complete); + Slice findByCompleted(@NotNull Pageable pageable, Boolean complete); + + /** + * Counts all {@link DistributionSet}s based on completeness. + * + * @param complete + * to true for counting only completed distribution + * sets or false for only incomplete ones nor + * null to count both. + * + * @return count of all found {@link DistributionSet}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + long countByCompleted(Boolean complete); + + /** + * Retrieves {@link DistributionSet}s by filtering on the given parameters. + * + * @param pageable + * page parameter + * @param distributionSetFilter + * has details of filters to be applied. + * @return the page of found {@link DistributionSet} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Slice findByDistributionSetFilter(@NotNull Pageable pageable, + @NotNull DistributionSetFilter distributionSetFilter); /** * Method retrieves all {@link DistributionSet}s from the repository in the @@ -301,29 +343,27 @@ public interface DistributionSetManagement * * @param pageable * the page request to page the result set * - * @param distributionSetFilterBuilder - * has details of filters to be applied + * @param distributionSetFilter + * has details of filters to be applied. * @param assignedOrInstalled * the id of the Target to be ordered by * * @return {@link DistributionSet}s */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findByFilterAndAssignedInstalledDsOrderedByLinkTarget(@NotNull Pageable pageable, - @NotNull DistributionSetFilterBuilder distributionSetFilterBuilder, @NotEmpty String assignedOrInstalled); + Slice findByDistributionSetFilterOrderByLinkedTarget(@NotNull Pageable pageable, + @NotNull DistributionSetFilter distributionSetFilter, @NotEmpty String assignedOrInstalled); /** - * Retrieves {@link DistributionSet}s by filtering on the given parameters. + * Counts all {@link DistributionSet}s in repository based on given filter. * - * @param pageable - * page parameter * @param distributionSetFilter * has details of filters to be applied. - * @return the page of found {@link DistributionSet} + * + * @return count of {@link DistributionSet}s */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findByDistributionSetFilter(@NotNull Pageable pageable, - @NotNull DistributionSetFilter distributionSetFilter); + long countByDistributionSetFilter(@NotNull DistributionSetFilter distributionSetFilter); /** * Retrieves {@link DistributionSet}s by filtering on the given parameters. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java index 538b0b429..666cf3638 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java @@ -181,8 +181,8 @@ public interface RolloutManagement { RolloutGroupConditions conditions); /** - * Calculates how many targets are addressed by each rollout group and returns - * the validation information. + * Calculates how many targets are addressed by each rollout group and + * returns the validation information. * * @param groups * a list of rollout groups @@ -226,7 +226,7 @@ public interface RolloutManagement { * statuses */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ) - Page findAllWithDetailedStatus(@NotNull Pageable pageable, boolean deleted); + Slice findAllWithDetailedStatus(@NotNull Pageable pageable, boolean deleted); /** * Retrieves all rollouts found by the given specification. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java index 5e83a0424..0fcb44804 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java @@ -220,6 +220,20 @@ public interface SoftwareModuleManagement @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) Page findMetaDataBySoftwareModuleId(@NotNull Pageable pageable, long moduleId); + /** + * Counts all meta data by the given software module id. + * + * @param moduleId + * the software module id to retrieve the meta data count from + * + * @return count of all meta data entries for a given software module id + * + * @throws EntityNotFoundException + * if software module with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + long countMetaDataBySoftwareModuleId(long moduleId); + /** * Finds all meta data by the given software module id where * {@link SoftwareModuleMetadata#isTargetVisible()}. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java index 615de1268..ecaf4705c 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java @@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.security.access.prepost.PreAuthorize; /** @@ -96,7 +97,7 @@ public interface TargetFilterQueryManagement { * @return the found {@link TargetFilterQuery}s */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findAll(@NotNull Pageable pageable); + Slice findAll(@NotNull Pageable pageable); /** * Counts all {@link TargetFilterQuery}s. @@ -128,7 +129,17 @@ public interface TargetFilterQueryManagement { * @return the page with the found {@link TargetFilterQuery}s */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findByName(@NotNull Pageable pageable, @NotNull String name); + Slice findByName(@NotNull Pageable pageable, @NotNull String name); + + /** + * Counts all {@link TargetFilterQuery}s which match the given name filter. + * + * @param name + * name filter + * @return count of found {@link TargetFilterQuery}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) + long countByName(@NotNull String name); /** * Retrieves all {@link TargetFilterQuery} which match the given RSQL @@ -153,7 +164,23 @@ public interface TargetFilterQueryManagement { * @return the page with the found {@link TargetFilterQuery}s */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findByQuery(@NotNull Pageable pageable, @NotNull String query); + Slice findByQuery(@NotNull Pageable pageable, @NotNull String query); + + /** + * Retrieves all {@link TargetFilterQuery}s which match the given + * auto-assign distribution set ID. + * + * @param pageable + * pagination parameter + * @param setId + * the auto assign distribution set + * @return the page with the found {@link TargetFilterQuery}s + * + * @throws EntityNotFoundException + * if DS with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) + Slice findByAutoAssignDistributionSetId(@NotNull Pageable pageable, long setId); /** * Retrieves all {@link TargetFilterQuery}s which match the given @@ -181,7 +208,7 @@ public interface TargetFilterQueryManagement { * @param pageable */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findWithAutoAssignDS(@NotNull Pageable pageable); + Slice findWithAutoAssignDS(@NotNull Pageable pageable); /** * Finds the {@link TargetFilterQuery} by id. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java index d7bf8348e..814917fe0 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java @@ -8,6 +8,16 @@ */ package org.eclipse.hawkbit.repository; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.validation.ConstraintViolationException; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.repository.builder.TargetCreate; import org.eclipse.hawkbit.repository.builder.TargetUpdate; @@ -34,15 +44,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.security.access.prepost.PreAuthorize; -import javax.validation.ConstraintViolationException; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Optional; - /** * Management service for {@link Target}s. * @@ -109,7 +110,9 @@ public interface TargetManagement { * @throws EntityNotFoundException * if distribution set with given ID does not exist * - * @deprecated this method {@link TargetManagement#countByFilters(FilterParams)} should be used instead. + * @deprecated this method + * {@link TargetManagement#countByFilters(FilterParams)} should + * be used instead. */ @Deprecated @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @@ -146,7 +149,8 @@ public interface TargetManagement { long countByInstalledDistributionSet(long distId); /** - * Checks if there is already a {@link Target} that has the given distribution set Id assigned or installed. + * Checks if there is already a {@link Target} that has the given + * distribution set Id assigned or installed. * * @param distId * to search for @@ -170,8 +174,8 @@ public interface TargetManagement { long countByRsql(@NotEmpty String rsqlParam); /** - * Count all targets for given {@link TargetFilterQuery} and that are compatible - * with the passed {@link DistributionSetType}. + * Count all targets for given {@link TargetFilterQuery} and that are + * compatible with the passed {@link DistributionSetType}. * * @param rsqlParam * filter definition in RSQL syntax @@ -190,7 +194,7 @@ public interface TargetManagement { * {@link TargetFilterQuery#getId()} * @return the found number of {@link Target}s * - * @throws EntityNotFoundException + * @throws EntityNotFoundException * if {@link TargetFilterQuery} with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @@ -265,9 +269,9 @@ public interface TargetManagement { void deleteByControllerID(@NotEmpty String controllerID); /** - * Finds all targets for all the given parameter {@link TargetFilterQuery} and - * that don't have the specified distribution set in their action history and - * are compatible with the passed {@link DistributionSetType}. + * Finds all targets for all the given parameter {@link TargetFilterQuery} + * and that don't have the specified distribution set in their action + * history and are compatible with the passed {@link DistributionSetType}. * * @param pageRequest * the pageRequest to enhance the query for paging and sorting @@ -281,13 +285,13 @@ public interface TargetManagement { * if distribution set with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findByTargetFilterQueryAndNonDSAndCompatible(@NotNull Pageable pageRequest, long distributionSetId, + Slice findByTargetFilterQueryAndNonDSAndCompatible(@NotNull Pageable pageRequest, long distributionSetId, @NotNull String rsqlParam); /** - * Counts all targets for all the given parameter {@link TargetFilterQuery} and - * that don't have the specified distribution set in their action history and - * are compatible with the passed {@link DistributionSetType}. + * Counts all targets for all the given parameter {@link TargetFilterQuery} + * and that don't have the specified distribution set in their action + * history and are compatible with the passed {@link DistributionSetType}. * * @param distributionSetId * id of the {@link DistributionSet} @@ -302,9 +306,9 @@ public interface TargetManagement { long countByRsqlAndNonDSAndCompatible(long distributionSetId, @NotNull String rsqlParam); /** - * Finds all targets for all the given parameter {@link TargetFilterQuery} and - * that are not assigned to one of the {@link RolloutGroup}s and are compatible - * with the passed {@link DistributionSetType}. + * Finds all targets for all the given parameter {@link TargetFilterQuery} + * and that are not assigned to one of the {@link RolloutGroup}s and are + * compatible with the passed {@link DistributionSetType}. * * @param pageRequest * the pageRequest to enhance the query for paging and sorting @@ -313,27 +317,27 @@ public interface TargetManagement { * @param rsqlParam * filter definition in RSQL syntax * @param distributionSetType - * type of the {@link DistributionSet} the targets must be compatible - * with + * type of the {@link DistributionSet} the targets must be + * compatible with * @return a page of the found {@link Target}s */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(@NotNull Pageable pageRequest, + Slice findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(@NotNull Pageable pageRequest, @NotEmpty Collection groups, @NotNull String rsqlParam, @NotNull DistributionSetType distributionSetType); /** - * Counts all targets for all the given parameter {@link TargetFilterQuery} and - * that are not assigned to one of the {@link RolloutGroup}s and are compatible - * with the passed {@link DistributionSetType}. + * Counts all targets for all the given parameter {@link TargetFilterQuery} + * and that are not assigned to one of the {@link RolloutGroup}s and are + * compatible with the passed {@link DistributionSetType}. * * @param groups * the list of {@link RolloutGroup}s * @param rsqlParam * filter definition in RSQL syntax * @param distributionSetType - * type of the {@link DistributionSet} the targets must be compatible - * with + * type of the {@link DistributionSet} the targets must be + * compatible with * @return count of the found {@link Target}s */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @@ -354,7 +358,7 @@ public interface TargetManagement { * if rollout group with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findByInRolloutGroupWithoutAction(@NotNull Pageable pageRequest, long group); + Slice findByInRolloutGroupWithoutAction(@NotNull Pageable pageRequest, long group); /** * retrieves {@link Target}s by the assigned {@link DistributionSet}. @@ -518,7 +522,7 @@ public interface TargetManagement { * if the RSQL syntax is wrong */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findByRsql(@NotNull Pageable pageable, @NotNull String rsqlParam); + Slice findByRsql(@NotNull Pageable pageable, @NotNull String rsqlParam); /** * Retrieves all target based on {@link TargetFilterQuery}. @@ -612,8 +616,8 @@ public interface TargetManagement { /** * Toggles {@link TargetTag} assignment to given {@link Target}s by means * that if some (or all) of the targets in the list have the {@link Tag} not - * yet assigned, they will be. Only if all of theme have the tag already assigned - * they will be removed instead. + * yet assigned, they will be. Only if all of theme have the tag already + * assigned they will be removed instead. * * @param controllerIds * to toggle for @@ -627,12 +631,11 @@ public interface TargetManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) TargetTagAssignmentResult toggleTagAssignment(@NotEmpty Collection controllerIds, @NotEmpty String tagName); - /** * Initiates {@link TargetType} assignment to given {@link Target}s. If some - * targets in the list have the {@link TargetType} not yet assigned, they will - * get assigned. If all targets are already of that type, there will be no - * un-assignment. + * targets in the list have the {@link TargetType} not yet assigned, they + * will get assigned. If all targets are already of that type, there will be + * no un-assignment. * * @param controllerIds * to set the type to @@ -648,8 +651,8 @@ public interface TargetManagement { TargetTypeAssignmentResult assignType(@NotEmpty Collection controllerIds, @NotNull Long typeId); /** - * Initiates {@link TargetType} un-assignment to given {@link Target}s. The type - * of the targets will be set to {@code null} + * Initiates {@link TargetType} un-assignment to given {@link Target}s. The + * type of the targets will be set to {@code null} * * @param controllerIds * to remove the type from @@ -851,6 +854,20 @@ public interface TargetManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) Page findMetaDataByControllerId(@NotNull Pageable pageable, @NotEmpty String controllerId); + /** + * Counts all meta data by the given target id. + * + * @param controllerId + * the controller id to retrieve the meta data from + * + * @return count of all meta data entries for a given target id + * + * @throws EntityNotFoundException + * if target with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + long countMetaDataByControllerId(@NotEmpty String controllerId); + /** * Finds all meta data by the given target id and query. * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTypeManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTypeManagement.java index 8b1b557c2..fda8df559 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTypeManagement.java @@ -8,21 +8,23 @@ */ package org.eclipse.hawkbit.repository; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.builder.TargetTypeCreate; import org.eclipse.hawkbit.repository.builder.TargetTypeUpdate; import org.eclipse.hawkbit.repository.model.TargetType; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.security.access.prepost.PreAuthorize; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.util.Collection; -import java.util.List; -import java.util.Optional; - /** * Management service for {@link TargetType}s. * @@ -43,9 +45,17 @@ public interface TargetTypeManagement { @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) long count(); + /** + * @param name + * as {@link TargetType#getName()} + * @return total count by name + */ + @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) + long countByName(String name); + /** * @param create - * TargetTypeCreate + * TargetTypeCreate * @return targetType */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_CREATE_TARGET) @@ -53,31 +63,32 @@ public interface TargetTypeManagement { /** * @param creates - * List of TargetTypeCreate + * List of TargetTypeCreate * @return List of targetType */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_CREATE_TARGET) List create(@NotEmpty @Valid Collection creates); /** - * @param id targetTypeId + * @param id + * targetTypeId */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_DELETE_TARGET) void delete(@NotNull Long id); /** * @param pageable - * Page + * Page * @return TargetType page */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findAll(@NotNull Pageable pageable); + Slice findAll(@NotNull Pageable pageable); /** * @param pageable - * Page + * Page * @param rsqlParam - * query param + * query param * @return Target type */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @@ -93,11 +104,11 @@ public interface TargetTypeManagement { * @return the page of found {@link TargetType} */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findByName(@NotNull Pageable pageable, String name); + Slice findByName(@NotNull Pageable pageable, String name); /** * @param id - * Target type ID + * Target type ID * @return Target Type */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @@ -105,7 +116,7 @@ public interface TargetTypeManagement { /** * @param targetId - * Target ID + * Target ID * @return Target Type */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @@ -113,7 +124,7 @@ public interface TargetTypeManagement { /** * @param targetIds - * List of Target ID + * List of Target ID * @return Target Type */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @@ -121,7 +132,7 @@ public interface TargetTypeManagement { /** * @param controllerId - * Target controller ID + * Target controller ID * @return Target Type */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @@ -129,25 +140,23 @@ public interface TargetTypeManagement { /** * @param controllerIds - * List of Target controller ID + * List of Target controller ID * @return Target Type */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) List findByTargetControllerIds(Collection controllerIds); - /** * @param ids - * List of Target type ID + * List of Target type ID * @return Target type list */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) List get(@NotEmpty Collection ids); - /** * @param update - * TargetTypeUpdate + * TargetTypeUpdate * @return Target Type */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) @@ -155,20 +164,20 @@ public interface TargetTypeManagement { /** * @param targetTypeId - * Target type ID + * Target type ID * @param distributionSetTypeIds - * Distribution set ID + * Distribution set ID * @return Target type */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET) TargetType assignCompatibleDistributionSetTypes(long targetTypeId, - @NotEmpty Collection distributionSetTypeIds); + @NotEmpty Collection distributionSetTypeIds); /** * @param targetTypeId - * Target type ID + * Target type ID * @param distributionSetTypeIds - * Distribution set ID + * Distribution set ID * @return Target type */ @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET) diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetFilter.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetFilter.java index 3e80ada54..f1c81a35d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetFilter.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetFilter.java @@ -21,9 +21,8 @@ public final class DistributionSetFilter { private Boolean isDeleted; private Boolean isComplete; private Boolean isValid; - private DistributionSetType type; + private Long typeId; private String searchText; - private String filterString; private Boolean selectDSWithNoTag; private Collection tagNames; private String assignedTargetId; @@ -68,11 +67,6 @@ public final class DistributionSetFilter { return this; } - public DistributionSetFilterBuilder setFilterString(final String filterString) { - this.filterString = filterString; - return this; - } - public DistributionSetFilterBuilder setSelectDSWithNoTag(final Boolean selectDSWithNoTag) { this.selectDSWithNoTag = selectDSWithNoTag; return this; @@ -83,8 +77,8 @@ public final class DistributionSetFilter { return this; } - public DistributionSetFilterBuilder setType(final DistributionSetType type) { - this.type = type; + public DistributionSetFilterBuilder setTypeId(final Long typeId) { + this.typeId = typeId; return this; } @@ -93,9 +87,8 @@ public final class DistributionSetFilter { private final Boolean isDeleted; private final Boolean isComplete; private final Boolean isValid; - private final DistributionSetType type; + private final Long typeId; private final String searchText; - private final String filterString; private final Boolean selectDSWithNoTag; private final Collection tagNames; private final String assignedTargetId; @@ -112,9 +105,8 @@ public final class DistributionSetFilter { this.isDeleted = builder.isDeleted; this.isComplete = builder.isComplete; this.isValid = builder.isValid; - this.type = builder.type; + this.typeId = builder.typeId; this.searchText = builder.searchText; - this.filterString = builder.filterString; this.selectDSWithNoTag = builder.selectDSWithNoTag; this.tagNames = builder.tagNames; this.assignedTargetId = builder.assignedTargetId; @@ -145,10 +137,6 @@ public final class DistributionSetFilter { return searchText; } - public String getFilterString() { - return filterString; - } - public Boolean getSelectDSWithNoTag() { return selectDSWithNoTag; } @@ -157,8 +145,8 @@ public final class DistributionSetFilter { return tagNames; } - public DistributionSetType getType() { - return type; + public Long getTypeId() { + return typeId; } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java index 68e0b36a0..93af8e10a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java @@ -220,6 +220,13 @@ public class JpaArtifactManagement implements ArtifactManagement { return localArtifactRepository.findBySoftwareModuleId(pageReq, swId); } + @Override + public long countBySoftwareModule(final long swId) { + throwExceptionIfSoftwareModuleDoesNotExist(swId); + + return localArtifactRepository.countBySoftwareModuleId(swId); + } + private void throwExceptionIfSoftwareModuleDoesNotExist(final Long swId) { if (!softwareModuleRepository.existsById(swId)) { throw new EntityNotFoundException(SoftwareModule.class, swId); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java index deee75191..ef3b724d2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java @@ -12,6 +12,7 @@ import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationPrope import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; @@ -273,7 +274,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); if (target.getTargetType() != null) { - // we assume that list of assigned DS is less than MAX_ENTRIES_IN_STATEMENT + // we assume that list of assigned DS is less than + // MAX_ENTRIES_IN_STATEMENT final Set incompatibleDistSetTypes = distributionSetManagement.get(distSetIds).stream() .map(DistributionSet::getType).collect(Collectors.toSet()); incompatibleDistSetTypes.removeAll(target.getTargetType().getCompatibleDistributionSetTypes()); @@ -309,8 +311,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl } /** - * method assigns the {@link DistributionSet} to all {@link Target}s by their - * IDs with a specific {@link ActionType} and {@code forcetime}. + * method assigns the {@link DistributionSet} to all {@link Target}s by + * their IDs with a specific {@link ActionType} and {@code forcetime}. * * * In case the update was executed offline (i.e. not managed by hawkBit) the @@ -318,8 +320,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl * A. it ignores targets completely that are in * {@link TargetUpdateStatus#PENDING}.
* B. it created completed actions.
- * C. sets both installed and assigned DS on the target and switches the status - * to {@link TargetUpdateStatus#IN_SYNC}
+ * C. sets both installed and assigned DS on the target and switches the + * status to {@link TargetUpdateStatus#IN_SYNC}
* D. does not send a {@link TargetAssignDistributionSetEvent}.
* * @param initiatedBy @@ -404,9 +406,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl } /** - * split tIDs length into max entries in-statement because many database have - * constraint of max entries in in-statements e.g. Oracle with maximum 1000 - * elements, so we need to split the entries here and execute multiple + * split tIDs length into max entries in-statement because many database + * have constraint of max entries in in-statements e.g. Oracle with maximum + * 1000 elements, so we need to split the entries here and execute multiple * statements */ private static List> getTargetEntitiesAsChunks(final List targetEntities) { @@ -579,10 +581,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl return 0L; } - final List targetAssignments = rolloutGroupActions.getContent().stream() - .map(action -> (JpaAction) action).map(this::closeActionIfSetWasAlreadyAssigned) - .filter(Objects::nonNull).map(this::startScheduledActionIfNoCancelationHasToBeHandledFirst) - .filter(Objects::nonNull).collect(Collectors.toList()); + final List targetAssignments = rolloutGroupActions.getContent().stream().map(JpaAction.class::cast) + .map(this::closeActionIfSetWasAlreadyAssigned).filter(Objects::nonNull) + .map(this::startScheduledActionIfNoCancelationHasToBeHandledFirst).filter(Objects::nonNull) + .collect(Collectors.toList()); if (!targetAssignments.isEmpty()) { onlineDsAssignmentStrategy.sendDeploymentEvents(distributionSetId, targetAssignments); @@ -696,20 +698,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl final Pageable pageable) { throwExceptionIfTargetDoesNotExist(controllerId); - final Specification byTargetSpec = createSpecificationFor(controllerId, rsqlParam); - final Page actions = actionRepository.findAll(byTargetSpec, pageable); - return convertAcPage(actions, pageable); + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database), + byControllerIdSpec(controllerId)); + + return JpaManagementHelper.findAllWithCountBySpec(actionRepository, pageable, specList); } - private Specification createSpecificationFor(final String controllerId, final String rsqlParam) { - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, - virtualPropertyReplacer, database); - return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb), - cb.equal(root.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId)); - } - - private static Page convertAcPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); + private Specification byControllerIdSpec(final String controllerId) { + return (root, query, cb) -> cb.equal(root.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId); } @Override @@ -744,7 +741,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl @Override public long countActionsByTarget(final String rsqlParam, final String controllerId) { throwExceptionIfTargetDoesNotExist(controllerId); - return actionRepository.count(createSpecificationFor(controllerId, rsqlParam)); + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database), + byControllerIdSpec(controllerId)); + + return JpaManagementHelper.countBySpec(actionRepository, specList); } private void throwExceptionIfTargetDoesNotExist(final String controllerId) { @@ -776,24 +777,28 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl @Override public Page findActionStatusByAction(final Pageable pageReq, final long actionId) { + verifyActionExists(actionId); + + return actionStatusRepository.findByActionId(pageReq, actionId); + } + + private void verifyActionExists(final long actionId) { if (!actionRepository.existsById(actionId)) { throw new EntityNotFoundException(Action.class, actionId); } + } - return actionStatusRepository.findByActionId(pageReq, actionId); + @Override + public long countActionStatusByAction(final long actionId) { + verifyActionExists(actionId); + + return actionStatusRepository.countByActionId(actionId); } @Override public Page findMessagesByActionStatusId(final Pageable pageable, final long actionStatusId) { final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); - final CriteriaQuery countMsgQuery = cb.createQuery(Long.class); - final Root countMsgQueryFrom = countMsgQuery.distinct(true).from(JpaActionStatus.class); - final ListJoin cJoin = countMsgQueryFrom.joinList("messages", JoinType.LEFT); - countMsgQuery.select(cb.count(cJoin)) - .where(cb.equal(countMsgQueryFrom.get(JpaActionStatus_.id), actionStatusId)); - final Long totalCount = entityManager.createQuery(countMsgQuery).getSingleResult(); - final CriteriaQuery msgQuery = cb.createQuery(String.class); final Root as = msgQuery.from(JpaActionStatus.class); final ListJoin join = as.joinList("messages", JoinType.LEFT); @@ -803,16 +808,25 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl final List result = new ArrayList<>(entityManager.createQuery(selMsgQuery) .setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList()); - return new PageImpl<>(result, pageable, totalCount); + return new PageImpl<>(result, pageable, result.size()); + } + + @Override + public long countMessagesByActionStatusId(final long actionStatusId) { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + final CriteriaQuery countMsgQuery = cb.createQuery(Long.class); + final Root countMsgQueryFrom = countMsgQuery.distinct(true).from(JpaActionStatus.class); + final ListJoin cJoin = countMsgQueryFrom.joinList("messages", JoinType.LEFT); + countMsgQuery.select(cb.count(cJoin)) + .where(cb.equal(countMsgQueryFrom.get(JpaActionStatus_.id), actionStatusId)); + + return entityManager.createQuery(countMsgQuery).getSingleResult(); } @Override public Page findActionStatusAll(final Pageable pageable) { - return convertAcSPage(actionStatusRepository.findAll(pageable), pageable); - } - - private static Page convertAcSPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); + return JpaManagementHelper.findAllWithCountBySpec(actionStatusRepository, pageable, null); } @Override @@ -844,7 +858,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl @Override public Slice findActionsAll(final Pageable pageable) { - return convertAcPage(actionRepository.findAll(pageable), pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, pageable, null); } @Override @@ -866,10 +880,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl return 0; } /* - * We use a native query here because Spring JPA does not support to specify a - * LIMIT clause on a DELETE statement. However, for this specific use case - * (action cleanup), we must specify a row limit to reduce the overall load on - * the database. + * We use a native query here because Spring JPA does not support to + * specify a LIMIT clause on a DELETE statement. However, for this + * specific use case (action cleanup), we must specify a row limit to + * reduce the overall load on the database. */ final int statusCount = status.size(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java index 061fb9251..cbca3616f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.repository.jpa; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -17,12 +16,14 @@ import java.util.Optional; import java.util.stream.Collectors; import javax.persistence.EntityManager; +import javax.validation.constraints.NotNull; import org.eclipse.hawkbit.repository.DistributionSetFields; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetMetadataFields; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; +import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; @@ -50,7 +51,6 @@ import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetFilter; -import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; @@ -62,9 +62,9 @@ import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; +import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; @@ -148,7 +148,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Override public Optional getWithDetails(final long distid) { return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid)) - .map(d -> (DistributionSet) d); + .map(DistributionSet.class::cast); } @Override @@ -337,101 +337,59 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - public Page findByDistributionSetFilter(final Pageable pageable, + public Slice findByDistributionSetFilter(final Pageable pageable, final DistributionSetFilter distributionSetFilter) { final List> specList = buildDistributionSetSpecifications( distributionSetFilter); - return convertDsPage(findByCriteriaAPI(pageable, specList), pageable); + + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable, specList); } - private static Page convertDsPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - private static Slice convertDsPage(final Slice findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0); - } - - /** - * - * @param distributionSetFilter - * had details of filters to be applied - * @return a single DistributionSet which is either installed or assigned to - * a specific target or {@code null}. - */ - private Optional findDistributionSetsByFiltersAndInstalledOrAssignedTarget( - final DistributionSetFilter distributionSetFilter) { + @Override + public long countByDistributionSetFilter(@NotNull final DistributionSetFilter distributionSetFilter) { final List> specList = buildDistributionSetSpecifications( distributionSetFilter); - if (CollectionUtils.isEmpty(specList)) { - return Optional.empty(); - } - return distributionSetRepository.findOne(SpecificationsBuilder.combineWithAnd(specList)); + + return JpaManagementHelper.countBySpec(distributionSetRepository, specList); } @Override - public Page findByCompleted(final Pageable pageReq, final Boolean complete) { + public Slice findByCompleted(final Pageable pageReq, final Boolean complete) { + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageReq, + buildSpecsByComplete(complete)); + } - List> specList; - if (complete != null) { - specList = Arrays.asList(DistributionSetSpecification.isDeleted(false), - DistributionSetSpecification.isCompleted(complete)); - } else { - specList = Collections.singletonList(DistributionSetSpecification.isDeleted(false)); - } - - return convertDsPage(findByCriteriaAPI(pageReq, specList), pageReq); + private List> buildSpecsByComplete(final Boolean complete) { + return complete != null + ? Arrays.asList(DistributionSetSpecification.isDeleted(false), + DistributionSetSpecification.isCompleted(complete)) + : Collections.singletonList(DistributionSetSpecification.isDeleted(false)); } @Override - public Page findByFilterAndAssignedInstalledDsOrderedByLinkTarget(final Pageable pageable, - final DistributionSetFilterBuilder distributionSetFilterBuilder, final String assignedOrInstalled) { + public long countByCompleted(final Boolean complete) { + return JpaManagementHelper.countBySpec(distributionSetRepository, buildSpecsByComplete(complete)); + } - final DistributionSetFilter filterWithInstalledTargets = distributionSetFilterBuilder - .setInstalledTargetId(assignedOrInstalled).setAssignedTargetId(null).build(); - final Optional installedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget( - filterWithInstalledTargets); + @Override + public Slice findByDistributionSetFilterOrderByLinkedTarget(final Pageable pageable, + final DistributionSetFilter distributionSetFilter, final String assignedOrInstalled) { + final List> specList = buildDistributionSetSpecifications( + distributionSetFilter); + specList.add(DistributionSetSpecification.orderedByLinkedTarget(assignedOrInstalled)); - final DistributionSetFilter filterWithAssignedTargets = distributionSetFilterBuilder.setInstalledTargetId(null) - .setAssignedTargetId(assignedOrInstalled).build(); - final Optional assignedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget( - filterWithAssignedTargets); + // remove default sort from pageable to not overwrite sorted spec + final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(), + pageable.getPageSize(), Sort.unsorted()); - final DistributionSetFilter dsFilterWithNoTargetLinked = distributionSetFilterBuilder.setInstalledTargetId(null) - .setAssignedTargetId(null).build(); - // first fine the distribution sets filtered by the given filter - // parameters - final Page findDistributionSetsByFilters = findByDistributionSetFilter(pageable, - dsFilterWithNoTargetLinked); - - final List resultSet = new ArrayList<>(findDistributionSetsByFilters.getContent()); - int orderIndex = 0; - if (installedDS.isPresent()) { - final boolean remove = resultSet.remove(installedDS.get()); - if (!remove) { - resultSet.remove(resultSet.size() - 1); - } - resultSet.add(orderIndex, installedDS.get()); - orderIndex++; - } - if (assignedDS.isPresent() && !assignedDS.equals(installedDS)) { - final boolean remove = resultSet.remove(assignedDS.get()); - if (!remove) { - resultSet.remove(resultSet.size() - 1); - } - resultSet.add(orderIndex, assignedDS.get()); - } - - return new PageImpl<>(resultSet, pageable, findDistributionSetsByFilters.getTotalElements()); + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, unsortedPage, specList); } @Override public Optional getByNameAndVersion(final String distributionName, final String version) { final Specification spec = DistributionSetSpecification .equalsNameAndVersionIgnoreCase(distributionName, version); - return distributionSetRepository.findOne(spec).map(d -> (DistributionSet) d); + return distributionSetRepository.findOne(spec).map(DistributionSet.class::cast); } @@ -453,7 +411,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { assertMetaDataQuota(dsId, md.size()); - final JpaDistributionSet set = touch(dsId); + final JpaDistributionSet set = JpaManagementHelper.touch(entityManager, distributionSetRepository, + (JpaDistributionSet) getValid(dsId)); return Collections.unmodifiableList(md.stream() .map(meta -> distributionSetMetadataRepository @@ -485,7 +444,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { toUpdate.setValue(md.getValue()); // touch it to update the lock revision because we are modifying the // DS indirectly - touch(dsId); + JpaManagementHelper.touch(entityManager, distributionSetRepository, (JpaDistributionSet) getValid(dsId)); return distributionSetMetadataRepository.save(toUpdate); } @@ -498,72 +457,42 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { distributionSetId, key).orElseThrow( () -> new EntityNotFoundException(DistributionSetMetadata.class, distributionSetId, key)); - touch(metadata.getDistributionSet()); + JpaManagementHelper.touch(entityManager, distributionSetRepository, + (JpaDistributionSet) metadata.getDistributionSet()); distributionSetMetadataRepository.deleteById(metadata.getId()); } - /** - * Method to get the latest distribution set based on DS ID after the - * metadata changes for that distribution set. - * - * @param ds - * is the DS to touch - */ - private JpaDistributionSet touch(final DistributionSet ds) { - - // merge base distribution set so optLockRevision gets updated and audit - // log written because modifying metadata is modifying the base - // distribution set itself for auditing purposes. - final JpaDistributionSet result = entityManager.merge((JpaDistributionSet) ds); - result.setLastModifiedAt(0L); - - return distributionSetRepository.save(result); - } - - /** - * Method to get the latest distribution set based on DS ID after the - * metadata changes for that distribution set. - * - * @param distId - * of the DS to touch - */ - private JpaDistributionSet touch(final Long distId) { - return touch(getValid(distId)); - } - @Override public Page findMetaDataByDistributionSetId(final Pageable pageable, final long distributionSetId) { throwExceptionIfDistributionSetDoesNotExist(distributionSetId); - return convertMdPage(distributionSetMetadataRepository - .findAll((Specification) (root, query, cb) -> cb.equal( - root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), - distributionSetId), pageable), - pageable); + return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable, + Collections.singletonList(byDsIdSpec(distributionSetId))); + } + + private Specification byDsIdSpec(final long dsId) { + return (root, query, cb) -> cb + .equal(root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), dsId); + } + + @Override + public long countMetaDataByDistributionSetId(final long setId) { + throwExceptionIfDistributionSetDoesNotExist(setId); + + return distributionSetMetadataRepository.countByDistributionSetId(setId); } @Override public Page findMetaDataByDistributionSetIdAndRsql(final Pageable pageable, final long distributionSetId, final String rsqlParam) { - throwExceptionIfDistributionSetDoesNotExist(distributionSetId); - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, - DistributionSetMetadataFields.class, virtualPropertyReplacer, database); + final List> specList = Arrays + .asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetMetadataFields.class, + virtualPropertyReplacer, database), byDsIdSpec(distributionSetId)); - return convertMdPage( - distributionSetMetadataRepository - .findAll((Specification) (root, query, cb) -> cb.and( - cb.equal(root.get(JpaDistributionSetMetadata_.distributionSet) - .get(JpaDistributionSet_.id), distributionSetId), - spec.toPredicate(root, query, cb)), pageable), - pageable); - } - - private static Page convertMdPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); + return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable, specList); } @Override @@ -571,7 +500,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { throwExceptionIfDistributionSetDoesNotExist(setId); return distributionSetMetadataRepository.findById(new DsMetadataCompositeKey(setId, key)) - .map(dmd -> (DistributionSetMetadata) dmd); + .map(DistributionSetMetadata.class::cast); } @Override @@ -611,19 +540,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { specList.add(spec); } - if (distributionSetFilter.getType() != null) { - spec = DistributionSetSpecification.byType(distributionSetFilter.getType()); + if (distributionSetFilter.getTypeId() != null) { + spec = DistributionSetSpecification.byType(distributionSetFilter.getTypeId()); specList.add(spec); } if (!StringUtils.isEmpty(distributionSetFilter.getSearchText())) { - spec = DistributionSetSpecification.likeNameOrDescriptionOrVersion(distributionSetFilter.getSearchText()); - specList.add(spec); - } - - if (!StringUtils.isEmpty(distributionSetFilter.getFilterString())) { - final String[] dsFilterNameAndVersionEntries = getDsFilterNameAndVersionEntries( - distributionSetFilter.getFilterString().trim()); + final String[] dsFilterNameAndVersionEntries = JpaManagementHelper + .getFilterNameAndVersionEntries(distributionSetFilter.getSearchText().trim()); spec = DistributionSetSpecification.likeNameAndVersion(dsFilterNameAndVersionEntries[0], dsFilterNameAndVersionEntries[1]); specList.add(spec); @@ -645,19 +569,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { return specList; } - // the format of filter string is 'name:version'. 'name' and 'version' - // fields follow the starts_with semantic, that changes to equal for 'name' - // field when the semicolon is present - private static String[] getDsFilterNameAndVersionEntries(final String filterString) { - final int semicolonIndex = filterString.indexOf(':'); - - final String dsFilterName = semicolonIndex != -1 ? filterString.substring(0, semicolonIndex) - : (filterString + "%"); - final String dsFilterVersion = semicolonIndex != -1 ? (filterString.substring(semicolonIndex + 1) + "%") : "%"; - - return new String[] { !StringUtils.isEmpty(dsFilterName) ? dsFilterName : "%", dsFilterVersion }; - } - private void assertDistributionSetIsNotAssignedToTargets(final Long distributionSet) { if (actionRepository.countByDistributionSetId(distributionSet) > 0) { throw new EntityReadOnlyException(String.format( @@ -672,26 +583,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { return isNoTagActive || isAtLeastOneTagActive; } - /** - * executes findAll with the given {@link DistributionSet} - * {@link Specification}s. - * - * @param pageable - * paging parameter - * @param specList - * list of @link {@link Specification} - * @return the page with the found {@link DistributionSet} - */ - private Page findByCriteriaAPI(final Pageable pageable, - final List> specList) { - - if (CollectionUtils.isEmpty(specList)) { - return distributionSetRepository.findAll(pageable); - } - - return distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable); - } - private void checkAndThrowIfDistributionSetMetadataAlreadyExists(final DsMetadataCompositeKey metadataId) { if (distributionSetMetadataRepository.existsById(metadataId)) { throw new EntityAlreadyExistsException( @@ -769,7 +660,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { public Page findByTag(final Pageable pageable, final long tagId) { throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId); - return convertDsPage(distributionSetRepository.findByTag(pageable, tagId), pageable); + return JpaManagementHelper.convertPage(distributionSetRepository.findByTag(pageable, tagId), pageable); } @@ -783,28 +674,27 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { public Page findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) { throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId); - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, - DistributionSetFields.class, virtualPropertyReplacer, database); + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer, + database), + DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isDeleted(false)); - return convertDsPage(findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.hasTag(tagId), - DistributionSetSpecification.isDeleted(false))), pageable); + return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, specList); } @Override public Slice findAll(final Pageable pageable) { - return convertDsPage( - distributionSetRepository.findAllWithoutCount(DistributionSetSpecification.isDeleted(false), pageable), - pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable, + Collections.singletonList(DistributionSetSpecification.isDeleted(false))); } @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, - DistributionSetFields.class, virtualPropertyReplacer, database); + final List> specList = Arrays.asList(RSQLUtility + .buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer, database), + DistributionSetSpecification.isDeleted(false)); - return convertDsPage( - findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.isDeleted(false))), - pageable); + return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, specList); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTagManagement.java index d5e4687fd..9ac715853 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTagManagement.java @@ -31,7 +31,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; @@ -125,7 +124,7 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage @Override public Slice findAll(final Pageable pageable) { - return convertDsPage(distributionSetTagRepository.findAllWithoutCount(pageable), pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTagRepository, pageable, null); } @Override @@ -133,7 +132,8 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class, virtualPropertyReplacer, database); - return convertDsPage(distributionSetTagRepository.findAll(spec, pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable, + Collections.singletonList(spec)); } @Override @@ -142,18 +142,8 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage throw new EntityNotFoundException(DistributionSet.class, setId); } - return convertDsPage(distributionSetTagRepository.findAll(TagSpecification.ofDistributionSet(setId), pageable), - pageable); - } - - private static Page convertDsPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - private static Slice convertDsPage(final Slice findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0); + return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable, + Collections.singletonList(TagSpecification.ofDistributionSet(setId))); } @Override @@ -178,7 +168,7 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage @Override public Optional get(final long id) { - return distributionSetTagRepository.findById(id).map(dst -> (DistributionSetTag) dst); + return distributionSetTagRepository.findById(id).map(DistributionSetTag.class::cast); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java index 755c933aa..7b3ec8144 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java @@ -35,17 +35,14 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTypeSpecification; -import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; -import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; @@ -227,17 +224,18 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { - return convertPage( - findByCriteriaAPI(pageable, - Arrays.asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTypeFields.class, - virtualPropertyReplacer, database), DistributionSetTypeSpecification.isDeleted(false))), - pageable); + return JpaManagementHelper + .findAllWithCountBySpec(distributionSetTypeRepository, pageable, + Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTypeFields.class, + virtualPropertyReplacer, database), + DistributionSetTypeSpecification.isDeleted(false))); } @Override public Slice findAll(final Pageable pageable) { - return convertPage(distributionSetTypeRepository - .findAllWithoutCount(DistributionSetTypeSpecification.isDeleted(false), pageable), pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTypeRepository, pageable, + Collections.singletonList(DistributionSetTypeSpecification.isDeleted(false))); } @Override @@ -280,14 +278,13 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana if (distributionSetRepository.countByTypeId(typeId) > 0) { toDelete.setDeleted(true); distributionSetTypeRepository.save(toDelete); - } - else { + } else { distributionSetTypeRepository.deleteById(typeId); } } - private void unassignDsTypeFromTargetTypes(long typeId) { - List targetTypesByDsType = targetTypeRepository.findByDsType(typeId); + private void unassignDsTypeFromTargetTypes(final long typeId) { + final List targetTypesByDsType = targetTypeRepository.findByDsType(typeId); targetTypesByDsType.forEach(targetType -> { targetType.removeDistributionSetType(typeId); targetTypeRepository.save(targetType); @@ -318,26 +315,6 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana } } - private static Page convertPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - private static Slice convertPage(final Slice findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0); - } - - private Page findByCriteriaAPI(final Pageable pageable, - final List> specList) { - - if (CollectionUtils.isEmpty(specList)) { - return distributionSetTypeRepository.findAll(pageable); - } - - return distributionSetTypeRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable); - } - @Override @Transactional @Retryable(include = { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java new file mode 100644 index 000000000..d2328c168 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2022 Bosch.IO GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository.jpa; + +import java.util.Collections; +import java.util.List; + +import javax.persistence.EntityManager; + +import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity; +import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.repository.CrudRepository; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +/** + * A collection of static helper methods for the management classes + */ +public final class JpaManagementHelper { + private JpaManagementHelper() { + } + + public static Page findAllWithCountBySpec(final JpaSpecificationExecutor repository, + final Pageable pageable, final List> specList) { + if (CollectionUtils.isEmpty(specList)) { + return convertPage(repository.findAll(Specification.where(null), pageable), pageable); + } + + return convertPage(repository.findAll(combineWithAnd(specList), pageable), pageable); + } + + public static Page convertPage(final Page jpaAll, final Pageable pageable) { + return new PageImpl<>(Collections.unmodifiableList(jpaAll.getContent()), pageable, jpaAll.getTotalElements()); + } + + private static Specification combineWithAnd(final List> specList) { + return specList.size() == 1 ? specList.get(0) : SpecificationsBuilder.combineWithAnd(specList); + } + + public static Slice findAllWithoutCountBySpec(final NoCountSliceRepository repository, + final Pageable pageable, final List> specList) { + if (CollectionUtils.isEmpty(specList)) { + return convertPage(repository.findAllWithoutCount(pageable), pageable); + } + + return convertPage(repository.findAllWithoutCount(combineWithAnd(specList), pageable), pageable); + } + + public static Slice convertPage(final Slice jpaAll, final Pageable pageable) { + return new PageImpl<>(Collections.unmodifiableList(jpaAll.getContent()), pageable, 0); + } + + public static long countBySpec(final JpaSpecificationExecutor repository, + final List> specList) { + if (CollectionUtils.isEmpty(specList)) { + return repository.count(Specification.where(null)); + } + + return repository.count(combineWithAnd(specList)); + } + + public static J touch(final EntityManager entityManager, + final CrudRepository repository, final J entity) { + // merge base entity so optLockRevision gets updated and audit + // log written because modifying e.g. metadata is modifying the base + // entity itself for auditing purposes. + final J result = entityManager.merge(entity); + result.setLastModifiedAt(0L); + + return repository.save(result); + } + + // the format of filter string is 'name:version'. 'name' and 'version' + // fields follow the starts_with semantic, that changes to equal for 'name' + // field when the semicolon is present + public static String[] getFilterNameAndVersionEntries(final String filterString) { + final int semicolonIndex = filterString.indexOf(':'); + + final String filterName = semicolonIndex != -1 ? filterString.substring(0, semicolonIndex) + : (filterString + "%"); + final String filterVersion = semicolonIndex != -1 ? (filterString.substring(semicolonIndex + 1) + "%") : "%"; + + return new String[] { !StringUtils.isEmpty(filterName) ? filterName : "%", filterVersion }; + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java index febb0c263..0f7397b6e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java @@ -55,7 +55,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; @@ -575,7 +574,7 @@ public class JpaRolloutExecutor implements RolloutExecutor { final PageRequest pageRequest = PageRequest.of(0, Math.toIntExact(limit)); final List readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(), RolloutGroupStatus.READY, group); - final Page targets = targetManagement.findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible( + final Slice targets = targetManagement.findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible( pageRequest, readyGroups, targetFilter, rollout.getDistributionSet().getType()); createAssignmentOfTargetsToGroup(targets, group); @@ -585,8 +584,8 @@ public class JpaRolloutExecutor implements RolloutExecutor { } /** - * Schedules a group of the rollout. Scheduled Actions are created to achieve - * this. The creation of those Actions is allowed to fail. + * Schedules a group of the rollout. Scheduled Actions are created to + * achieve this. The creation of those Actions is allowed to fail. */ private boolean scheduleRolloutGroup(final JpaRollout rollout, final JpaRolloutGroup group) { final long targetsInGroup = rolloutTargetGroupRepository.countByRolloutGroup(group); @@ -634,8 +633,8 @@ public class JpaRolloutExecutor implements RolloutExecutor { final ActionType actionType = rollout.getActionType(); final long forceTime = rollout.getForcedTime(); - final Page targets = targetManagement.findByInRolloutGroupWithoutAction(pageRequest, groupId); - if (targets.getTotalElements() > 0) { + final Slice targets = targetManagement.findByInRolloutGroupWithoutAction(pageRequest, groupId); + if (targets.getNumberOfElements() > 0) { createScheduledAction(targets.getContent(), distributionSet, actionType, forceTime, rollout, group); } @@ -643,14 +642,14 @@ public class JpaRolloutExecutor implements RolloutExecutor { }); } - private void createAssignmentOfTargetsToGroup(final Page targets, final RolloutGroup group) { + private void createAssignmentOfTargetsToGroup(final Slice targets, final RolloutGroup group) { targets.forEach(target -> rolloutTargetGroupRepository.save(new RolloutTargetGroup(group, target))); } /** * Creates an action entry into the action repository. In case of existing - * scheduled actions the scheduled actions gets canceled. A scheduled action is - * created in-active. + * scheduled actions the scheduled actions gets canceled. A scheduled action + * is created in-active. */ private void createScheduledAction(final Collection targets, final DistributionSet distributionSet, final ActionType actionType, final Long forcedTime, final Rollout rollout, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java index 5bab6afe5..3b1a4fde6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java @@ -8,6 +8,7 @@ */ package org.eclipse.hawkbit.repository.jpa; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -104,15 +105,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { public Page findByRollout(final Pageable pageable, final long rolloutId) { throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); - return convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, pageable), pageable); - } - - private static Page convertPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - private static Page convertTPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); + return JpaManagementHelper.convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, pageable), pageable); } @Override @@ -120,12 +113,12 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { final String rsqlParam) { throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); - final Specification specification = RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutGroupFields.class, - virtualPropertyReplacer, database); + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutGroupFields.class, virtualPropertyReplacer, + database), + (root, query, cb) -> cb.equal(root.get(JpaRolloutGroup_.rollout).get(JpaRollout_.id), rolloutId)); - return convertPage(rolloutGroupRepository.findAll((root, query, criteriaBuilder) -> criteriaBuilder.and( - criteriaBuilder.equal(root.get(JpaRolloutGroup_.rollout).get(JpaRollout_.id), rolloutId), - specification.toPredicate(root, query, criteriaBuilder)), pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(rolloutGroupRepository, pageable, specList); } private void throwEntityNotFoundExceptionIfRolloutDoesNotExist(final Long rolloutId) { @@ -157,7 +150,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { rolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus); } - return convertPage(rolloutGroups, pageable); + return JpaManagementHelper.convertPage(rolloutGroups, pageable); } @Override @@ -209,19 +202,18 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { @Override public Page findTargetsOfRolloutGroupByRsql(final Pageable pageable, final long rolloutGroupId, final String rsqlParam) { - throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); - final Specification rsqlSpecification = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, - virtualPropertyReplacer, database); + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), + (root, query, cb) -> { + final ListJoin rolloutTargetJoin = root + .join(JpaTarget_.rolloutTargetGroup); + return cb.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), + rolloutGroupId); + }); - return convertTPage(targetRepository.findAll((root, query, criteriaBuilder) -> { - final ListJoin rolloutTargetJoin = root.join(JpaTarget_.rolloutTargetGroup); - return criteriaBuilder.and(rsqlSpecification.toPredicate(root, query, criteriaBuilder), - criteriaBuilder.equal( - rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), - rolloutGroupId)); - }, pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList); } @Override @@ -233,11 +225,11 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { // in case of status ready the action has not been created yet and // the relation information between target and rollout-group is // stored in the #TargetRolloutGroup. - return JpaTargetManagement.convertPage( - targetRepository.findAll(TargetSpecifications.isInRolloutGroup(rolloutGroupId), page), page); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page, + Collections.singletonList(TargetSpecifications.isInRolloutGroup(rolloutGroupId))); } - return JpaTargetManagement.convertPage( - targetRepository.findAll(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId), page), page); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page, + Collections.singletonList(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId))); } private static boolean isRolloutStatusReady(final RolloutGroup rolloutGroup) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHelper.java deleted file mode 100644 index 4439c3588..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHelper.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.repository.jpa; - -import java.util.Collections; - -import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; -import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate; -import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; -import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; -import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_; -import org.eclipse.hawkbit.repository.model.Rollout; -import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.jpa.domain.Specification; - -/** - * A collection of static helper methods for the {@link JpaRolloutManagement} - */ -final class JpaRolloutHelper { - private JpaRolloutHelper() { - } - - /** - * In case the given group is missing conditions or actions, they will be - * set from the supplied default conditions. - * - * @param create - * group to check - * @param conditions - * default conditions and actions - */ - static JpaRolloutGroup prepareRolloutGroupWithDefaultConditions(final RolloutGroupCreate create, - final RolloutGroupConditions conditions) { - final JpaRolloutGroup group = ((JpaRolloutGroupCreate) create).build(); - - if (group.getSuccessCondition() == null) { - group.setSuccessCondition(conditions.getSuccessCondition()); - } - if (group.getSuccessConditionExp() == null) { - group.setSuccessConditionExp(conditions.getSuccessConditionExp()); - } - if (group.getSuccessAction() == null) { - group.setSuccessAction(conditions.getSuccessAction()); - } - if (group.getSuccessActionExp() == null) { - group.setSuccessActionExp(conditions.getSuccessActionExp()); - } - - if (group.getErrorCondition() == null) { - group.setErrorCondition(conditions.getErrorCondition()); - } - if (group.getErrorConditionExp() == null) { - group.setErrorConditionExp(conditions.getErrorConditionExp()); - } - if (group.getErrorAction() == null) { - group.setErrorAction(conditions.getErrorAction()); - } - if (group.getErrorActionExp() == null) { - group.setErrorActionExp(conditions.getErrorActionExp()); - } - - return group; - } - - /** - * Builds a {@link Specification} to search a rollout by name or - * description. - * - * @param searchText - * search string - * @param isDeleted - * true if deleted rollouts should be included in - * the search. Otherwise false - * @return criteria specification with a query for name or description of a - * rollout - */ - static Specification likeNameOrDescription(final String searchText, final boolean isDeleted) { - return (rolloutRoot, query, criteriaBuilder) -> { - final String searchTextToLower = searchText.toLowerCase(); - return criteriaBuilder.and(criteriaBuilder.or( - criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(JpaRollout_.name)), searchTextToLower), - criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(JpaRollout_.description)), - searchTextToLower)), - criteriaBuilder.equal(rolloutRoot.get(JpaRollout_.deleted), isDeleted)); - }; - } - - static Page convertPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - static Slice convertPage(final Slice findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0); - } - -} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java index 346bb054b..cb9718ada 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java @@ -12,6 +12,7 @@ import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.a import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -41,13 +42,13 @@ import org.eclipse.hawkbit.repository.event.remote.entity.RolloutGroupCreatedEve import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; +import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification; -import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper; @@ -160,8 +161,8 @@ public class JpaRolloutManagement implements RolloutManagement { @Override public Page findAll(final Pageable pageable, final boolean deleted) { - final Specification spec = RolloutSpecification.isDeletedWithDistributionSet(deleted); - return JpaRolloutHelper.convertPage(rolloutRepository.findAll(spec, pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable, + Collections.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted))); } @Override @@ -171,24 +172,12 @@ public class JpaRolloutManagement implements RolloutManagement { RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database)); specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted)); - return JpaRolloutHelper.convertPage(findByCriteriaAPI(pageable, specList), pageable); - } - - /** - * Executes findAll with the given {@link Rollout} {@link Specification}s. - */ - private Page findByCriteriaAPI(final Pageable pageable, - final List> specList) { - if (CollectionUtils.isEmpty(specList)) { - return rolloutRepository.findAll(pageable); - } - - return rolloutRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable); + return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable, specList); } @Override public Optional get(final long rolloutId) { - return rolloutRepository.findById(rolloutId).map(r -> (Rollout) r); + return rolloutRepository.findById(rolloutId).map(Rollout.class::cast); } @Override @@ -264,8 +253,7 @@ public class JpaRolloutManagement implements RolloutManagement { // prepare the groups final List groups = groupList.stream() - .map(group -> JpaRolloutHelper.prepareRolloutGroupWithDefaultConditions(group, conditions)) - .collect(Collectors.toList()); + .map(group -> prepareRolloutGroupWithDefaultConditions(group, conditions)).collect(Collectors.toList()); groups.forEach(RolloutHelper::verifyRolloutGroupHasConditions); RolloutHelper.verifyRemainingTargets(calculateRemainingTargets(groups, savedRollout.getTargetFilterQuery(), @@ -307,6 +295,48 @@ public class JpaRolloutManagement implements RolloutManagement { return rolloutRepository.save(savedRollout); } + /** + * In case the given group is missing conditions or actions, they will be + * set from the supplied default conditions. + * + * @param create + * group to check + * @param conditions + * default conditions and actions + */ + private static JpaRolloutGroup prepareRolloutGroupWithDefaultConditions(final RolloutGroupCreate create, + final RolloutGroupConditions conditions) { + final JpaRolloutGroup group = ((JpaRolloutGroupCreate) create).build(); + + if (group.getSuccessCondition() == null) { + group.setSuccessCondition(conditions.getSuccessCondition()); + } + if (group.getSuccessConditionExp() == null) { + group.setSuccessConditionExp(conditions.getSuccessConditionExp()); + } + if (group.getSuccessAction() == null) { + group.setSuccessAction(conditions.getSuccessAction()); + } + if (group.getSuccessActionExp() == null) { + group.setSuccessActionExp(conditions.getSuccessActionExp()); + } + + if (group.getErrorCondition() == null) { + group.setErrorCondition(conditions.getErrorCondition()); + } + if (group.getErrorConditionExp() == null) { + group.setErrorConditionExp(conditions.getErrorConditionExp()); + } + if (group.getErrorAction() == null) { + group.setErrorAction(conditions.getErrorAction()); + } + if (group.getErrorActionExp() == null) { + group.setErrorActionExp(conditions.getErrorActionExp()); + } + + return group; + } + private void publishRolloutGroupCreatedEventAfterCommit(final RolloutGroup group, final Rollout rollout) { afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher().publishEvent( new RolloutGroupCreatedEvent(group, rollout.getId(), eventPublisherHolder.getApplicationId()))); @@ -456,7 +486,7 @@ public class JpaRolloutManagement implements RolloutManagement { @Override public long countByFilters(final String searchText) { - return rolloutRepository.count(JpaRolloutHelper.likeNameOrDescription(searchText, false)); + return rolloutRepository.count(RolloutSpecification.likeName(searchText, false)); } @Override @@ -467,10 +497,10 @@ public class JpaRolloutManagement implements RolloutManagement { @Override public Slice findByFiltersWithDetailedStatus(final Pageable pageable, final String searchText, final boolean deleted) { - final Slice findAll = findByCriteriaAPI(pageable, - Arrays.asList(JpaRolloutHelper.likeNameOrDescription(searchText, deleted))); + final Slice findAll = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable, + Collections.singletonList(RolloutSpecification.likeName(searchText, deleted))); setRolloutStatusDetails(findAll); - return JpaRolloutHelper.convertPage(findAll, pageable); + return findAll; } @Override @@ -521,12 +551,11 @@ public class JpaRolloutManagement implements RolloutManagement { } @Override - public Page findAllWithDetailedStatus(final Pageable pageable, final boolean deleted) { - final Page rollouts; - final Specification spec = RolloutSpecification.isDeletedWithDistributionSet(deleted); - rollouts = rolloutRepository.findAll(spec, pageable); + public Slice findAllWithDetailedStatus(final Pageable pageable, final boolean deleted) { + final Slice rollouts = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable, + Collections.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted))); setRolloutStatusDetails(rollouts); - return JpaRolloutHelper.convertPage(rollouts, pageable); + return rollouts; } @Override @@ -579,7 +608,7 @@ public class JpaRolloutManagement implements RolloutManagement { return fromCache; } - private void setRolloutStatusDetails(final Slice rollouts) { + private void setRolloutStatusDetails(final Slice rollouts) { final List rolloutIds = rollouts.getContent().stream().map(Rollout::getId).collect(Collectors.toList()); final Map> allStatesForRollout = getStatusCountItemForRollout( rolloutIds); @@ -588,7 +617,7 @@ public class JpaRolloutManagement implements RolloutManagement { rollouts.forEach(rollout -> { final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus( allStatesForRollout.get(rollout.getId()), rollout.getTotalTargets(), rollout.getActionType()); - rollout.setTotalTargetCountStatus(totalTargetCountStatus); + ((JpaRollout) rollout).setTotalTargetCountStatus(totalTargetCountStatus); }); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java index 93a755f18..4477cd51a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java @@ -58,7 +58,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule_; import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification; -import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; @@ -70,7 +69,6 @@ import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -183,7 +181,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { specList.add(SoftwareModuleSpecification.equalType(typeId)); specList.add(SoftwareModuleSpecification.isDeletedFalse()); - return convertSmPage(findByCriteriaAPI(pageable, specList), pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList); } private void throwExceptionIfSoftwareModuleTypeDoesNotExist(final Long typeId) { @@ -192,23 +190,9 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { } } - private static Slice convertSmPage(final Slice findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0); - } - - private static Page convertSmPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - private static Page convertSmMdPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - @Override public Optional get(final long id) { - return softwareModuleRepository.findById(id).map(sm -> (SoftwareModule) sm); + return softwareModuleRepository.findById(id).map(SoftwareModule.class::cast); } @Override @@ -224,15 +208,6 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { return distributionSetRepository.countByModulesId(moduleId) <= 0; } - private Slice findByCriteriaAPI(final Pageable pageable, - final List> specList) { - return softwareModuleRepository.findAllWithoutCount(SpecificationsBuilder.combineWithAnd(specList), pageable); - } - - private Long countSwModuleByCriteriaAPI(final List> specList) { - return softwareModuleRepository.count(SpecificationsBuilder.combineWithAnd(specList)); - } - private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) { for (final Artifact localArtifact : swModule.getArtifacts()) { artifactManagement.clearArtifactBinary(localArtifact.getSha1Hash(), swModule.getId()); @@ -276,29 +251,18 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Override public Slice findAll(final Pageable pageable) { - final List> specList = new ArrayList<>(2); + specList.add(SoftwareModuleSpecification.isDeletedFalse()); + specList.add(SoftwareModuleSpecification.fetchType()); - Specification spec = SoftwareModuleSpecification.isDeletedFalse(); - specList.add(spec); - - spec = (root, query, cb) -> { - if (!query.getResultType().isAssignableFrom(Long.class)) { - root.fetch(JpaSoftwareModule_.type); - } - return cb.conjunction(); - }; - - specList.add(spec); - - return convertSmPage(findByCriteriaAPI(pageable, specList), pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList); } @Override public long count() { final Specification spec = SoftwareModuleSpecification.isDeletedFalse(); - return countSwModuleByCriteriaAPI(Arrays.asList(spec)); + return JpaManagementHelper.countBySpec(softwareModuleRepository, Collections.singletonList(spec)); } @Override @@ -306,7 +270,8 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleFields.class, virtualPropertyReplacer, database); - return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(softwareModuleRepository, pageable, + Collections.singletonList(spec)); } @Override @@ -318,34 +283,28 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Override public Slice findByTextAndType(final Pageable pageable, final String searchText, final Long typeId) { - final List> specList = new ArrayList<>(4); - - Specification spec = SoftwareModuleSpecification.isDeletedFalse(); - specList.add(spec); + specList.add(SoftwareModuleSpecification.isDeletedFalse()); if (!StringUtils.isEmpty(searchText)) { - spec = SoftwareModuleSpecification.likeNameOrVersion(searchText); - specList.add(spec); + specList.add(buildSmSearchQuerySpec(searchText)); } if (null != typeId) { throwExceptionIfSoftwareModuleTypeDoesNotExist(typeId); - - spec = SoftwareModuleSpecification.equalType(typeId); - specList.add(spec); + specList.add(SoftwareModuleSpecification.equalType(typeId)); } - spec = (root, query, cb) -> { - if (!query.getResultType().isAssignableFrom(Long.class)) { - root.fetch(JpaSoftwareModule_.type); - } - return cb.conjunction(); - }; + specList.add(SoftwareModuleSpecification.fetchType()); - specList.add(spec); + return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList); + } - return convertSmPage(findByCriteriaAPI(pageable, specList), pageable); + private Specification buildSmSearchQuerySpec(final String searchText) { + final String[] smFilterNameAndVersionEntries = JpaManagementHelper + .getFilterNameAndVersionEntries(searchText.trim()); + return SoftwareModuleSpecification.likeNameAndVersion(smFilterNameAndVersionEntries[0], + smFilterNameAndVersionEntries[1]); } @Override @@ -392,8 +351,9 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { private List> buildSpecificationList(final String searchText, final Long typeId) { final List> specList = Lists.newArrayListWithExpectedSize(3); if (!StringUtils.isEmpty(searchText)) { - specList.add(SoftwareModuleSpecification.likeNameOrVersion(searchText)); + specList.add(buildSmSearchQuerySpec(searchText)); } + if (typeId != null) { throwExceptionIfSoftwareModuleTypeDoesNotExist(typeId); @@ -413,15 +373,13 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Override public long countByTextAndType(final String searchText, final Long typeId) { - final List> specList = new ArrayList<>(3); Specification spec = SoftwareModuleSpecification.isDeletedFalse(); specList.add(spec); if (!StringUtils.isEmpty(searchText)) { - spec = SoftwareModuleSpecification.likeNameOrVersion(searchText); - specList.add(spec); + specList.add(buildSmSearchQuerySpec(searchText)); } if (null != typeId) { @@ -431,7 +389,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { specList.add(spec); } - return countSwModuleByCriteriaAPI(specList); + return JpaManagementHelper.countBySpec(softwareModuleRepository, specList); } @Override @@ -506,7 +464,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { private static Stream createJpaMetadataCreateStream( final Collection create) { - return create.stream().map(c -> (JpaSoftwareModuleMetadataCreate) c); + return create.stream().map(JpaSoftwareModuleMetadataCreate.class::cast); } private SoftwareModuleMetadata saveMetadata(final JpaSoftwareModuleMetadataCreate create) { @@ -522,7 +480,8 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { } private void assertSoftwareModuleExists(final Long moduleId) { - touch(moduleId); + JpaManagementHelper.touch(entityManager, softwareModuleRepository, (JpaSoftwareModule) get(moduleId) + .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, moduleId))); } /** @@ -555,38 +514,11 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { update.getValue().ifPresent(metadata::setValue); update.isTargetVisible().ifPresent(metadata::setTargetVisible); - touch(metadata.getSoftwareModule()); + JpaManagementHelper.touch(entityManager, softwareModuleRepository, + (JpaSoftwareModule) metadata.getSoftwareModule()); return softwareModuleMetadataRepository.save(metadata); } - /** - * Method to get the latest module based on ID after the metadata changes - * for that module. - * - * @param latestModule - * module to touch - */ - private JpaSoftwareModule touch(final SoftwareModule latestModule) { - // merge base distribution set so optLockRevision gets updated and audit - // log written because modifying metadata is modifying the base - // distribution set itself for auditing purposes. - final JpaSoftwareModule result = entityManager.merge((JpaSoftwareModule) latestModule); - result.setLastModifiedAt(0L); - - return result; - } - - /** - * Method to get the latest module based on ID after the metadata changes - * for that module. - * - * @param moduleId - * of the module to touch - */ - private JpaSoftwareModule touch(final Long moduleId) { - return touch(get(moduleId).orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, moduleId))); - } - @Override @Transactional @Retryable(include = { @@ -595,7 +527,8 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId(moduleId, key).orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, moduleId, key)); - touch(metadata.getSoftwareModule()); + JpaManagementHelper.touch(entityManager, softwareModuleRepository, + (JpaSoftwareModule) metadata.getSoftwareModule()); softwareModuleMetadataRepository.deleteById(metadata.getId()); } @@ -608,35 +541,32 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Override public Page findMetaDataByRsql(final Pageable pageable, final long softwareModuleId, final String rsqlParam) { - throwExceptionIfSoftwareModuleDoesNotExist(softwareModuleId); - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, - SoftwareModuleMetadataFields.class, virtualPropertyReplacer, database); - return convertSmMdPage( - softwareModuleMetadataRepository - .findAll( - (root, query, cb) -> cb.and( - cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule) - .get(JpaSoftwareModule_.id), softwareModuleId), - spec.toPredicate(root, query, cb)), - pageable), - pageable); + final List> specList = Arrays + .asList(RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleMetadataFields.class, + virtualPropertyReplacer, database), bySmIdSpec(softwareModuleId)); + return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, pageable, specList); } - private static Page convertMdPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); + private static Specification bySmIdSpec(final long smId) { + return (root, query, cb) -> cb + .equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), smId); } @Override public Page findMetaDataBySoftwareModuleId(final Pageable pageable, final long swId) { throwExceptionIfSoftwareModuleDoesNotExist(swId); - return convertMdPage(softwareModuleMetadataRepository.findAll( - (Specification) (root, query, cb) -> cb - .equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), swId), - pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, pageable, + Collections.singletonList(bySmIdSpec(swId))); + } + + @Override + public long countMetaDataBySoftwareModuleId(final long moduleId) { + throwExceptionIfSoftwareModuleDoesNotExist(moduleId); + + return softwareModuleMetadataRepository.countBySoftwareModuleId(moduleId); } @Override @@ -644,7 +574,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { throwExceptionIfSoftwareModuleDoesNotExist(moduleId); return softwareModuleMetadataRepository.findById(new SwMetadataCompositeKey(moduleId, key)) - .map(smmd -> (SoftwareModuleMetadata) smmd); + .map(SoftwareModuleMetadata.class::cast); } private static void throwMetadataKeyAlreadyExists(final String metadataKey) { @@ -669,7 +599,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { final long moduleId) { throwExceptionIfSoftwareModuleDoesNotExist(moduleId); - return convertMdPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible( + return JpaManagementHelper.convertPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible( PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT), moduleId, true), pageable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleTypeManagement.java index 1371ab4be..d1eb97be0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleTypeManagement.java @@ -29,10 +29,8 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; -import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; @@ -60,8 +58,7 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage public JpaSoftwareModuleTypeManagement(final DistributionSetTypeRepository distributionSetTypeRepository, final SoftwareModuleTypeRepository softwareModuleTypeRepository, final VirtualPropertyReplacer virtualPropertyReplacer, - final SoftwareModuleRepository softwareModuleRepository, - final Database database) { + final SoftwareModuleRepository softwareModuleRepository, final Database database) { this.distributionSetTypeRepository = distributionSetTypeRepository; this.softwareModuleTypeRepository = softwareModuleTypeRepository; this.virtualPropertyReplacer = virtualPropertyReplacer; @@ -87,18 +84,16 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { - - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleTypeFields.class, - virtualPropertyReplacer, database); - - return convertPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(softwareModuleTypeRepository, pageable, + Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleTypeFields.class, + virtualPropertyReplacer, database))); } @Override public Slice findAll(final Pageable pageable) { - return convertPage(softwareModuleTypeRepository.findAllWithoutCount( - (targetRoot, query, cb) -> cb.equal(targetRoot. get(JpaSoftwareModuleType_.deleted), false), - pageable), pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleTypeRepository, pageable, + Collections.singletonList( + (smTypeRoot, query, cb) -> cb.equal(smTypeRoot.get(JpaSoftwareModuleType_.deleted), false))); } @Override @@ -151,16 +146,6 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage return creates.stream().map(this::create).collect(Collectors.toList()); } - private static Page convertPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - private static Slice convertPage(final Slice findAll, - final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0); - } - @Override @Transactional @Retryable(include = { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java index 9620274a0..a21692913 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java @@ -8,11 +8,12 @@ */ package org.eclipse.hawkbit.repository.jpa; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; +import javax.validation.constraints.NotNull; + import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.TargetFields; @@ -32,7 +33,6 @@ import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; -import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper; @@ -47,14 +47,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; @@ -137,8 +136,8 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme } @Override - public Page findAll(final Pageable pageable) { - return convertPage(targetFilterQueryRepository.findAll(pageable), pageable); + public Slice findAll(final Pageable pageable) { + return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, null); } @Override @@ -151,70 +150,73 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme return targetFilterQueryRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId); } - private static Page convertPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); + @Override + public Slice findByName(final Pageable pageable, final String name) { + if (StringUtils.isEmpty(name)) { + return findAll(pageable); + } + + return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, + Collections.singletonList(TargetFilterQuerySpecification.likeName(name))); } @Override - public Page findByName(final Pageable pageable, final String name) { - List> specList = Collections.emptyList(); - if (!StringUtils.isEmpty(name)) { - specList = Collections.singletonList(TargetFilterQuerySpecification.likeName(name)); + public long countByName(final String name) { + if (StringUtils.isEmpty(name)) { + return count(); } - return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable); + + return JpaManagementHelper.countBySpec(targetFilterQueryRepository, + Collections.singletonList(TargetFilterQuerySpecification.likeName(name))); } @Override public Page findByRsql(final Pageable pageable, final String rsqlFilter) { - List> specList = Collections.emptyList(); - if (!StringUtils.isEmpty(rsqlFilter)) { - specList = Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlFilter, - TargetFilterQueryFields.class, virtualPropertyReplacer, database)); - } - return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable); + final List> specList = !StringUtils.isEmpty(rsqlFilter) + ? Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlFilter, + TargetFilterQueryFields.class, virtualPropertyReplacer, database)) + : Collections.emptyList(); + + return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, pageable, specList); } @Override - public Page findByQuery(final Pageable pageable, final String query) { - List> specList = Collections.emptyList(); - if (!StringUtils.isEmpty(query)) { - specList = Collections.singletonList(TargetFilterQuerySpecification.equalsQuery(query)); - } - return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable); + public Slice findByQuery(final Pageable pageable, final String query) { + final List> specList = !StringUtils.isEmpty(query) + ? Collections.singletonList(TargetFilterQuerySpecification.equalsQuery(query)) + : Collections.emptyList(); + + return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, specList); + } + + @Override + public Slice findByAutoAssignDistributionSetId(@NotNull final Pageable pageable, + final long setId) { + final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId); + + return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, + Collections.singletonList(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet))); } @Override public Page findByAutoAssignDSAndRsql(final Pageable pageable, final long setId, final String rsqlFilter) { - final List> specList = Lists.newArrayListWithExpectedSize(2); - final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId); + final List> specList = Lists.newArrayListWithExpectedSize(2); specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet)); - if (!StringUtils.isEmpty(rsqlFilter)) { specList.add(RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer, database)); } - return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable); + + return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, pageable, specList); } @Override - public Page findWithAutoAssignDS(final Pageable pageable) { - final List> specList = Collections - .singletonList(TargetFilterQuerySpecification.withAutoAssignDS()); - return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable); - } - - private Page findTargetFilterQueryByCriteriaAPI(final Pageable pageable, - final List> specList) { - if (CollectionUtils.isEmpty(specList)) { - return targetFilterQueryRepository.findAll(pageable); - } - - final Specification specs = SpecificationsBuilder.combineWithAnd(specList); - return targetFilterQueryRepository.findAll(specs, pageable); + public Slice findWithAutoAssignDS(final Pageable pageable) { + return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, + Collections.singletonList(TargetFilterQuerySpecification.withAutoAssignDS())); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java index 9efdb6fab..642bc5eec 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java @@ -8,9 +8,6 @@ */ package org.eclipse.hawkbit.repository.jpa; -import static org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications.orderedByLinkedDistributionSet; - -import com.google.common.collect.Lists; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; @@ -21,11 +18,14 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; + import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.MapJoin; import javax.persistence.criteria.Root; +import javax.validation.constraints.NotEmpty; + import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; @@ -53,7 +53,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.jpa.model.TargetMetadataCompositeKey; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; -import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -73,7 +72,6 @@ import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; @@ -82,10 +80,11 @@ import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; +import com.google.common.collect.Lists; + /** * JPA implementation of {@link TargetManagement}. * @@ -185,7 +184,7 @@ public class JpaTargetManagement implements TargetManagement { assertMetaDataQuota(target.getId(), md.size()); - final JpaTarget updatedTarget = touch(target); + final JpaTarget updatedTarget = JpaManagementHelper.touch(entityManager, targetRepository, target); final List createdMetadata = Collections.unmodifiableList(md.stream() .map(meta -> targetMetadataRepository @@ -212,21 +211,6 @@ public class JpaTargetManagement implements TargetManagement { TargetMetadata.class, Target.class, targetMetadataRepository::countByTargetId); } - private JpaTarget touch(final JpaTarget target) { - - // merge base target so optLockRevision gets updated and audit - // log written because modifying metadata is modifying the base - // target itself for auditing purposes. - final JpaTarget result = entityManager.merge(target); - result.setLastModifiedAt(0L); - - return targetRepository.save(result); - } - - private JpaTarget touch(final String controllerId) { - return touch(getByControllerIdAndThrowIfNotFound(controllerId)); - } - @Override @Transactional @Retryable(include = { @@ -240,7 +224,8 @@ public class JpaTargetManagement implements TargetManagement { updatedMetadata.setValue(md.getValue()); // touch it to update the lock revision because we are modifying the // target indirectly - final JpaTarget target = touch(controllerId); + final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository, + getByControllerIdAndThrowIfNotFound(controllerId)); final JpaTargetMetadata matadata = targetMetadataRepository.save(updatedMetadata); // target update event is set to ignore "lastModifiedAt" field so it is // not send automatically within the touch() method @@ -257,7 +242,8 @@ public class JpaTargetManagement implements TargetManagement { final JpaTargetMetadata metadata = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, key) .orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, controllerId, key)); - final JpaTarget target = touch(controllerId); + final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository, + getByControllerIdAndThrowIfNotFound(controllerId)); targetMetadataRepository.deleteById(metadata.getId()); // target update event is set to ignore "lastModifiedAt" field so it is // not send automatically within the touch() method @@ -269,32 +255,32 @@ public class JpaTargetManagement implements TargetManagement { public Page findMetaDataByControllerId(final Pageable pageable, final String controllerId) { final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); - return convertMdPage( - targetMetadataRepository - .findAll( - (Specification) (root, query, cb) -> cb - .equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId), - pageable), - pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable, + Collections.singletonList(metadataByTargetIdSpec(targetId))); } - private static Page convertMdPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); + private Specification metadataByTargetIdSpec(final Long targetId) { + return (root, query, cb) -> cb.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId); + } + + @Override + public long countMetaDataByControllerId(@NotEmpty final String controllerId) { + final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); + + return JpaManagementHelper.countBySpec(targetMetadataRepository, + Collections.singletonList(metadataByTargetIdSpec(targetId))); } @Override public Page findMetaDataByControllerIdAndRsql(final Pageable pageable, final String controllerId, final String rsqlParam) { - final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, - TargetMetadataFields.class, virtualPropertyReplacer, database); + final List> specList = Arrays.asList(RSQLUtility + .buildRsqlSpecification(rsqlParam, TargetMetadataFields.class, virtualPropertyReplacer, database), + metadataByTargetIdSpec(targetId)); - return convertMdPage(targetMetadataRepository.findAll((Specification) (root, query, cb) -> cb - .and(cb.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId), - spec.toPredicate(root, query, cb)), - pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable, specList); } @Override @@ -306,7 +292,7 @@ public class JpaTargetManagement implements TargetManagement { @Override public Slice findAll(final Pageable pageable) { - return convertPage(targetRepository.findAllWithoutCount(pageable), pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, null); } @Override @@ -314,18 +300,16 @@ public class JpaTargetManagement implements TargetManagement { final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId) .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); - return findTargetsBySpec(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), TargetFields.class, - virtualPropertyReplacer, database), pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, + Collections.singletonList(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), + TargetFields.class, virtualPropertyReplacer, database))); } @Override - public Page findByRsql(final Pageable pageable, final String targetFilterQuery) { - return findTargetsBySpec(RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer, database), pageable); - } - - private Page findTargetsBySpec(final Specification spec, final Pageable pageable) { - return convertPage(targetRepository.findAll(spec, pageable), pageable); + public Slice findByRsql(final Pageable pageable, final String targetFilterQuery) { + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, + Collections.singletonList(RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, + virtualPropertyReplacer, database))); } @Override @@ -385,8 +369,8 @@ public class JpaTargetManagement implements TargetManagement { public Page findByAssignedDistributionSet(final Pageable pageReq, final long distributionSetID) { final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID); - return convertPage(targetRepository - .findAll(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()), pageReq), pageReq); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, + Collections.singletonList(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()))); } @Override @@ -394,31 +378,19 @@ public class JpaTargetManagement implements TargetManagement { final String rsqlParam) { final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID); - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, - virtualPropertyReplacer, database); + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), + TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())); - return convertPage( - targetRepository - .findAll((Specification) (root, query, - cb) -> cb.and(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()) - .toPredicate(root, query, cb), spec.toPredicate(root, query, cb)), - pageReq), - pageReq); - } - - public static Page convertPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - private static Slice convertPage(final Slice findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, specList); } @Override public Page findByInstalledDistributionSet(final Pageable pageReq, final long distributionSetID) { final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID); - return convertPage(targetRepository - .findAll(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()), pageReq), pageReq); + + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, + Collections.singletonList(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()))); } @Override @@ -426,34 +398,29 @@ public class JpaTargetManagement implements TargetManagement { final String rsqlParam) { final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, - virtualPropertyReplacer, database); + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), + TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())); - return convertPage( - targetRepository - .findAll((Specification) (root, query, - cb) -> cb.and(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()) - .toPredicate(root, query, cb), spec.toPredicate(root, query, cb)), - pageable), - pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList); } @Override public Page findByUpdateStatus(final Pageable pageable, final TargetUpdateStatus status) { - return convertPage(targetRepository.findAll(TargetSpecifications.hasTargetUpdateStatus(status), pageable), - pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, + Collections.singletonList(TargetSpecifications.hasTargetUpdateStatus(status))); } @Override public Slice findByFilters(final Pageable pageable, final FilterParams filterParams) { final List> specList = buildSpecificationList(filterParams); - return findByCriteriaAPI(pageable, specList); + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, specList); } @Override - public long countByFilters(Collection status, Boolean overdueState, String searchText, - Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, - String... tagNames) { + public long countByFilters(final Collection status, final Boolean overdueState, + final String searchText, final Long installedOrAssignedDistributionSetId, + final Boolean selectTargetWithNoTag, final String... tagNames) { return countByFilters(new FilterParams(status, overdueState, searchText, installedOrAssignedDistributionSetId, selectTargetWithNoTag, tagNames)); } @@ -461,7 +428,7 @@ public class JpaTargetManagement implements TargetManagement { @Override public long countByFilters(final FilterParams filterParams) { final List> specList = buildSpecificationList(filterParams); - return countByCriteriaAPI(specList); + return JpaManagementHelper.countBySpec(targetRepository, specList); } private List> buildSpecificationList(final FilterParams filterParams) { @@ -479,8 +446,7 @@ public class JpaTargetManagement implements TargetManagement { specList.add(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId())); } if (!StringUtils.isEmpty(filterParams.getFilterBySearchText())) { - specList.add(TargetSpecifications - .likeIdOrNameOrDescriptionOrAttributeValue(filterParams.getFilterBySearchText())); + specList.add(TargetSpecifications.likeControllerIdOrName(filterParams.getFilterBySearchText())); } if (hasTagsFilterActive(filterParams)) { specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(), @@ -512,23 +478,6 @@ public class JpaTargetManagement implements TargetManagement { return Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTargetType()); } - private Slice findByCriteriaAPI(final Pageable pageable, final List> specList) { - if (CollectionUtils.isEmpty(specList)) { - return convertPage(targetRepository.findAllWithoutCount(pageable), pageable); - } - return convertPage( - targetRepository.findAllWithoutCount(SpecificationsBuilder.combineWithAnd(specList), pageable), - pageable); - } - - private Long countByCriteriaAPI(final List> specList) { - if (CollectionUtils.isEmpty(specList)) { - return targetRepository.count(); - } - - return targetRepository.count(SpecificationsBuilder.combineWithAnd(specList)); - } - @Override @Transactional @Retryable(include = { @@ -585,8 +534,8 @@ public class JpaTargetManagement implements TargetManagement { targetsWithoutSameType.forEach(target -> target.setTargetType(type)); final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(), - Collections - .unmodifiableList(targetsWithoutSameType.stream().map(targetRepository::save).collect(Collectors.toList())), + Collections.unmodifiableList( + targetsWithoutSameType.stream().map(targetRepository::save).collect(Collectors.toList())), Collections.emptyList(), type); // no reason to persist the type @@ -613,8 +562,8 @@ public class JpaTargetManagement implements TargetManagement { .unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList())), null); } - private List findTargetsByInSpecification(Collection controllerIds, - Specification specification) { + private List findTargetsByInSpecification(final Collection controllerIds, + final Specification specification) { return Lists.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream() .map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification))) .flatMap(List::stream).collect(Collectors.toList()); @@ -690,30 +639,14 @@ public class JpaTargetManagement implements TargetManagement { @Override public Slice findByFilterOrderByLinkedDistributionSet(final Pageable pageable, final long orderByDistributionId, final FilterParams filterParams) { - Specification orderedFilterSpec = combineFiltersAndDsOrder(orderByDistributionId, filterParams); // remove default sort from pageable to not overwrite sorted spec final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(), pageable.getPageSize(), Sort.unsorted()); - return convertPage(targetRepository.findAllWithoutCount(orderedFilterSpec, unsortedPage), unsortedPage); - } - /** - * Applies orderedByLinkedDistributionSet spec for order and adds additional - * specs based on filters - * - * @param orderByDistributionId - * distribution set used for order - * @param filterParams - * filters to generate additional specs for - * @return specification combining order and filter specs - */ - private Specification combineFiltersAndDsOrder(final long orderByDistributionId, - final FilterParams filterParams) { - Specification orderedFilterSpec = orderedByLinkedDistributionSet(orderByDistributionId); - for (Specification spec : buildSpecificationList(filterParams)) { - orderedFilterSpec = orderedFilterSpec.and(spec); - } - return orderedFilterSpec; + final List> specList = buildSpecificationList(filterParams); + specList.add(TargetSpecifications.orderedByLinkedDistributionSet(orderByDistributionId)); + + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, unsortedPage, specList); } @Override @@ -739,55 +672,52 @@ public class JpaTargetManagement implements TargetManagement { } @Override - public Page findByTargetFilterQueryAndNonDSAndCompatible(final Pageable pageRequest, + public Slice findByTargetFilterQueryAndNonDSAndCompatible(final Pageable pageRequest, final long distributionSetId, final String targetFilterQuery) { final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId); final Long distSetTypeId = jpaDistributionSet.getType().getId(); - final Specification spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer, database); - final Specification dsNotInActions = TargetSpecifications - .hasNotDistributionSetInActions(distributionSetId); - final Specification isCompatibleWithDsType = TargetSpecifications - .isCompatibleWithDistributionSetType(distSetTypeId); + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, + database), + TargetSpecifications.hasNotDistributionSetInActions(distributionSetId), + TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId)); - return findTargetsBySpec(spec.and(dsNotInActions).and(isCompatibleWithDsType), pageRequest); + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest, specList); } @Override - public Page findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(final Pageable pageRequest, + public Slice findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(final Pageable pageRequest, final Collection groups, final String targetFilterQuery, final DistributionSetType dsType) { + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, + database), + TargetSpecifications.isNotInRolloutGroups(groups), + TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId())); - final Specification spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer, database); - final Specification notInRolloutGroups = TargetSpecifications.isNotInRolloutGroups(groups); - final Specification isCompatibleWithDsType = TargetSpecifications - .isCompatibleWithDistributionSetType(dsType.getId()); - - return findTargetsBySpec((spec.and(notInRolloutGroups).and(isCompatibleWithDsType)), pageRequest); + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest, specList); } @Override - public Page findByInRolloutGroupWithoutAction(final Pageable pageRequest, final long group) { + public Slice findByInRolloutGroupWithoutAction(final Pageable pageRequest, final long group) { if (!rolloutGroupRepository.existsById(group)) { throw new EntityNotFoundException(RolloutGroup.class, group); } - return findTargetsBySpec( - (root, cq, cb) -> TargetSpecifications.hasNoActionInRolloutGroup(group).toPredicate(root, cq, cb), - pageRequest); + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest, + Collections.singletonList(TargetSpecifications.hasNoActionInRolloutGroup(group))); } @Override public long countByRsqlAndNotInRolloutGroupsAndCompatible(final Collection groups, final String targetFilterQuery, final DistributionSetType dsType) { - final Specification spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer, database); - final List> specList = Arrays.asList(spec, + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, + database), TargetSpecifications.isNotInRolloutGroups(groups), TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId())); - return countByCriteriaAPI(specList); + return JpaManagementHelper.countBySpec(targetRepository, specList); } @Override @@ -795,13 +725,13 @@ public class JpaTargetManagement implements TargetManagement { final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId); final Long distSetTypeId = jpaDistributionSet.getType().getId(); - final Specification spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer, database); - final List> specList = Arrays.asList(spec, + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, + database), TargetSpecifications.hasNotDistributionSetInActions(distributionSetId), TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId)); - return countByCriteriaAPI(specList); + return JpaManagementHelper.countBySpec(targetRepository, specList); } @Override @@ -825,7 +755,8 @@ public class JpaTargetManagement implements TargetManagement { public Page findByTag(final Pageable pageable, final long tagId) { throwEntityNotFoundExceptionIfTagDoesNotExist(tagId); - return convertPage(targetRepository.findAll(TargetSpecifications.hasTag(tagId), pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, + Collections.singletonList(TargetSpecifications.hasTag(tagId))); } private void throwEntityNotFoundExceptionIfTagDoesNotExist(final Long tagId) { @@ -836,15 +767,13 @@ public class JpaTargetManagement implements TargetManagement { @Override public Page findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) { - throwEntityNotFoundExceptionIfTagDoesNotExist(tagId); - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, - virtualPropertyReplacer, database); + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), + TargetSpecifications.hasTag(tagId)); - return convertPage(targetRepository.findAll((Specification) (root, query, cb) -> cb.and( - TargetSpecifications.hasTag(tagId).toPredicate(root, query, cb), spec.toPredicate(root, query, cb)), - pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList); } @Override @@ -852,23 +781,22 @@ public class JpaTargetManagement implements TargetManagement { final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId) .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); - final Specification specs = RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), - TargetFields.class, virtualPropertyReplacer, database); - return targetRepository.count(specs); + return countByRsql(targetFilterQuery.getQuery()); } @Override public long countByRsql(final String targetFilterQuery) { - final Specification specs = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer, database); - return targetRepository.count(specs); + return JpaManagementHelper.countBySpec(targetRepository, Collections.singletonList(RSQLUtility + .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database))); } @Override public long countByRsqlAndCompatible(final String targetFilterQuery, final Long dsTypeId) { - final Specification rsqlSpec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, - TargetFields.class, virtualPropertyReplacer, database); - return targetRepository.count(rsqlSpec.and(TargetSpecifications.isCompatibleWithDistributionSetType(dsTypeId))); + final List> specList = Arrays.asList(RSQLUtility + .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database), + TargetSpecifications.isCompatibleWithDistributionSetType(dsTypeId)); + + return JpaManagementHelper.countBySpec(targetRepository, specList); } @Override @@ -925,8 +853,8 @@ public class JpaTargetManagement implements TargetManagement { @Override public Page findByControllerAttributesRequested(final Pageable pageReq) { - return convertPage(targetRepository.findAll(TargetSpecifications.hasRequestControllerAttributesTrue(), pageReq), - pageReq); + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, + Collections.singletonList(TargetSpecifications.hasRequestControllerAttributesTrue())); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java index 67dd3eb83..cfa16dd19 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java @@ -31,9 +31,7 @@ import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; @@ -106,14 +104,8 @@ public class JpaTargetTagManagement implements TargetTagManagement { @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { - - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class, virtualPropertyReplacer, - database); - return convertTPage(targetTagRepository.findAll(spec, pageable), pageable); - } - - private static Page convertTPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); + return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, Collections.singletonList( + RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class, virtualPropertyReplacer, database))); } @Override @@ -140,7 +132,7 @@ public class JpaTargetTagManagement implements TargetTagManagement { @Override public Optional get(final long id) { - return targetTagRepository.findById(id).map(tt -> (TargetTag) tt); + return targetTagRepository.findById(id).map(TargetTag.class::cast); } @Override @@ -150,7 +142,7 @@ public class JpaTargetTagManagement implements TargetTagManagement { @Override public Page findAll(final Pageable pageable) { - return convertTPage(targetTagRepository.findAll(pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, null); } @Override @@ -159,6 +151,7 @@ public class JpaTargetTagManagement implements TargetTagManagement { throw new EntityNotFoundException(Target.class, controllerId); } - return convertTPage(targetTagRepository.findAll(TagSpecification.ofTarget(controllerId), pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, + Collections.singletonList(TagSpecification.ofTarget(controllerId))); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTypeManagement.java index 5f6083a3a..f2fe37ecb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTypeManagement.java @@ -8,6 +8,12 @@ */ package org.eclipse.hawkbit.repository.jpa; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.TargetTypeFields; import org.eclipse.hawkbit.repository.TargetTypeManagement; @@ -29,21 +35,14 @@ import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.domain.Slice; import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - /** * JPA implementation of {@link TargetTypeManagement}. * @@ -95,6 +94,11 @@ public class JpaTargetTypeManagement implements TargetTypeManagement { return targetTypeRepository.count(); } + @Override + public long countByName(final String name) { + return targetTypeRepository.countByName(name); + } + @Override @Transactional @Retryable(include = { @@ -127,21 +131,21 @@ public class JpaTargetTypeManagement implements TargetTypeManagement { } @Override - public Page findAll(final Pageable pageable) { - return convertPage(targetTypeRepository.findAll(pageable), pageable); + public Slice findAll(final Pageable pageable) { + return JpaManagementHelper.findAllWithoutCountBySpec(targetTypeRepository, pageable, null); } @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetTypeFields.class, - virtualPropertyReplacer, database); - - return convertPage(targetTypeRepository.findAll(spec, pageable), pageable); + return JpaManagementHelper.findAllWithCountBySpec(targetTypeRepository, pageable, + Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlParam, TargetTypeFields.class, + virtualPropertyReplacer, database))); } @Override - public Page findByName(Pageable pageable, String name) { - return convertPage(targetTypeRepository.findAll(TargetTypeSpecification.likeName(name), pageable), pageable); + public Slice findByName(final Pageable pageable, final String name) { + return JpaManagementHelper.findAllWithoutCountBySpec(targetTypeRepository, pageable, + Collections.singletonList(TargetTypeSpecification.likeName(name))); } @Override @@ -258,9 +262,4 @@ public class JpaTargetTypeManagement implements TargetTypeManagement { QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxDistributionSetTypesPerTargetType(), DistributionSetType.class, TargetType.class, targetTypeRepository::countDsSetTypesById); } - - private static Page convertPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); - } - } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetTypeRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetTypeRepository.java index c23936155..2aaf90eb0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetTypeRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetTypeRepository.java @@ -8,6 +8,12 @@ */ package org.eclipse.hawkbit.repository.jpa; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType; import org.eclipse.hawkbit.repository.jpa.specifications.TargetTypeSpecification; import org.eclipse.hawkbit.repository.model.TargetType; @@ -23,12 +29,6 @@ import org.springframework.data.repository.query.Param; import org.springframework.lang.NonNull; import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - /** * {@link PagingAndSortingRepository} for {@link JpaTargetType}. * @@ -42,23 +42,24 @@ public interface TargetTypeRepository * * Calls version based on spec to allow injecting further specs * - * @param id id to filter for + * @param id + * id to filter for * @return {@link Optional} of {@link TargetType} */ @Override @NonNull - default Optional findById(@NonNull Long id) { + default Optional findById(@NonNull final Long id) { return this.findOne(Specification.where(TargetTypeSpecification.hasId(id))); } /** * @param ids - * List of ID + * List of ID * @return Target type list */ @Override @NonNull - default List findAllById(Iterable ids) { + default List findAllById(final Iterable ids) { final List collectedIds = StreamSupport.stream(ids.spliterator(), true).collect(Collectors.toList()); return this.findAll(Specification.where(TargetTypeSpecification.hasIdIn(collectedIds))); } @@ -92,12 +93,13 @@ public interface TargetTypeRepository * * Calls version with (empty) spec to allow injecting further specs * - * @param sort instructions to sort result by + * @param sort + * instructions to sort result by * @return {@link List} of {@link TargetType}s */ @Override @NonNull - default Iterable findAll(@NonNull Sort sort) { + default Iterable findAll(@NonNull final Sort sort) { return this.findAll(Specification.where(null), sort); } @@ -106,35 +108,40 @@ public interface TargetTypeRepository * * Calls version with (empty) spec to allow injecting further specs * - * @param pageable paging context + * @param pageable + * paging context * @return {@link List} of {@link TargetType}s */ @Override @NonNull - default Page findAll(@NonNull Pageable pageable) { + default Page findAll(@NonNull final Pageable pageable) { return this.findAll(Specification.where(null), pageable); } /** - * Checks whether {@link TargetType} in the repository matching an id exists or not. + * Checks whether {@link TargetType} in the repository matching an id exists + * or not. * * Calls version based on spec to allow injecting further specs * - * @param id id to check for + * @param id + * id to check for * @return true if TargetType with id exists */ @Override - default boolean existsById(@NonNull Long id) { + default boolean existsById(@NonNull final Long id) { return this.exists(TargetTypeSpecification.hasId(id)); } /** - * Checks whether {@link TargetType} in the repository matching a spec exists or not. + * Checks whether {@link TargetType} in the repository matching a spec + * exists or not. * - * @param spec to check for existence + * @param spec + * to check for existence * @return true if target with id exists */ - default boolean exists(@NonNull Specification spec) { + default boolean exists(@NonNull final Specification spec) { return this.count(spec) > 0; } @@ -152,7 +159,7 @@ public interface TargetTypeRepository /** * @param tenant - * Tenant + * Tenant */ @Modifying @Transactional @@ -169,7 +176,7 @@ public interface TargetTypeRepository * @return all {@link TargetType}s in the repository with given * {@link TargetType#getName()} */ - default List findByDsType(@Param("id") Long dsTypeId) { + default List findByDsType(@Param("id") final Long dsTypeId) { return this.findAll(Specification.where(TargetTypeSpecification.hasDsSetType(dsTypeId))); } @@ -180,7 +187,18 @@ public interface TargetTypeRepository * @return all {@link TargetType}s in the repository with given * {@link TargetType#getName()} */ - default Optional findByName(String name){ + default Optional findByName(final String name) { return this.findOne(Specification.where(TargetTypeSpecification.hasName(name))); - }; + } + + /** + * Count number of {@link TargetType}s in the repository by name. + * + * @param name + * target type name + * @return number of targetTypes in the repository by name + */ + default long countByName(final String name) { + return this.count(TargetTypeSpecification.hasName(name)); + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AbstractAutoAssignExecutor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AbstractAutoAssignExecutor.java index ee281fde8..caa7ac364 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AbstractAutoAssignExecutor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AbstractAutoAssignExecutor.java @@ -23,9 +23,9 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.tenancy.TenantAware; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Isolation; import org.springframework.util.StringUtils; @@ -38,11 +38,11 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAutoAssignExecutor.class); /** - * The message which is added to the action status when a distribution set is - * assigned to an target. First %s is the name of the target filter. + * The message which is added to the action status when a distribution set + * is assigned to an target. First %s is the name of the target filter. */ private static final String ACTION_MESSAGE = "Auto assignment by target filter: %s"; - + /** * Maximum for target filter queries with auto assign DS activated. */ @@ -94,7 +94,7 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { } protected void forEachFilterWithAutoAssignDS(final Consumer consumer) { - Page filterQueries; + Slice filterQueries; Pageable query = PageRequest.of(0, PAGE_SIZE); do { @@ -117,8 +117,8 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { } /** - * Runs target assignments within a dedicated transaction for a given list of - * controllerIDs + * Runs target assignments within a dedicated transaction for a given list + * of controllerIDs * * @param targetFilterQuery * the target filter query @@ -146,8 +146,8 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { } /** - * Creates a list of {@link DeploymentRequest} for given list of controllerIds - * and {@link TargetFilterQuery} + * Creates a list of {@link DeploymentRequest} for given list of + * controllerIds and {@link TargetFilterQuery} * * @param controllerIds * list of controllerIds diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetSpecification.java index 8a2fe163b..b645f19a4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetSpecification.java @@ -13,6 +13,7 @@ import java.util.Collection; import java.util.List; import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Expression; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.ListJoin; import javax.persistence.criteria.Path; @@ -23,12 +24,11 @@ import javax.persistence.criteria.SetJoin; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag_; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType; +import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType_; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.springframework.data.jpa.domain.Specification; import org.springframework.util.CollectionUtils; @@ -52,7 +52,7 @@ public final class DistributionSetSpecification { * @return the {@link DistributionSet} {@link Specification} */ public static Specification isDeleted(final Boolean isDeleted) { - return (targetRoot, query, cb) -> cb.equal(targetRoot. get(JpaDistributionSet_.deleted), isDeleted); + return (dsRoot, query, cb) -> cb.equal(dsRoot. get(JpaDistributionSet_.deleted), isDeleted); } @@ -66,7 +66,7 @@ public final class DistributionSetSpecification { * @return the {@link DistributionSet} {@link Specification} */ public static Specification isCompleted(final Boolean isCompleted) { - return (targetRoot, query, cb) -> cb.equal(targetRoot. get(JpaDistributionSet_.complete), isCompleted); + return (dsRoot, query, cb) -> cb.equal(dsRoot. get(JpaDistributionSet_.complete), isCompleted); } @@ -80,7 +80,7 @@ public final class DistributionSetSpecification { * @return the {@link DistributionSet} {@link Specification} */ public static Specification isValid(final Boolean isValid) { - return (targetRoot, query, cb) -> cb.equal(targetRoot. get(JpaDistributionSet_.valid), isValid); + return (dsRoot, query, cb) -> cb.equal(dsRoot. get(JpaDistributionSet_.valid), isValid); } @@ -93,10 +93,10 @@ public final class DistributionSetSpecification { * @return the {@link DistributionSet} {@link Specification} */ public static Specification byId(final Long distid) { - return (targetRoot, query, cb) -> { - final Predicate predicate = cb.equal(targetRoot. get(JpaDistributionSet_.id), distid); - targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT); - targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT); + return (dsRoot, query, cb) -> { + final Predicate predicate = cb.equal(dsRoot. get(JpaDistributionSet_.id), distid); + dsRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT); + dsRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT); query.distinct(true); return predicate; @@ -112,31 +112,16 @@ public final class DistributionSetSpecification { * @return the {@link DistributionSet} {@link Specification} */ public static Specification byIds(final Collection distids) { - return (targetRoot, query, cb) -> { - final Predicate predicate = targetRoot. get(JpaDistributionSet_.id).in(distids); - targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT); - targetRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT); - targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT); + return (dsRoot, query, cb) -> { + final Predicate predicate = dsRoot. get(JpaDistributionSet_.id).in(distids); + dsRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT); + dsRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT); + dsRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT); query.distinct(true); return predicate; }; } - /** - * {@link Specification} for retrieving {@link DistributionSet}s by "like - * name or like description or like version". - * - * @param subString - * to be filtered on - * @return the {@link DistributionSet} {@link Specification} - */ - public static Specification likeNameOrDescriptionOrVersion(final String subString) { - return (targetRoot, query, cb) -> cb.or( - cb.like(cb.lower(targetRoot. get(JpaDistributionSet_.name)), subString.toLowerCase()), - cb.like(cb.lower(targetRoot. get(JpaDistributionSet_.version)), subString.toLowerCase()), - cb.like(cb.lower(targetRoot. get(JpaDistributionSet_.description)), subString.toLowerCase())); - } - /** * {@link Specification} for retrieving {@link DistributionSet}s by "like * name and like version". @@ -148,9 +133,9 @@ public final class DistributionSetSpecification { * @return the {@link DistributionSet} {@link Specification} */ public static Specification likeNameAndVersion(final String name, final String version) { - return (targetRoot, query, cb) -> cb.and( - cb.like(cb.lower(targetRoot. get(JpaDistributionSet_.name)), name.toLowerCase()), - cb.like(cb.lower(targetRoot. get(JpaDistributionSet_.version)), version.toLowerCase())); + return (dsRoot, query, cb) -> cb.and( + cb.like(cb.lower(dsRoot. get(JpaDistributionSet_.name)), name.toLowerCase()), + cb.like(cb.lower(dsRoot. get(JpaDistributionSet_.version)), version.toLowerCase())); } /** @@ -165,16 +150,16 @@ public final class DistributionSetSpecification { */ public static Specification hasTags(final Collection tagNames, final Boolean selectDSWithNoTag) { - return (targetRoot, query, cb) -> { - final Predicate predicate = getHasTagsPredicate(targetRoot, cb, selectDSWithNoTag, tagNames); + return (dsRoot, query, cb) -> { + final Predicate predicate = getHasTagsPredicate(dsRoot, cb, selectDSWithNoTag, tagNames); query.distinct(true); return predicate; }; } - private static Predicate getHasTagsPredicate(final Root targetRoot, final CriteriaBuilder cb, + private static Predicate getHasTagsPredicate(final Root dsRoot, final CriteriaBuilder cb, final Boolean selectDSWithNoTag, final Collection tagNames) { - final SetJoin tags = targetRoot.join(JpaDistributionSet_.tags, + final SetJoin tags = dsRoot.join(JpaDistributionSet_.tags, JoinType.LEFT); final Path exp = tags.get(JpaDistributionSetTag_.name); @@ -210,9 +195,9 @@ public final class DistributionSetSpecification { */ public static Specification equalsNameAndVersionIgnoreCase(final String name, final String version) { - return (targetRoot, query, cb) -> cb.and( - cb.equal(cb.lower(targetRoot. get(JpaDistributionSet_.name)), name.toLowerCase()), - cb.equal(cb.lower(targetRoot. get(JpaDistributionSet_.version)), version.toLowerCase())); + return (dsRoot, query, cb) -> cb.and( + cb.equal(cb.lower(dsRoot. get(JpaDistributionSet_.name)), name.toLowerCase()), + cb.equal(cb.lower(dsRoot. get(JpaDistributionSet_.version)), version.toLowerCase())); } @@ -220,13 +205,13 @@ public final class DistributionSetSpecification { * {@link Specification} for retrieving {@link DistributionSet} with given * {@link DistributionSet#getType()}. * - * @param type - * to search + * @param typeId + * id of distribution set type to search * @return the {@link DistributionSet} {@link Specification} */ - public static Specification byType(final DistributionSetType type) { - return (targetRoot, query, cb) -> cb.equal(targetRoot. get(JpaDistributionSet_.type), - type); + public static Specification byType(final Long typeId) { + return (dsRoot, query, cb) -> cb.equal(dsRoot.get(JpaDistributionSet_.type).get(JpaDistributionSetType_.id), + typeId); } @@ -269,11 +254,38 @@ public final class DistributionSetSpecification { */ public static Specification hasTag(final Long tagId) { - return (targetRoot, query, cb) -> { - final SetJoin tags = targetRoot.join(JpaDistributionSet_.tags, + return (dsRoot, query, cb) -> { + final SetJoin tags = dsRoot.join(JpaDistributionSet_.tags, JoinType.LEFT); return cb.equal(tags.get(JpaDistributionSetTag_.id), tagId); }; } + /** + * Can be added to specification chain to order result by provided target + * + * Order: 1. Distribution set installed on target, 2. Distribution set(s) + * assigned to target, 3. Based on distribution set id + * + * NOTE: Other specs, pagables and sort objects may alter the queries + * orderBy entry too, possibly invalidating the applied order, keep in mind + * when using this + * + * @param linkedControllerId + * controller id to get installed/assigned DS for + * @return specification that applies order by target, may be overwritten + */ + public static Specification orderedByLinkedTarget(final String linkedControllerId) { + return (dsRoot, query, cb) -> { + final Root targetRoot = query.from(JpaTarget.class); + + final Expression assignedInstalledCase = cb.selectCase() + .when(cb.equal(targetRoot.get(JpaTarget_.installedDistributionSet), dsRoot), 1) + .when(cb.equal(targetRoot.get(JpaTarget_.assignedDistributionSet), dsRoot), 2).otherwise(3); + query.orderBy(cb.asc(assignedInstalledCase), cb.asc(dsRoot.get(JpaDistributionSet_.id))); + + return cb.equal(targetRoot.get(JpaTarget_.controllerId), linkedControllerId); + }; + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/RolloutSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/RolloutSpecification.java index 13d72b518..68b95cad9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/RolloutSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/RolloutSpecification.java @@ -45,4 +45,24 @@ public final class RolloutSpecification { } + /** + * Builds a {@link Specification} to search a rollout by name. + * + * @param searchText + * search string + * @param isDeleted + * true if deleted rollouts should be included in + * the search. Otherwise false + * @return criteria specification with a query for name of a rollout + * + */ + public static Specification likeName(final String searchText, final boolean isDeleted) { + return (rolloutRoot, query, criteriaBuilder) -> { + final String searchTextToLower = searchText.toLowerCase(); + return criteriaBuilder.and( + criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(JpaRollout_.name)), searchTextToLower), + criteriaBuilder.equal(rolloutRoot.get(JpaRollout_.deleted), isDeleted)); + }; + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SoftwareModuleSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SoftwareModuleSpecification.java index 676dd0003..10ffdd912 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SoftwareModuleSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SoftwareModuleSpecification.java @@ -37,16 +37,18 @@ public final class SoftwareModuleSpecification { /** * {@link Specification} for retrieving {@link SoftwareModule}s by "like - * name or like version". - * - * @param subString + * name and like version". + * + * @param name + * to be filtered on + * @param version * to be filtered on * @return the {@link SoftwareModule} {@link Specification} */ - public static Specification likeNameOrVersion(final String subString) { - return (targetRoot, query, cb) -> cb.or( - cb.like(cb.lower(targetRoot. get(JpaSoftwareModule_.name)), subString.toLowerCase()), - cb.like(cb.lower(targetRoot. get(JpaSoftwareModule_.version)), subString.toLowerCase())); + public static Specification likeNameAndVersion(final String name, final String version) { + return (smRoot, query, cb) -> cb.and( + cb.like(cb.lower(smRoot. get(JpaSoftwareModule_.name)), name.toLowerCase()), + cb.like(cb.lower(smRoot. get(JpaSoftwareModule_.version)), version.toLowerCase())); } /** @@ -58,8 +60,22 @@ public final class SoftwareModuleSpecification { * @return the {@link SoftwareModule} {@link Specification} */ public static Specification equalType(final Long type) { - return (targetRoot, query, cb) -> cb.equal( - targetRoot. get(JpaSoftwareModule_.type).get(JpaSoftwareModuleType_.id), type); + return (smRoot, query, cb) -> cb.equal( + smRoot. get(JpaSoftwareModule_.type).get(JpaSoftwareModuleType_.id), type); + } + + /** + * {@link Specification} for fetching {@link SoftwareModule}s type. + * + * @return the {@link SoftwareModule} {@link Specification} + */ + public static Specification fetchType() { + return (smRoot, query, cb) -> { + if (!query.getResultType().isAssignableFrom(Long.class)) { + smRoot.fetch(JpaSoftwareModule_.type); + } + return cb.conjunction(); + }; } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java index e4cdc5459..9e6397fc5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java @@ -126,8 +126,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s that have the request - * controller attributes flag set + * {@link Specification} for retrieving {@link Target}s that have the + * request controller attributes flag set * * @return the {@link Target} {@link Specification} */ @@ -154,8 +154,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s by "equal to any given - * {@link TargetUpdateStatus}". + * {@link Specification} for retrieving {@link Target}s by "equal to any + * given {@link TargetUpdateStatus}". * * @param updateStatus * to be filtered on @@ -180,8 +180,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s by "not equal to given - * {@link TargetUpdateStatus}". + * {@link Specification} for retrieving {@link Target}s by "not equal to + * given {@link TargetUpdateStatus}". * * @param updateStatus * to be filtered on @@ -194,14 +194,15 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s that are overdue. A - * target is overdue if it did not respond during the configured intervals:
+ * target is overdue if it did not respond during the configured + * intervals:
* poll_itvl + overdue_itvl * * @param overdueTimestamp * the calculated timestamp to compare with the last respond of a * target (lastTargetQuery).
- * The overdueTimestamp has to be calculated with the - * following expression:
+ * The overdueTimestamp has to be calculated with + * the following expression:
* overdueTimestamp = nowTimestamp - poll_itvl - * overdue_itvl * @@ -212,23 +213,6 @@ public final class TargetSpecifications { overdueTimestamp); } - /** - * {@link Specification} for retrieving {@link Target}s by "like controllerId or - * like name or like description". - * - * @param searchText - * to be filtered on - * @return the {@link Target} {@link Specification} - */ - public static Specification likeIdOrNameOrDescription(final String searchText) { - return (targetRoot, query, cb) -> { - final String searchTextToLower = searchText.toLowerCase(); - return cb.or(cb.like(cb.lower(targetRoot.get(JpaTarget_.controllerId)), searchTextToLower), - cb.like(cb.lower(targetRoot.get(JpaTarget_.name)), searchTextToLower), - cb.like(cb.lower(targetRoot.get(JpaTarget_.description)), searchTextToLower)); - }; - } - /** * {@link Specification} for retrieving {@link Target}s by "like attribute * value". @@ -248,19 +232,24 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s by "like controllerId or - * like name or like description or like attribute value". + * {@link Specification} for retrieving {@link Target}s by "like + * controllerId or like name". * * @param searchText * to be filtered on * @return the {@link Target} {@link Specification} */ - public static Specification likeIdOrNameOrDescriptionOrAttributeValue(final String searchText) { - return Specification.where(likeIdOrNameOrDescription(searchText)).or(likeAttributeValue(searchText)); + public static Specification likeControllerIdOrName(final String searchText) { + return (targetRoot, query, cb) -> { + final String searchTextToLower = searchText.toLowerCase(); + return cb.or(cb.like(cb.lower(targetRoot.get(JpaTarget_.controllerId)), searchTextToLower), + cb.like(cb.lower(targetRoot.get(JpaTarget_.name)), searchTextToLower)); + }; } /** - * {@link Specification} for retrieving {@link Target}s by "like controllerId". + * {@link Specification} for retrieving {@link Target}s by "like + * controllerId". * * @param distributionId * to be filtered on @@ -271,8 +260,8 @@ public final class TargetSpecifications { } /** - * Finds all targets by given {@link Target#getControllerId()}s and which are - * not yet assigned to given {@link DistributionSet}. + * Finds all targets by given {@link Target#getControllerId()}s and which + * are not yet assigned to given {@link DistributionSet}. * * @param tIDs * to search for. @@ -305,8 +294,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s by "has no tag names"or - * "has at least on of the given tag names". + * {@link Specification} for retrieving {@link Target}s by "has no tag + * names"or "has at least on of the given tag names". * * @param tagNames * to be filtered on @@ -348,8 +337,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s by assigned distribution - * set. + * {@link Specification} for retrieving {@link Target}s by assigned + * distribution set. * * @param distributionSetId * the ID of the distribution set which must be assigned @@ -380,10 +369,10 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s that are compatible with - * given {@link DistributionSetType}. Compatibility is evaluated by checking the - * {@link TargetType} of a target. Targets that don't have a {@link TargetType} - * are compatible with all {@link DistributionSetType} + * {@link Specification} for retrieving {@link Target}s that are compatible + * with given {@link DistributionSetType}. Compatibility is evaluated by + * checking the {@link TargetType} of a target. Targets that don't have a + * {@link TargetType} are compatible with all {@link DistributionSetType} * * @param distributionSetTypeId * the ID of the distribution set type which must be compatible @@ -399,15 +388,16 @@ public final class TargetSpecifications { }; } - private static Predicate getTargetTypeIsNullPredicate(Root targetRoot) { + private static Predicate getTargetTypeIsNullPredicate(final Root targetRoot) { return targetRoot.get(JpaTarget_.targetType).isNull(); } /** - * {@link Specification} for retrieving {@link Target}s that are NOT compatible - * with given {@link DistributionSetType}. Compatibility is evaluated by - * checking the {@link TargetType} of a target. Targets that don't have a - * {@link TargetType} are compatible with all {@link DistributionSetType} + * {@link Specification} for retrieving {@link Target}s that are NOT + * compatible with given {@link DistributionSetType}. Compatibility is + * evaluated by checking the {@link TargetType} of a target. Targets that + * don't have a {@link TargetType} are compatible with all + * {@link DistributionSetType} * * @param distributionSetTypeId * the ID of the distribution set type which must be incompatible @@ -456,8 +446,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s that are in an action - * for a given {@link RolloutGroup} + * {@link Specification} for retrieving {@link Target}s that are in an + * action for a given {@link RolloutGroup} * * @param group * the {@link RolloutGroup} @@ -490,8 +480,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s that have no Action of - * the {@link RolloutGroup}. + * {@link Specification} for retrieving {@link Target}s that have no Action + * of the {@link RolloutGroup}. * * @param group * the {@link RolloutGroup} @@ -512,8 +502,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s by assigned distribution - * set. + * {@link Specification} for retrieving {@link Target}s by assigned + * distribution set. * * @param distributionSetId * the ID of the distribution set which must be assigned @@ -553,7 +543,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s by target type id is equal to null + * {@link Specification} for retrieving {@link Target}s by target type id is + * equal to null * * @return the {@link Target} {@link Specification} */ @@ -562,8 +553,8 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s that don't have target - * type assigned + * {@link Specification} for retrieving {@link Target}s that don't have + * target type assigned * * @param typeId * the id of the target type @@ -576,15 +567,15 @@ public final class TargetSpecifications { } /** - * Can be added to specification chain to order result by provided distribution - * set + * Can be added to specification chain to order result by provided + * distribution set * - * Order: 1. Targets with DS installed, 2. Targets with DS assigned, 3. Based on - * target id + * Order: 1. Targets with DS installed, 2. Targets with DS assigned, 3. + * Based on target id * - * NOTE: Other specs, pagables and sort objects may alter the queries orderBy - * entry too, possibly invalidating the applied order, keep in mind when using - * this + * NOTE: Other specs, pagables and sort objects may alter the queries + * orderBy entry too, possibly invalidating the applied order, keep in mind + * when using this * * @param distributionSetIdForOrder * distribution set to consider diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_21__add_rollouts_status_index___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_21__add_rollouts_status_index___DB2.sql new file mode 100644 index 000000000..4d845ed84 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_21__add_rollouts_status_index___DB2.sql @@ -0,0 +1 @@ +CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_21__add_rollouts_status_index___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_21__add_rollouts_status_index___H2.sql new file mode 100644 index 000000000..4d845ed84 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_21__add_rollouts_status_index___H2.sql @@ -0,0 +1 @@ +CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_21__add_rollouts_status_index___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_21__add_rollouts_status_index___MYSQL.sql new file mode 100644 index 000000000..4d845ed84 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_21__add_rollouts_status_index___MYSQL.sql @@ -0,0 +1 @@ +CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_21__add_rollouts_status_index___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_21__add_rollouts_status_index___POSTGRESQL.sql new file mode 100644 index 000000000..0d4783710 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_21__add_rollouts_status_index___POSTGRESQL.sql @@ -0,0 +1,3 @@ +CREATE INDEX sp_idx_rollout_status_tenant +ON sp_rollout +USING BTREE (tenant, status); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_21__add_rollouts_status_index___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_21__add_rollouts_status_index___SQL_SERVER.sql new file mode 100644 index 000000000..4d845ed84 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_21__add_rollouts_status_index___SQL_SERVER.sql @@ -0,0 +1 @@ +CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java index 7e0987633..568e9e836 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java @@ -45,6 +45,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.DistributionSetFilter; import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder; import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation; import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType; @@ -215,9 +216,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with invalid description should not be created") - .isThrownBy(() -> distributionSetManagement.create( - entityFactory.distributionSet().create().name("a").version("a") - .description(INVALID_TEXT_HTML))); + .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") + .version("a").description(INVALID_TEXT_HTML))); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too long description should not be updated") @@ -225,8 +225,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { .description(RandomStringUtils.randomAlphanumeric(513)))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with invalid characters should not be updated") - .isThrownBy(() -> distributionSetManagement + .as("entity with invalid characters should not be updated").isThrownBy(() -> distributionSetManagement .update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML))); } @@ -253,8 +252,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with invalid characters should not be updated") - .isThrownBy(() -> distributionSetManagement + .as("entity with invalid characters should not be updated").isThrownBy(() -> distributionSetManagement .update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML))); assertThatExceptionOfType(ConstraintViolationException.class) @@ -383,7 +381,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { // add some meta data entries final DistributionSet ds3 = testdataFactory.createDistributionSet("ds3"); - final int firstHalf = Math.round(((float) maxMetaData) / 2.f); + final int firstHalf = Math.round((maxMetaData) / 2.f); for (int i = 0; i < firstHalf; ++i) { createDistributionSetMetadata(ds3.getId(), new JpaDistributionSetMetadata("k" + i, ds3, "v" + i)); } @@ -415,7 +413,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { assignedDS.stream().map(c -> (JpaDistributionSet) c) .forEach(ds -> assertThat(ds.getTags().size()).as("ds has wrong tag size").isEqualTo(1)); - DistributionSetTag findDistributionSetTag = getOrThrow(distributionSetTagManagement.getByName(TAG1_NAME)); + final DistributionSetTag findDistributionSetTag = getOrThrow(distributionSetTagManagement.getByName(TAG1_NAME)); assertThat(assignedDS.size()).as("assigned ds has wrong size") .isEqualTo(distributionSetManagement.findByTag(PAGE, tag.getId()).getNumberOfElements()); @@ -549,7 +547,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { // assign some software modules final DistributionSet ds3 = testdataFactory.createDistributionSetWithNoSoftwareModules("ds3", "1.0"); - final int firstHalf = Math.round(((float) maxModules) / 2.f); + final int firstHalf = Math.round((maxModules) / 2.f); for (int i = 0; i < firstHalf; ++i) { distributionSetManagement.assignSoftwareModules(ds3.getId(), singletonList(modules.get(i))); } @@ -566,9 +564,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs(); assertThatExceptionOfType(InvalidDistributionSetException.class) - .as("Invalid distributionSet should throw an exception") - .isThrownBy(() -> distributionSetManagement.assignSoftwareModules(distributionSet.getId(), - singletonList(softwareModule.getId()))); + .as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement + .assignSoftwareModules(distributionSet.getId(), singletonList(softwareModule.getId()))); } @Test @@ -576,10 +573,9 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { void verifyUnassignSoftwareModulesToInvalidDistributionSet() { final DistributionSet distributionSet = testdataFactory.createDistributionSet(); final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs(); - distributionSetManagement.assignSoftwareModules(distributionSet.getId(), - singletonList(softwareModule.getId())); - distributionSetInvalidationManagement.invalidateDistributionSet(new DistributionSetInvalidation( - singletonList(distributionSet.getId()), CancelationType.NONE, false)); + distributionSetManagement.assignSoftwareModules(distributionSet.getId(), singletonList(softwareModule.getId())); + distributionSetInvalidationManagement.invalidateDistributionSet( + new DistributionSetInvalidation(singletonList(distributionSet.getId()), CancelationType.NONE, false)); assertThatExceptionOfType(InvalidDistributionSetException.class) .as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement @@ -647,13 +643,12 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { assignDistributionSet(dsFour.getId(), tSecond.getControllerId()); - final DistributionSetFilterBuilder distributionSetFilterBuilder = new DistributionSetFilterBuilder() - .setIsDeleted(false).setIsComplete(true).setSelectDSWithNoTag(Boolean.FALSE); + final DistributionSetFilter distributionSetFilter = new DistributionSetFilterBuilder().setIsDeleted(false) + .setIsComplete(true).setSelectDSWithNoTag(Boolean.FALSE).build(); // target first only has an assigned DS-three so check order correct final List tFirstPin = distributionSetManagement - .findByFilterAndAssignedInstalledDsOrderedByLinkTarget(PAGE, distributionSetFilterBuilder, - tFirst.getControllerId()) + .findByDistributionSetFilterOrderByLinkedTarget(PAGE, distributionSetFilter, tFirst.getControllerId()) .getContent(); assertThat(tFirstPin.get(0)).isEqualTo(dsThree); assertThat(tFirstPin).hasSize(10); @@ -661,8 +656,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { // target second has installed DS-2 and assigned DS-4 so check order // correct final List tSecondPin = distributionSetManagement - .findByFilterAndAssignedInstalledDsOrderedByLinkTarget(PAGE, distributionSetFilterBuilder, - tSecond.getControllerId()) + .findByDistributionSetFilterOrderByLinkedTarget(PAGE, distributionSetFilter, tSecond.getControllerId()) .getContent(); assertThat(tSecondPin.get(0)).isEqualTo(dsSecond); assertThat(tSecondPin.get(1)).isEqualTo(dsFour); @@ -724,15 +718,14 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { validateDeleted(dsDeleted, sizeOfAllDistributionSets - 1); validateCompleted(dsInComplete, sizeOfAllDistributionSets - 1); validateType(newType, dsNewType, sizeOfAllDistributionSets - 1); - validateSearchText(dsGroup2, "%" + dsGroup2Prefix); - validateFilterString(allDistributionSets, dsGroup2Prefix); + validateSearchText(allDistributionSets, dsGroup2Prefix); validateTags(dsTagA, dsTagB, dsTagC, dsGroup1WithGroup2, dsGroup1); validateDeletedAndCompleted(dsGroup1WithGroup2, dsNewType, dsDeleted); validateDeletedAndCompletedAndType(dsGroup1WithGroup2, dsDeleted, newType, dsNewType); - validateDeletedAndCompletedAndTypeAndSearchText(dsGroup2, newType, "%" + dsGroup2Prefix); - validateDeletedAndCompletedAndTypeAndFilterString(dsGroup1WithGroup2, dsDeleted, dsInComplete, dsNewType, - newType, ":1"); - validateDeletedAndCompletedAndTypeAndSearchTextAndTag(dsGroup2, dsTagA, "%" + dsGroup2Prefix); + validateDeletedAndCompletedAndTypeAndSearchText(dsGroup2, newType, dsGroup2Prefix); + validateDeletedAndCompletedAndTypeAndSearchText(dsGroup1WithGroup2, dsDeleted, dsInComplete, dsNewType, newType, + ":1"); + validateDeletedAndCompletedAndTypeAndSearchTextAndTag(dsGroup2, dsTagA, dsGroup2Prefix); } @Step @@ -764,59 +757,51 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { @Step private void validateType(final DistributionSetType newType, final DistributionSet dsNewType, final int standardDsTypeSize) { - - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setType(newType), + assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setTypeId(newType.getId()), singletonList(dsNewType)); - assertThatFilterHasSizeAndDoesNotContainDistributionSet( - getDistributionSetFilterBuilder().setType(standardDsType), standardDsTypeSize, dsNewType); + getDistributionSetFilterBuilder().setTypeId(standardDsType.getId()), standardDsTypeSize, dsNewType); } @Step - private void validateSearchText(final List withText, final String text) { - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(text), - withText); - } - - @Step - private void validateFilterString(final List allDistributionSets, final String dsNamePrefix) { + private void validateSearchText(final List allDistributionSets, final String dsNamePrefix) { final List withTestNamePrefix = allDistributionSets.stream() .filter(ds -> ds.getName().startsWith(dsNamePrefix)).collect(Collectors.toList()); - assertThatFilterContainsOnlyGivenDistributionSets( - getDistributionSetFilterBuilder().setFilterString(dsNamePrefix), withTestNamePrefix); + assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(dsNamePrefix), + withTestNamePrefix); final List withTestNameExact = withTestNamePrefix.stream() .filter(ds -> ds.getName().equals(dsNamePrefix)).collect(Collectors.toList()); assertThatFilterContainsOnlyGivenDistributionSets( - getDistributionSetFilterBuilder().setFilterString(dsNamePrefix + ":"), withTestNameExact); + getDistributionSetFilterBuilder().setSearchText(dsNamePrefix + ":"), withTestNameExact); final List withTestNameExactAndVersionPrefix = withTestNameExact.stream() .filter(ds -> ds.getVersion().startsWith("1")).collect(Collectors.toList()); assertThatFilterContainsOnlyGivenDistributionSets( - getDistributionSetFilterBuilder().setFilterString(dsNamePrefix + ":1"), + getDistributionSetFilterBuilder().setSearchText(dsNamePrefix + ":1"), withTestNameExactAndVersionPrefix); final List dsWithExactNameAndVersion = withTestNameExactAndVersionPrefix.stream() .filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList()); assertThat(dsWithExactNameAndVersion).hasSize(1); assertThatFilterContainsOnlyGivenDistributionSets( - getDistributionSetFilterBuilder().setFilterString(dsNamePrefix + ":1.0.0"), dsWithExactNameAndVersion); + getDistributionSetFilterBuilder().setSearchText(dsNamePrefix + ":1.0.0"), dsWithExactNameAndVersion); final List withVersionPrefix = allDistributionSets.stream() .filter(ds -> ds.getVersion().startsWith("1.0.")).collect(Collectors.toList()); - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setFilterString(":1.0."), + assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(":1.0."), withVersionPrefix); final List withVersionExact = withVersionPrefix.stream() .filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList()); - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setFilterString(":1.0.0"), + assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(":1.0.0"), withVersionExact); - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setFilterString(":"), + assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(":"), allDistributionSets); - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setFilterString(" : "), + assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(" : "), allDistributionSets); } @@ -864,18 +849,14 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { @Step private void validateDeletedAndCompletedAndType(final List deletedAndCompletedAndStandardType, final DistributionSet dsDeleted, final DistributionSetType newType, final DistributionSet dsNewType) { - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsDeleted(Boolean.FALSE) - .setIsComplete(Boolean.TRUE).setType(standardDsType), deletedAndCompletedAndStandardType); - + .setIsComplete(Boolean.TRUE).setTypeId(standardDsType.getId()), deletedAndCompletedAndStandardType); assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) - .setType(standardDsType).setIsDeleted(Boolean.TRUE), singletonList(dsDeleted)); - + .setTypeId(standardDsType.getId()).setIsDeleted(Boolean.TRUE), singletonList(dsDeleted)); assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setIsDeleted(Boolean.TRUE) - .setIsComplete(Boolean.FALSE).setType(standardDsType)); - + .setIsComplete(Boolean.FALSE).setTypeId(standardDsType.getId())); assertThatFilterContainsOnlyGivenDistributionSets( - getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setType(newType), + getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setTypeId(newType.getId()), singletonList(dsNewType)); } @@ -884,21 +865,23 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { final List completedAndStandardTypeAndSearchText, final DistributionSetType newType, final String text) { - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) - .setType(standardDsType).setSearchText(text), completedAndStandardTypeAndSearchText); + assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsDeleted(Boolean.FALSE) + .setIsComplete(Boolean.TRUE).setTypeId(standardDsType.getId()).setSearchText(text), + completedAndStandardTypeAndSearchText); assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) - .setIsDeleted(Boolean.TRUE).setType(standardDsType).setSearchText(text)); + .setIsDeleted(Boolean.TRUE).setTypeId(standardDsType.getId()).setSearchText(text + ":")); - assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setType(standardDsType) - .setSearchText(text).setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE)); + assertThatFilterDoesNotContainAnyDistributionSet( + getDistributionSetFilterBuilder().setTypeId(standardDsType.getId()).setSearchText(text) + .setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE)); - assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setType(newType) + assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setTypeId(newType.getId()) .setSearchText(text).setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE)); } @Step - private void validateDeletedAndCompletedAndTypeAndFilterString( + private void validateDeletedAndCompletedAndTypeAndSearchText( final List completedAndNotDeletedStandardTypeAndFilterString, final DistributionSet dsDeleted, final DistributionSet dsInComplete, final DistributionSet dsNewType, final DistributionSetType newType, final String filterString) { @@ -907,23 +890,25 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { completedAndNotDeletedStandardTypeAndFilterString); completedAndStandardTypeAndFilterString.add(dsDeleted); assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) - .setType(standardDsType).setFilterString(filterString), completedAndStandardTypeAndFilterString); + .setTypeId(standardDsType.getId()).setSearchText(filterString), + completedAndStandardTypeAndFilterString); assertThatFilterContainsOnlyGivenDistributionSets( getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE) - .setType(standardDsType).setFilterString(filterString), + .setTypeId(standardDsType.getId()).setSearchText(filterString), completedAndNotDeletedStandardTypeAndFilterString); assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) - .setIsDeleted(Boolean.TRUE).setType(standardDsType).setFilterString(filterString), + .setIsDeleted(Boolean.TRUE).setTypeId(standardDsType.getId()).setSearchText(filterString), singletonList(dsDeleted)); - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setType(standardDsType) - .setFilterString(filterString).setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE), + assertThatFilterContainsOnlyGivenDistributionSets( + getDistributionSetFilterBuilder().setTypeId(standardDsType.getId()).setSearchText(filterString) + .setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE), singletonList(dsInComplete)); - assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setType(newType) - .setFilterString(filterString).setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE), + assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setTypeId(newType.getId()) + .setSearchText(filterString).setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE), singletonList(dsNewType)); } @@ -933,13 +918,13 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { final String text) { assertThatFilterContainsOnlyGivenDistributionSets( - getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setType(standardDsType) + getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setTypeId(standardDsType.getId()) .setSearchText(text).setTagNames(singletonList(dsTagA.getName())), completedAndStandartTypeAndSearchTextAndTagA); - assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setType(standardDsType) - .setSearchText(text).setTagNames(singletonList(dsTagA.getName())).setIsComplete(Boolean.FALSE) - .setIsDeleted(Boolean.FALSE)); + assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder() + .setTypeId(standardDsType.getId()).setSearchText(text).setTagNames(singletonList(dsTagA.getName())) + .setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE)); } private DistributionSetFilterBuilder getDistributionSetFilterBuilder() { @@ -983,7 +968,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { distributionSetManagement.delete(ds1.getId()); // not assigned so not marked as deleted but fully deleted assertThat(distributionSetRepository.findAll()).hasSize(1); - assertThat(distributionSetManagement.findByCompleted(PAGE, true).getTotalElements()).isEqualTo(1); + assertThat(distributionSetManagement.findByCompleted(PAGE, true)).hasSize(1); } @Test @@ -1027,11 +1012,15 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { final Page metadataOfDs2 = distributionSetManagement .findMetaDataByDistributionSetId(PageRequest.of(0, 100), ds2.getId()); - assertThat(metadataOfDs1.getNumberOfElements()).isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet()); - assertThat(metadataOfDs1.getTotalElements()).isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet()); + assertThat(metadataOfDs1.getNumberOfElements()) + .isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet()); + assertThat(metadataOfDs1.getTotalElements()) + .isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet()); - assertThat(metadataOfDs2.getNumberOfElements()).isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1); - assertThat(metadataOfDs2.getTotalElements()).isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1); + assertThat(metadataOfDs2.getNumberOfElements()) + .isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1); + assertThat(metadataOfDs2.getTotalElements()) + .isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1); } @Test @@ -1056,7 +1045,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { // not assigned so not marked as deleted assertThat(distributionSetRepository.findAll()).hasSize(4); - assertThat(distributionSetManagement.findByCompleted(PAGE, true).getTotalElements()).isEqualTo(2); + assertThat(distributionSetManagement.findByCompleted(PAGE, true)).hasSize(2); } @Test @@ -1131,7 +1120,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } // can be removed with java-11 - private T getOrThrow(Optional opt) { + private T getOrThrow(final Optional opt) { return opt.orElseThrow(NoSuchElementException::new); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTagManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTagManagementTest.java index a749c1748..7ea3d4190 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTagManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTagManagementTest.java @@ -10,13 +10,13 @@ package org.eclipse.hawkbit.repository.jpa; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.builder.TagCreate; @@ -35,6 +35,7 @@ import org.junit.jupiter.api.Test; import io.qameta.allure.Description; import io.qameta.allure.Feature; +import io.qameta.allure.Step; import io.qameta.allure.Story; /** @@ -103,71 +104,43 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest toggleTagAssignment(dsABCs, distributionSetTagManagement.getByName(tagB.getName()).get()); toggleTagAssignment(dsABCs, distributionSetTagManagement.getByName(tagC.getName()).get()); - DistributionSetFilterBuilder distributionSetFilterBuilder; - // search for not deleted - distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true) - .setTagNames(Arrays.asList(tagA.getName())); - assertEquals(dsAs.spliterator().getExactSizeIfKnown() + dsABs.spliterator().getExactSizeIfKnown() - + dsACs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(), - distributionSetManagement.findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()) - .getTotalElements(), - "filter works not correct"); - - distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true) - .setTagNames(Arrays.asList(tagB.getName())); - assertEquals( - dsBs.spliterator().getExactSizeIfKnown() + dsABs.spliterator().getExactSizeIfKnown() - + dsBCs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(), - distributionSetManagement.findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()) - .getTotalElements(), - "filter works not correct"); - - distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true) - .setTagNames(Arrays.asList(tagC.getName())); - assertEquals(dsCs.spliterator().getExactSizeIfKnown() + dsACs.spliterator().getExactSizeIfKnown() - + dsBCs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(), - distributionSetManagement.findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()) - .getTotalElements(), - "filter works not correct"); - - distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true) - .setTagNames(Arrays.asList(tagX.getName())); - assertEquals(0, distributionSetManagement - .findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()).getTotalElements(), - "filter works not correct"); - - assertEquals(5, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown(), "wrong tag size"); + final DistributionSetFilterBuilder distributionSetFilterBuilder = getDistributionSetFilterBuilder() + .setIsComplete(true); + verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagA.getName())), + Stream.of(dsAs, dsABs, dsACs, dsABCs)); + verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagB.getName())), + Stream.of(dsBs, dsABs, dsBCs, dsABCs)); + verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagC.getName())), + Stream.of(dsCs, dsACs, dsBCs, dsABCs)); + verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagX.getName())), + Stream.empty()); + assertThat(distributionSetTagRepository.findAll()).hasSize(5); distributionSetTagManagement.delete(tagY.getName()); - assertEquals(4, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown(), "wrong tag size"); + assertThat(distributionSetTagRepository.findAll()).hasSize(4); distributionSetTagManagement.delete(tagX.getName()); - assertEquals(3, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown(), "wrong tag size"); - + assertThat(distributionSetTagRepository.findAll()).hasSize(3); distributionSetTagManagement.delete(tagB.getName()); - assertEquals(2, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown(), "wrong tag size"); + assertThat(distributionSetTagRepository.findAll()).hasSize(2); - distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) - .setTagNames(Arrays.asList(tagA.getName())); - assertEquals(dsAs.spliterator().getExactSizeIfKnown() + dsABs.spliterator().getExactSizeIfKnown() - + dsACs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(), - distributionSetManagement.findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()) - .getTotalElements(), - "filter works not correct"); + verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagA.getName())), + Stream.of(dsAs, dsABs, dsACs, dsABCs)); + verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagB.getName())), + Stream.empty()); + verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagC.getName())), + Stream.of(dsCs, dsACs, dsBCs, dsABCs)); + } - distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) - .setTagNames(Arrays.asList(tagB.getName())); - assertEquals(0, distributionSetManagement - .findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()).getTotalElements(), - "filter works not correct"); - - distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) - .setTagNames(Arrays.asList(tagC.getName())); - assertEquals(dsCs.spliterator().getExactSizeIfKnown() + dsACs.spliterator().getExactSizeIfKnown() - + dsBCs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(), - distributionSetManagement.findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()) - .getTotalElements(), - "filter works not correct"); + @Step + private void verifyExpectedFilteredDistributionSets(final DistributionSetFilterBuilder distributionSetFilterBuilder, + final Stream> expectedFilteredDistributionSets) { + final Collection retrievedFilteredDsIds = distributionSetManagement + .findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()).stream() + .map(DistributionSet::getId).collect(Collectors.toList()); + final Collection expectedFilteredDsIds = expectedFilteredDistributionSets.flatMap(Collection::stream) + .map(DistributionSet::getId).collect(Collectors.toList()); + assertThat(retrievedFilteredDsIds).hasSameElementsAs(expectedFilteredDsIds); } @Test @@ -182,11 +155,11 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest // toggle A only -> A is now assigned DistributionSetTagAssignmentResult result = toggleTagAssignment(groupA, tag); - assertThat(result.getAlreadyAssigned()).isEqualTo(0); + assertThat(result.getAlreadyAssigned()).isZero(); assertThat(result.getAssigned()).isEqualTo(20); assertThat(result.getAssignedEntity()).containsAll(distributionSetManagement .get(groupA.stream().map(DistributionSet::getId).collect(Collectors.toList()))); - assertThat(result.getUnassigned()).isEqualTo(0); + assertThat(result.getUnassigned()).isZero(); assertThat(result.getUnassignedEntity()).isEmpty(); assertThat(result.getDistributionSetTag()).isEqualTo(tag); @@ -196,14 +169,14 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest assertThat(result.getAssigned()).isEqualTo(20); assertThat(result.getAssignedEntity()).containsAll(distributionSetManagement .get(groupB.stream().map(DistributionSet::getId).collect(Collectors.toList()))); - assertThat(result.getUnassigned()).isEqualTo(0); + assertThat(result.getUnassigned()).isZero(); assertThat(result.getUnassignedEntity()).isEmpty(); assertThat(result.getDistributionSetTag()).isEqualTo(tag); // toggle A+B -> both unassigned result = toggleTagAssignment(concat(groupA, groupB), tag); - assertThat(result.getAlreadyAssigned()).isEqualTo(0); - assertThat(result.getAssigned()).isEqualTo(0); + assertThat(result.getAlreadyAssigned()).isZero(); + assertThat(result.getAssigned()).isZero(); assertThat(result.getAssignedEntity()).isEmpty(); assertThat(result.getUnassigned()).isEqualTo(40); assertThat(result.getUnassignedEntity()).containsAll(distributionSetManagement diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java index 8d3fb4da8..bbe4a3baa 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java @@ -22,6 +22,7 @@ import java.util.Optional; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; + import javax.validation.ConstraintViolationException; import javax.validation.ValidationException; @@ -139,8 +140,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Verifies that a running action is auto canceled by a rollout which assigns another distribution-set.") void rolloutAssignsNewDistributionSetAndAutoCloseActiveActions() { - tenantConfigurationManagement.addOrUpdateConfiguration( - TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, true); + tenantConfigurationManagement + .addOrUpdateConfiguration(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, true); try { // manually assign distribution set to target @@ -197,9 +198,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { @Expect(type = RolloutGroupUpdatedEvent.class, count = 5), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), - @Expect(type = RolloutCreatedEvent.class, count = 1), - @Expect(type = RolloutUpdatedEvent.class, count = 1), - @Expect(type = TargetCreatedEvent.class, count = 125)}) + @Expect(type = RolloutCreatedEvent.class, count = 1), @Expect(type = RolloutUpdatedEvent.class, count = 1), + @Expect(type = TargetCreatedEvent.class, count = 125) }) void entityQueriesReferringToNotExistingEntitiesThrowsException() { testdataFactory.createRollout("xxx"); @@ -255,7 +255,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { scheduledGroups.forEach(group -> assertThat(group.getStatus()) .as("group which should be in scheduled state is in " + group.getStatus() + " state") .isEqualTo(RolloutGroupStatus.SCHEDULED)); - // verify that the first group actions has been started and are in state running + // verify that the first group actions has been started and are in state + // running final List runningActions = findActionsByRolloutAndStatus(createdRollout, Status.RUNNING); assertThat(runningActions).hasSize(amountTargetsForRollout / amountGroups) .as("Created actions are initiated by rollout creator") @@ -522,8 +523,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { rolloutManagement.handleRollouts(); // finish running actions, 2 actions should be finished assertThat(changeStatusForAllRunningActions(createdRollout, Status.FINISHED)).isEqualTo(2); - assertThat(getRollout(createdRollout.getId()).getStatus()) - .isEqualTo(RolloutStatus.RUNNING); + assertThat(getRollout(createdRollout.getId()).getStatus()).isEqualTo(RolloutStatus.RUNNING); } // check rollout to see that all actions and all groups are finished and @@ -1006,7 +1006,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { changeStatusForAllRunningActions(rolloutD, Status.FINISHED); rolloutManagement.handleRollouts(); - final Page rolloutPage = rolloutManagement + final Slice rolloutPage = rolloutManagement .findAllWithDetailedStatus(new OffsetBasedPageRequest(0, 100, Sort.by(Direction.ASC, "name")), false); final List rolloutList = rolloutPage.getContent(); @@ -1387,12 +1387,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { // group1 exceeds the quota assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( - entityFactory.rollout() - .create() - .name(rolloutName) - .description(rolloutName) - .targetFilterQuery("controllerId==" + rolloutName + "-*") - .set(distributionSet), Arrays.asList(group1, group2), conditions)); + entityFactory.rollout().create().name(rolloutName).description(rolloutName) + .targetFilterQuery("controllerId==" + rolloutName + "-*").set(distributionSet), + Arrays.asList(group1, group2), conditions)); // create group definitions final RolloutGroupCreate group3 = entityFactory.rolloutGroup().create().conditions(conditions).name("group3") @@ -1402,37 +1399,23 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { // group4 exceeds the quota assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( - entityFactory.rollout() - .create() - .name(rolloutName) - .description(rolloutName) - .targetFilterQuery("controllerId==" + rolloutName + "-*") - .set(distributionSet), Arrays.asList(group3, group4), conditions)); + entityFactory.rollout().create().name(rolloutName).description(rolloutName) + .targetFilterQuery("controllerId==" + rolloutName + "-*").set(distributionSet), + Arrays.asList(group3, group4), conditions)); // create group definitions - final RolloutGroupCreate group5 = entityFactory.rolloutGroup() - .create() - .conditions(conditions) - .name("group5") + final RolloutGroupCreate group5 = entityFactory.rolloutGroup().create().conditions(conditions).name("group5") .targetPercentage(33.3F); - final RolloutGroupCreate group6 = entityFactory.rolloutGroup() - .create() - .conditions(conditions) - .name("group6") + final RolloutGroupCreate group6 = entityFactory.rolloutGroup().create().conditions(conditions).name("group6") .targetPercentage(66.6F); - final RolloutGroupCreate group7 = entityFactory.rolloutGroup() - .create() - .conditions(conditions) - .name("group7") + final RolloutGroupCreate group7 = entityFactory.rolloutGroup().create().conditions(conditions).name("group7") .targetPercentage(100.0F); // should work fine - assertThat(rolloutManagement.create(entityFactory.rollout() - .create() - .name(rolloutName) - .description(rolloutName) - .targetFilterQuery("controllerId==" + rolloutName + "-*") - .set(distributionSet), Arrays.asList(group5, group6, group7), conditions)).isNotNull(); + assertThat(rolloutManagement.create( + entityFactory.rollout().create().name(rolloutName).description(rolloutName) + .targetFilterQuery("controllerId==" + rolloutName + "-*").set(distributionSet), + Arrays.asList(group5, group6, group7), conditions)).isNotNull(); } @@ -1603,8 +1586,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); final RolloutCreate rollout = generateTargetsAndRollout(rolloutName, targets); - assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy( - () -> rolloutManagement.create(rollout, maxGroups + 1, conditions)) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) + .isThrownBy(() -> rolloutManagement.create(rollout, maxGroups + 1, conditions)) .withMessageContaining("not be greater than " + maxGroups); } @@ -1625,8 +1608,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { .errorCondition(RolloutGroupErrorCondition.THRESHOLD, errorCondition) .errorAction(RolloutGroupErrorAction.PAUSE, null).build(); final RolloutCreate rolloutToCreate = entityFactory.rollout().create().name(rolloutName) - .description("some description").targetFilterQuery("id==" + rolloutName + "-*") - .set(distributionSet); + .description("some description").targetFilterQuery("id==" + rolloutName + "-*").set(distributionSet); Rollout myRollout = rolloutManagement.create(rolloutToCreate, amountGroups, conditions); myRollout = getRollout(myRollout.getId()); @@ -1783,8 +1765,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { @Description("Creating a rollout without weight value when multi assignment in enabled.") void weightNotRequiredInMultiAssignmentMode() { enableMultiAssignments(); - final Rollout rollout = createSimpleTestRolloutWithTargetsAndDistributionSet( - 10, 10, 2, "50", "80", ActionType.FORCED, null); + final Rollout rollout = createSimpleTestRolloutWithTargetsAndDistributionSet(10, 10, 2, "50", "80", + ActionType.FORCED, null); assertThat(rollout).isNotNull(); } @@ -1854,8 +1836,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { void createRolloutWithInvalidDistributionSet() { final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet(); - assertThatExceptionOfType(InvalidDistributionSetException.class).as( - "Invalid distributionSet should throw an exception") + assertThatExceptionOfType(InvalidDistributionSetException.class) + .as("Invalid distributionSet should throw an exception") .isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithInvalidDistributionSet", "desc", 2, "name==*", distributionSet, "50", "80")); } @@ -1865,8 +1847,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { void createRolloutWithIncompleteDistributionSet() { final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet(); - assertThatExceptionOfType(IncompleteDistributionSetException.class).as( - "Incomplete distributionSet should throw an exception") + assertThatExceptionOfType(IncompleteDistributionSetException.class) + .as("Incomplete distributionSet should throw an exception") .isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithIncompleteDistributionSet", "desc", 2, "name==*", distributionSet, "50", "80")); } @@ -1880,10 +1862,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { "desc", 2, "name==*", distributionSet, "50", "80"); final DistributionSet invalidDistributionSet = testdataFactory.createAndInvalidateDistributionSet(); - assertThatExceptionOfType(InvalidDistributionSetException.class).as( - "Invalid distributionSet should throw an exception") - .isThrownBy(() -> rolloutManagement.update( - entityFactory.rollout().update(rollout.getId()).set(invalidDistributionSet.getId()))); + assertThatExceptionOfType(InvalidDistributionSetException.class) + .as("Invalid distributionSet should throw an exception").isThrownBy(() -> rolloutManagement + .update(entityFactory.rollout().update(rollout.getId()).set(invalidDistributionSet.getId()))); } @Test @@ -1895,9 +1876,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { "desc", 2, "name==*", distributionSet, "50", "80"); final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet(); - assertThatExceptionOfType(IncompleteDistributionSetException.class).as( - "Incomplete distributionSet should throw an exception") - .isThrownBy(() -> rolloutManagement.update( + assertThatExceptionOfType(IncompleteDistributionSetException.class) + .as("Incomplete distributionSet should throw an exception").isThrownBy(() -> rolloutManagement.update( entityFactory.rollout().update(rollout.getId()).set(incompleteDistributionSet.getId()))); } @@ -1920,11 +1900,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { targets.addAll(targetsWithoutType); final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); - final RolloutCreate rolloutToCreate = entityFactory.rollout() - .create() - .name(rolloutName) - .targetFilterQuery("name==*") - .set(testDs); + final RolloutCreate rolloutToCreate = entityFactory.rollout().create().name(rolloutName) + .targetFilterQuery("name==*").set(testDs); final Rollout createdRollout = rolloutManagement.create(rolloutToCreate, 1, conditions); @@ -1932,19 +1909,18 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { rolloutManagement.handleRollouts(); final Rollout testRollout = reloadRollout(createdRollout); - final List rolloutGroups = rolloutGroupManagement.findByRollout(Pageable.unpaged(), - testRollout.getId()).getContent(); + final List rolloutGroups = rolloutGroupManagement + .findByRollout(Pageable.unpaged(), testRollout.getId()).getContent(); assertThat(testRollout.getStatus()).isEqualTo(RolloutStatus.READY); assertThat(testRollout.getTotalTargets()).isEqualTo(targets.size()); assertThat(rolloutGroups).hasSize(1); assertThat(rolloutGroups.get(0).getTotalTargets()).isEqualTo(targets.size()); - final List rolloutGroupTargets = rolloutGroupManagement.findTargetsOfRolloutGroup(Pageable.unpaged(), - rolloutGroups.get(0).getId()).getContent(); + final List rolloutGroupTargets = rolloutGroupManagement + .findTargetsOfRolloutGroup(Pageable.unpaged(), rolloutGroups.get(0).getId()).getContent(); - assertThat(rolloutGroupTargets).hasSize(targets.size()) - .containsExactlyInAnyOrderElementsOf(targets) + assertThat(rolloutGroupTargets).hasSize(targets.size()).containsExactlyInAnyOrderElementsOf(targets) .doesNotContainAnyElementsOf(incompatibleTargets); } @@ -2049,13 +2025,10 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { } private void awaitRunningState(final Long myRolloutId) { - Awaitility.await() - .atMost(Duration.TEN_SECONDS) - .pollInterval(Duration.FIVE_HUNDRED_MILLISECONDS) - .with() - .until(() -> WithSpringAuthorityRule.runAsPrivileged( + Awaitility.await().atMost(Duration.TEN_SECONDS).pollInterval(Duration.FIVE_HUNDRED_MILLISECONDS).with() + .until(() -> WithSpringAuthorityRule + .runAsPrivileged( () -> rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new)) - .getStatus() - .equals(RolloutStatus.RUNNING)); + .getStatus().equals(RolloutStatus.RUNNING)); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleManagementTest.java index 8e962eb3a..2aee2467c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleManagementTest.java @@ -81,9 +81,8 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule module = testdataFactory.createSoftwareModuleApp(); verifyThrownExceptionBy( - () -> softwareModuleManagement - .create(Collections - .singletonList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))), + () -> softwareModuleManagement.create(Collections + .singletonList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))), "SoftwareModuleType"); verifyThrownExceptionBy( () -> softwareModuleManagement @@ -195,21 +194,20 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(softwareModuleManagement.findByTextAndType(PAGE, "poky", osType.getId()).getContent()).hasSize(1); assertThat(softwareModuleManagement.findByTextAndType(PAGE, "poky", osType.getId()).getContent().get(0)) .isEqualTo(os); - assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle%", runtimeType.getId()).getContent()) + assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle", runtimeType.getId()).getContent()) .hasSize(1); - assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle%", runtimeType.getId()).getContent().get(0)) + assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle", runtimeType.getId()).getContent().get(0)) .isEqualTo(jvm); - assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0.1", appType.getId()).getContent()).hasSize(1); - assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0.1", appType.getId()).getContent().get(0)) - .isEqualTo(ah); - assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0%", appType.getId()).getContent()).hasSize(2); + assertThat(softwareModuleManagement.findByTextAndType(PAGE, ":1.0.1", appType.getId()).getContent()).hasSize(1) + .first().isEqualTo(ah); + assertThat(softwareModuleManagement.findByTextAndType(PAGE, ":1.0", appType.getId()).getContent()).hasSize(2); // no we search with on entity marked as deleted softwareModuleManagement.delete( softwareModuleRepository.findByAssignedToAndType(PAGE, ds, appType).getContent().get(0).getId()); - assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0%", appType.getId()).getContent()).hasSize(1); - assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0%", appType.getId()).getContent().get(0)) + assertThat(softwareModuleManagement.findByTextAndType(PAGE, ":1.0", appType.getId()).getContent()).hasSize(1); + assertThat(softwareModuleManagement.findByTextAndType(PAGE, ":1.0", appType.getId()).getContent().get(0)) .isEqualTo(ah); } @@ -694,7 +692,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { // add some meta data entries final SoftwareModule module3 = testdataFactory.createSoftwareModuleApp("m3"); - final int firstHalf = Math.round(((float) maxMetaData) / 2.f); + final int firstHalf = Math.round((maxMetaData) / 2.f); for (int i = 0; i < firstHalf; ++i) { softwareModuleManagement.createMetaData( entityFactory.softwareModuleMetadata().create(module3.getId()).key("k" + i).value("v" + i)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryManagementTest.java index 07aef02f3..bb2921137 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryManagementTest.java @@ -46,6 +46,7 @@ import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; import io.qameta.allure.Description; import io.qameta.allure.Feature; @@ -417,26 +418,33 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest final Page tfqList = targetFilterQueryManagement .findByAutoAssignDSAndRsql(PageRequest.of(0, 500), distributionSet.getId(), rsql); + assertThat(tfqList.getTotalElements()).isEqualTo(expectedFilterQueries.length); verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries); } - private void verifyExpectedFilterQueriesInList(final Page tfqList, + private void verifyExpectedFilterQueriesInList(final Slice tfqList, final TargetFilterQuery... expectedFilterQueries) { - assertThat(expectedFilterQueries.length).as("Target filter query count") - .isEqualTo((int) tfqList.getTotalElements()); - assertThat(tfqList.map(TargetFilterQuery::getId)).containsExactly( Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new)); } @Step private void verifyFindForAllWithAutoAssignDs(final TargetFilterQuery... expectedFilterQueries) { - final Page tfqList = targetFilterQueryManagement + final Slice tfqList = targetFilterQueryManagement .findWithAutoAssignDS(PageRequest.of(0, 500)); + assertThat(tfqList.getNumberOfElements()).isEqualTo(expectedFilterQueries.length); verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries); } + private void verifyExpectedFilterQueriesInList(final Page tfqList, + final TargetFilterQuery... expectedFilterQueries) { + assertThat(expectedFilterQueries).as("Target filter query count").hasSize((int) tfqList.getTotalElements()); + + assertThat(tfqList.map(TargetFilterQuery::getId)).containsExactly( + Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new)); + } + @Test @Description("Creating or updating a target filter query with autoassignment and no-value weight when multi assignment in enabled.") public void weightNotRequiredInMultiAssignmentMode() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java index fefe695ae..324c5719a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java @@ -15,13 +15,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import org.eclipse.hawkbit.repository.FilterParams; -import org.eclipse.hawkbit.repository.UpdateMode; import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; @@ -110,19 +107,6 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final String installedC = targCs.iterator().next().getControllerId(); final Long actionId = getFirstAssignedActionId(assignDistributionSet(installedSet.getId(), assignedC)); - // add attributes to match against only attribute value or attribute - // value and name - final Map attributes = new HashMap<>(); - attributes.put("key", "targ-C-attribute-value"); - final Target targAttribute = controllerManagement.updateControllerAttributes(targCs.get(0).getControllerId(), - attributes, UpdateMode.REPLACE); - // prepare one target with an attribute value equal to controller id - Target targAttributeId = targCs.get(15); - final Map idAttributes = new HashMap<>(); - idAttributes.put("key", targAttributeId.getControllerId()); - targAttributeId = controllerManagement.updateControllerAttributes(targAttributeId.getControllerId(), - idAttributes, UpdateMode.REPLACE); - // set one installed DS also controllerManagement.addUpdateActionStatus( entityFactory.actionStatus().create(actionId).status(Status.FINISHED).message("message")); @@ -142,9 +126,6 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { // try to find several targets with different filter settings verifyThat1TargetHasNameAndId("targ-A-special", targSpecialName.getControllerId()); - verifyThat1TargetHasAttributeValue("%c-attribute%", targAttribute.getControllerId()); - verifyThat1TargetHasAttributeValue("%" + targAttributeId.getControllerId() + "%", - targAttributeId.getControllerId()); verifyThatRepositoryContains500Targets(); verifyThat200TargetsHaveTagD(targTagW, concat(targBs, targCs)); verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(targTagY, targTagW, targBs); @@ -183,8 +164,10 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(installedSet, pending, targetManagement.getByControllerID(installedC).get()); verifyThat1TargetHasTypeAndDSAssigned(targetTypeX, setB, targetManagement.getByControllerID(assignedE).get()); - verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(setA, targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC))); - verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(installedSet, targetManagement.getByControllerID(Collections.singletonList(installedC))); + verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(setA, + targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC))); + verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(installedSet, + targetManagement.getByControllerID(Collections.singletonList(installedC))); verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(targetTypeX, targEs); verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(concat(targAs, targBs, targCs, targDs)); @@ -481,14 +464,6 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParamsByControllerId))); } - @Step - private void verifyThat1TargetHasAttributeValue(final String value, final String controllerId) { - final FilterParams filterParams = new FilterParams(null, null, value, null, Boolean.FALSE); - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(1).as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams))); - } - @Step private void verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(final TargetTag targTagY, final TargetTag targTagW, final List expected) { @@ -544,7 +519,8 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { } @Step - private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set, final List expected) { + private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set, + final List expected) { final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.TRUE, null); assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") .hasSize(expected.size()).as("that number is also returned by count query") @@ -556,11 +532,12 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { private void verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(final TargetType targetType, final List expected) { final FilterParams filterParams = new FilterParams("%targ-E%", null, Boolean.FALSE, targetType.getId()); - List filteredTargets = targetManagement.findByFilters(PAGE, filterParams).getContent(); + final List filteredTargets = targetManagement.findByFilters(PAGE, filterParams).getContent(); assertThat(filteredTargets).as("has number of elements").hasSize(100) .as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams))); - // Comparing the controller ids, as one of the targets was modified, so a 1:1 + // Comparing the controller ids, as one of the targets was modified, so + // a 1:1 // comparison of the objects is not possible assertThat(filteredTargets.stream().map(Target::getControllerId).collect(Collectors.toList())) .containsAll(expected.stream().map(Target::getControllerId).collect(Collectors.toList())); @@ -787,19 +764,18 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { @Test @Description("Verifies that targets with given target type are returned from repository.") public void findTargetByTargetType() { - TargetType testType = testdataFactory.createTargetType("testType", Collections.singletonList(standardDsType)); - List unassigned = testdataFactory.createTargets(9, "unassigned"); - List assigned = testdataFactory.createTargetsWithType(11, "assigned", testType); + final TargetType testType = testdataFactory.createTargetType("testType", + Collections.singletonList(standardDsType)); + final List unassigned = testdataFactory.createTargets(9, "unassigned"); + final List assigned = testdataFactory.createTargetsWithType(11, "assigned", testType); - assertThat(targetManagement.findByFilters(PAGE, - new FilterParams(null,null, false, testType.getId()))) + assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, false, testType.getId()))) .as("Contains the targets with set type").containsAll(assigned) .as("and that means the following expected amount").hasSize(11); - assertThat(targetManagement.countByFilters(new FilterParams(null,null, false, testType.getId()))) + assertThat(targetManagement.countByFilters(new FilterParams(null, null, false, testType.getId()))) .as("Count the targets with set type").isEqualTo(11); - assertThat(targetManagement.findByFilters(PAGE, - new FilterParams(null, null, true, null))) + assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, true, null))) .as("Contains the targets without a type").containsAll(unassigned) .as("and that means the following expected amount").hasSize(9); assertThat(targetManagement.countByFilters(new FilterParams(null, null, true, null))) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java index 13803025f..4a6de4d87 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java @@ -69,6 +69,7 @@ import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; import com.google.common.collect.Iterables; @@ -160,10 +161,9 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy(() -> targetManagement.deleteMetaData(target.getControllerId(), NOT_EXIST_ID), "TargetMetadata"); verifyThrownExceptionBy(() -> targetManagement.getMetaDataByControllerId(NOT_EXIST_ID, "xxx"), "Target"); - verifyThrownExceptionBy(() -> targetManagement.findMetaDataByControllerId(PAGE, NOT_EXIST_ID), + verifyThrownExceptionBy(() -> targetManagement.findMetaDataByControllerId(PAGE, NOT_EXIST_ID), "Target"); + verifyThrownExceptionBy(() -> targetManagement.findMetaDataByControllerIdAndRsql(PAGE, NOT_EXIST_ID, "key==*"), "Target"); - verifyThrownExceptionBy( - () -> targetManagement.findMetaDataByControllerIdAndRsql(PAGE, NOT_EXIST_ID, "key==*"), "Target"); verifyThrownExceptionBy( () -> targetManagement.updateMetadata(NOT_EXIST_ID, entityFactory.generateTargetMetadata("xxx", "xxx")), "Target"); @@ -222,8 +222,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Verify that a target with with invalid properties cannot be created or updated") - @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), - @Expect(type = TargetUpdatedEvent.class) }) + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class) }) void createAndUpdateTargetWithInvalidFields() { final Target target = testdataFactory.createTarget(); @@ -243,8 +242,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .description(RandomStringUtils.randomAlphanumeric(513)))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid description should not be created") - .isThrownBy(() -> targetManagement + .as("target with invalid description should not be created").isThrownBy(() -> targetManagement .create(entityFactory.target().create().controllerId("a").description(INVALID_TEXT_HTML))); assertThatExceptionOfType(ConstraintViolationException.class) @@ -253,9 +251,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .description(RandomStringUtils.randomAlphanumeric(513)))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid description should not be updated") - .isThrownBy(() -> targetManagement - .update(entityFactory.target().update(target.getControllerId()).description(INVALID_TEXT_HTML))); + .as("target with invalid description should not be updated").isThrownBy(() -> targetManagement.update( + entityFactory.target().update(target.getControllerId()).description(INVALID_TEXT_HTML))); } @Step @@ -267,8 +264,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid name should not be created") - .isThrownBy(() -> targetManagement + .as("target with invalid name should not be created").isThrownBy(() -> targetManagement .create(entityFactory.target().create().controllerId("a").name(INVALID_TEXT_HTML))); assertThatExceptionOfType(ConstraintViolationException.class) @@ -277,14 +273,12 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid name should not be updated") - .isThrownBy(() -> targetManagement + .as("target with invalid name should not be updated").isThrownBy(() -> targetManagement .update(entityFactory.target().update(target.getControllerId()).name(INVALID_TEXT_HTML))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too short name should not be updated") - .isThrownBy( - () -> targetManagement.update(entityFactory.target().update(target.getControllerId()).name(""))); + .as("target with too short name should not be updated").isThrownBy(() -> targetManagement + .update(entityFactory.target().update(target.getControllerId()).name(""))); } @@ -297,8 +291,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1)))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid token should not be created") - .isThrownBy(() -> targetManagement + .as("target with invalid token should not be created").isThrownBy(() -> targetManagement .create(entityFactory.target().create().controllerId("a").securityToken(INVALID_TEXT_HTML))); assertThatExceptionOfType(ConstraintViolationException.class) @@ -307,13 +300,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1)))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid token should not be updated") - .isThrownBy(() -> targetManagement.update( + .as("target with invalid token should not be updated").isThrownBy(() -> targetManagement.update( entityFactory.target().update(target.getControllerId()).securityToken(INVALID_TEXT_HTML))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too short token should not be updated") - .isThrownBy(() -> targetManagement + .as("target with too short token should not be updated").isThrownBy(() -> targetManagement .update(entityFactory.target().update(target.getControllerId()).securityToken(""))); } @@ -325,8 +316,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") .address(RandomStringUtils.randomAlphanumeric(513)))); - assertThatExceptionOfType(InvalidTargetAddressException.class) - .as("target with invalid should not be created") + assertThatExceptionOfType(InvalidTargetAddressException.class).as("target with invalid should not be created") .isThrownBy(() -> targetManagement .create(entityFactory.target().create().controllerId("a").address(INVALID_TEXT_HTML))); @@ -336,8 +326,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .address(RandomStringUtils.randomAlphanumeric(513)))); assertThatExceptionOfType(InvalidTargetAddressException.class) - .as("target with invalid address should not be updated") - .isThrownBy(() -> targetManagement + .as("target with invalid address should not be updated").isThrownBy(() -> targetManagement .update(entityFactory.target().update(target.getControllerId()).address(INVALID_TEXT_HTML))); } @@ -357,24 +346,19 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .controllerId(RandomStringUtils.randomAlphanumeric(Target.CONTROLLER_ID_MAX_SIZE + 1)))); assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid controller id should not be created") - .isThrownBy( + .as("target with invalid controller id should not be created").isThrownBy( () -> targetManagement.create(entityFactory.target().create().controllerId(INVALID_TEXT_HTML))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as(WHITESPACE_ERROR) + assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" "))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as(WHITESPACE_ERROR) + assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a b"))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as(WHITESPACE_ERROR) + assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" "))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as(WHITESPACE_ERROR) + assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("aaa bbb"))); } @@ -402,7 +386,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { assignedTargets.forEach(target -> assertThat( targetTagManagement.findByTarget(PAGE, target.getControllerId()).getNumberOfElements()).isEqualTo(1)); - TargetTag findTargetTag = targetTagManagement.getByName("Tag1").orElseThrow(IllegalStateException::new); + final TargetTag findTargetTag = targetTagManagement.getByName("Tag1").orElseThrow(IllegalStateException::new); assertThat(assignedTargets.size()).as("Assigned targets are wrong") .isEqualTo(targetManagement.findByTag(PAGE, targetTag.getId()).getNumberOfElements()); @@ -473,20 +457,15 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { final DistributionSet testDs2 = testdataFactory.createDistributionSet("test2"); assertThat(targetManagement.countByAssignedDistributionSet(testDs1.getId())) - .as("For newly created distributions sets the assigned target count should be zero") - .isZero(); + .as("For newly created distributions sets the assigned target count should be zero").isZero(); assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId())) - .as("For newly created distributions sets the installed target count should be zero") - .isZero(); + .as("For newly created distributions sets the installed target count should be zero").isZero(); assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId())) - .as("Exists assigned or installed query should return false for new distribution sets") - .isFalse(); + .as("Exists assigned or installed query should return false for new distribution sets").isFalse(); assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId())) - .as("For newly created distributions sets the assigned target count should be zero") - .isZero(); + .as("For newly created distributions sets the assigned target count should be zero").isZero(); assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId())) - .as("For newly created distributions sets the installed target count should be zero") - .isZero(); + .as("For newly created distributions sets the installed target count should be zero").isZero(); assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs2.getId())) .as("For newly created distributions sets the assigned target count should be zero").isFalse(); @@ -508,8 +487,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .isZero(); assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId())).as("Target count is wrong") .isEqualTo(1); - assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId())).as("Target count is wrong") - .isTrue(); + assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId())) + .as("Target count is wrong").isTrue(); assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId())).as("Target count is wrong") .isEqualTo(1); assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId())).as("Target count is wrong") @@ -520,14 +499,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { final DistributionSet assignedDs = deploymentManagement.getAssignedDistributionSet("4711") .orElseThrow(NoSuchElementException::new); - assertThat(assignedDs).as("Assigned ds size is wrong") - .isEqualTo(testDs2); + assertThat(assignedDs).as("Assigned ds size is wrong").isEqualTo(testDs2); final DistributionSet installedDs = deploymentManagement.getInstalledDistributionSet("4711") .orElseThrow(NoSuchElementException::new); - assertThat(installedDs) - .as("Installed ds is wrong") - .isEqualTo(testDs1); + assertThat(installedDs).as("Installed ds is wrong").isEqualTo(testDs1); } @Test @@ -556,14 +532,14 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { } /** - * verifies, that all {@link TargetTag} of parameter. NOTE: it's accepted that - * the target have additional tags assigned to them which are not contained - * within parameter tags. + * verifies, that all {@link TargetTag} of parameter. NOTE: it's accepted + * that the target have additional tags assigned to them which are not + * contained within parameter tags. * * @param strict - * if true, the given targets MUST contain EXACTLY ALL given tags, - * AND NO OTHERS. If false, the given targets MUST contain ALL given - * tags, BUT MAY CONTAIN FURTHER ONE + * if true, the given targets MUST contain EXACTLY ALL given + * tags, AND NO OTHERS. If false, the given targets MUST contain + * ALL given tags, BUT MAY CONTAIN FURTHER ONE * @param targets * targets to be verified * @param tags @@ -615,7 +591,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { assertThat(createdAt).as("CreatedAt compared with modifiedAt").isEqualTo(modifiedAt); - Awaitility.await().until( () -> System.currentTimeMillis() > createdAt + 1); + Awaitility.await().until(() -> System.currentTimeMillis() > createdAt + 1); savedTarget = targetManagement.update( entityFactory.target().update(savedTarget.getControllerId()).description("changed description")); @@ -625,7 +601,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .isNotEqualTo(savedTarget.getLastModifiedAt()); modifiedAt = savedTarget.getLastModifiedAt(); - final Target foundTarget = targetManagement.getByControllerID(savedTarget.getControllerId()).orElseThrow(IllegalStateException::new); + final Target foundTarget = targetManagement.getByControllerID(savedTarget.getControllerId()) + .orElseThrow(IllegalStateException::new); assertThat(foundTarget).as("The target should not be null").isNotNull(); assertThat(myCtrlID).as("ControllerId compared with saved controllerId") .isEqualTo(foundTarget.getControllerId()); @@ -718,13 +695,15 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { final List t2Tags = testdataFactory.createTargetTags(noT2Tags, "tag2"); t2Tags.forEach(tag -> targetManagement.assignTag(Collections.singletonList(t2.getControllerId()), tag.getId())); - final Target t11 = targetManagement.getByControllerID(t1.getControllerId()).orElseThrow(IllegalStateException::new); + final Target t11 = targetManagement.getByControllerID(t1.getControllerId()) + .orElseThrow(IllegalStateException::new); assertThat(targetTagManagement.findByTarget(PAGE, t11.getControllerId()).getContent()).as("Tag size is wrong") .hasSize(noT1Tags).containsAll(t1Tags); assertThat(targetTagManagement.findByTarget(PAGE, t11.getControllerId()).getContent()).as("Tag size is wrong") .hasSize(noT1Tags).doesNotContain(Iterables.toArray(t2Tags, TargetTag.class)); - final Target t21 = targetManagement.getByControllerID(t2.getControllerId()).orElseThrow(IllegalStateException::new); + final Target t21 = targetManagement.getByControllerID(t2.getControllerId()) + .orElseThrow(IllegalStateException::new); assertThat(targetTagManagement.findByTarget(PAGE, t21.getControllerId()).getContent()).as("Tag size is wrong") .hasSize(noT2Tags).containsAll(t2Tags); assertThat(targetTagManagement.findByTarget(PAGE, t21.getControllerId()).getContent()).as("Tag size is wrong") @@ -909,10 +888,12 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { testdataFactory.createTargets(25, "target-id-B", "first description"); - final Page foundTargets = targetManagement.findByRsql(PAGE, rsqlFilter); + final Slice foundTargets = targetManagement.findByRsql(PAGE, rsqlFilter); + final long foundTargetsCount = targetManagement.countByRsql(rsqlFilter); assertThat(targetManagement.count()).as("Total targets").isEqualTo(50L); - assertThat(foundTargets.getTotalElements()).as("Targets in RSQL filter").isEqualTo(27L); + assertThat(foundTargets.getNumberOfElements()).as("Targets in RSQL filter").isEqualTo(foundTargetsCount) + .isEqualTo(27L); } @Test @@ -1033,11 +1014,12 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { // create target meta data entry insertTargetMetadata(knownKey, knownValue, target); - Target changedLockRevisionTarget = targetManagement.get(target.getId()).orElseThrow(NoSuchElementException::new); + Target changedLockRevisionTarget = targetManagement.get(target.getId()) + .orElseThrow(NoSuchElementException::new); assertThat(changedLockRevisionTarget.getOptLockRevision()).isEqualTo(2); // Unsure if needed maybe to wait for a db flush? - // Thread.sleep(100); + // Thread.sleep(100); // update the target metadata final JpaTargetMetadata updated = (JpaTargetMetadata) targetManagement.updateMetadata(target.getControllerId(), @@ -1117,7 +1099,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { assertThat(targetFound1.get().getOptLockRevision()).isEqualTo(2); assertThat(targetFound1.get().getTargetType().getId()).isEqualTo(targetType.getId()); } - + @Test @WithUser(allSpPermissions = true) @Description("Tests the assignment of types to multiple targets.") @@ -1150,7 +1132,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { checkTargetsHaveType(typeATargets, typeA); checkTargetsHaveType(typeBTargets, typeB); - // verify that type assignment does not throw an error if target list includes an unknown id + // verify that type assignment does not throw an error if target list + // includes an unknown id targetManagement.deleteByControllerID(typeATargets.get(0).getControllerId()); final TargetTypeAssignmentResult resultC = initiateTypeAssignment(typeATargets, typeB); assertThat(resultC.getAssigned()).isEqualTo(9); @@ -1159,7 +1142,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { } private void checkTargetsHaveType(final List targets, final TargetType type) { - List foundTargets = targetRepository + final List foundTargets = targetRepository .findAllById(targets.stream().map(Identifiable::getId).collect(Collectors.toList())); for (final Target target : foundTargets) { if (!type.getName().equals(type.getName())) { @@ -1167,7 +1150,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { } } } - + @Test @Description("Queries and loads the metadata related to a given target.") void findAllTargetMetadataByControllerId() { @@ -1205,14 +1188,13 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { // create a target final Target target = testdataFactory.createTarget("target1", "testtarget"); // initial opt lock revision must be one - Optional targetFound = targetRepository.findById(target.getId()); + final Optional targetFound = targetRepository.findById(target.getId()); assertThat(targetFound).isPresent(); assertThat(targetFound.get().getOptLockRevision()).isEqualTo(1); assertThat(targetFound.get().getTargetType()).isNull(); // assign target type to target - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target type with id=null cannot be assigned") + assertThatExceptionOfType(ConstraintViolationException.class).as("target type with id=null cannot be assigned") .isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), null)); assertThatExceptionOfType(EntityNotFoundException.class) @@ -1220,7 +1202,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), 114L)); // opt lock revision is not changed - Optional targetFound1 = targetRepository.findById(target.getId()); + final Optional targetFound1 = targetRepository.findById(target.getId()); assertThat(targetFound1).isPresent(); assertThat(targetFound1.get().getOptLockRevision()).isEqualTo(1); } @@ -1230,12 +1212,12 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { @Description("Checks that target type can be unassigned from target.") void unAssignTargetTypeFromTarget() { // create a target type - TargetType targetType = testdataFactory.findOrCreateTargetType("targettype"); + final TargetType targetType = testdataFactory.findOrCreateTargetType("targettype"); assertThat(targetType).isNotNull(); // create a target final Target target = testdataFactory.createTarget("target1", "testtarget", targetType.getId()); // initial opt lock revision must be one - Optional targetFound = targetRepository.findById(target.getId()); + final Optional targetFound = targetRepository.findById(target.getId()); assertThat(targetFound).isPresent(); assertThat(targetFound.get().getOptLockRevision()).isEqualTo(1); assertThat(targetFound.get().getTargetType().getName()).isEqualTo(targetType.getName()); @@ -1244,7 +1226,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { targetManagement.unAssignType(targetFound.get().getControllerId()); // opt lock revision must be changed - Optional targetFound1 = targetRepository.findById(target.getId()); + final Optional targetFound1 = targetRepository.findById(target.getId()); assertThat(targetFound1).isPresent(); assertThat(targetFound1.get().getOptLockRevision()).isEqualTo(2); assertThat(targetFound1.get().getTargetType()).isNull(); @@ -1275,9 +1257,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { } private void validateFoundTargetsByRsql(final String rsqlFilter, final String... controllerIds) { - final Page foundTargetsByMetadataAndControllerId = targetManagement.findByRsql(PAGE, rsqlFilter); + final Slice foundTargetsByMetadataAndControllerId = targetManagement.findByRsql(PAGE, rsqlFilter); + final long foundTargetsByMetadataAndControllerIdCount = targetManagement.countByRsql(rsqlFilter); - assertThat(foundTargetsByMetadataAndControllerId.getTotalElements()).as("Targets count in RSQL filter is wrong") + assertThat(foundTargetsByMetadataAndControllerId.getNumberOfElements()) + .as("Targets count in RSQL filter is wrong").isEqualTo(foundTargetsByMetadataAndControllerIdCount) .isEqualTo(controllerIds.length); assertThat(foundTargetsByMetadataAndControllerId.getContent().stream().map(Target::getControllerId)) .as("Targets found by RSQL filter have wrong controller ids").containsExactlyInAnyOrder(controllerIds); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFieldTest.java index 13862c465..48e020c6f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFieldTest.java @@ -28,7 +28,7 @@ import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.data.domain.Page; +import org.springframework.data.domain.Slice; import io.qameta.allure.Description; import io.qameta.allure.Feature; @@ -88,8 +88,10 @@ class RSQLTargetFieldTest extends AbstractJpaIntegrationTest { assignDistributionSet(ds.getId(), target.getControllerId()); - targetType1 = targetTypeManagement.create(entityFactory.targetType().create().name("Type1").description("Desc. Type1")); - targetType2 = targetTypeManagement.create(entityFactory.targetType().create().name("Type2").description("Desc. Type2")); + targetType1 = targetTypeManagement + .create(entityFactory.targetType().create().name("Type1").description("Desc. Type1")); + targetType2 = targetTypeManagement + .create(entityFactory.targetType().create().name("Type2").description("Desc. Type2")); targetManagement.assignType(target.getControllerId(), targetType1.getId()); targetManagement.assignType(target2.getControllerId(), targetType2.getId()); @@ -317,10 +319,10 @@ class RSQLTargetFieldTest extends AbstractJpaIntegrationTest { } private void assertRSQLQuery(final String rsqlParam, final long expectedTargets) { - final Page findTargetPage = targetManagement.findByRsql(PAGE, rsqlParam); - final long countTargetsAll = findTargetPage.getTotalElements(); + final Slice findTargetPage = targetManagement.findByRsql(PAGE, rsqlParam); + final long countTargetsAll = targetManagement.countByRsql(rsqlParam); assertThat(findTargetPage).isNotNull(); - assertThat(countTargetsAll).isEqualTo(expectedTargets); + assertThat(findTargetPage.getNumberOfElements()).isEqualTo(countTargetsAll).isEqualTo(expectedTargets); } private void assertRSQLQueryThrowsException(final String rsqlParam) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java index 08918a12b..9b1452fb6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java @@ -22,7 +22,6 @@ import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule; import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Slice; import io.qameta.allure.Description; @@ -155,11 +154,11 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest { createDistributionSetForTenant(anotherTenant); // ensure both tenants see their distribution sets - final Page findDistributionSetsForTenant = findDistributionSetForTenant(tenant); + final Slice findDistributionSetsForTenant = findDistributionSetForTenant(tenant); assertThat(findDistributionSetsForTenant).hasSize(1); assertThat(findDistributionSetsForTenant.getContent().get(0).getTenant().toUpperCase()) .isEqualTo(tenant.toUpperCase()); - final Page findDistributionSetsForAnotherTenant = findDistributionSetForTenant(anotherTenant); + final Slice findDistributionSetsForAnotherTenant = findDistributionSetForTenant(anotherTenant); assertThat(findDistributionSetsForAnotherTenant).hasSize(1); assertThat(findDistributionSetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase()) .isEqualTo(anotherTenant.toUpperCase()); @@ -188,7 +187,7 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest { return runAsTenant(tenant, () -> testdataFactory.createDistributionSet()); } - private Page findDistributionSetForTenant(final String tenant) throws Exception { + private Slice findDistributionSetForTenant(final String tenant) throws Exception { return runAsTenant(tenant, () -> distributionSetManagement.findByCompleted(PAGE, true)); } } diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java index b4dc0136f..06000715f 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.mgmt.rest.resource; import java.util.List; import java.util.stream.Collectors; + import javax.validation.ValidationException; import org.eclipse.hawkbit.mgmt.json.model.PagedList; @@ -83,15 +84,15 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting); - final Page findModulesAll; + final Page findRolloutsAll; if (rsqlParam != null) { - findModulesAll = this.rolloutManagement.findByRsql(pageable, rsqlParam, false); + findRolloutsAll = this.rolloutManagement.findByRsql(pageable, rsqlParam, false); } else { - findModulesAll = this.rolloutManagement.findAll(pageable, false); + findRolloutsAll = this.rolloutManagement.findAll(pageable, false); } - final List rest = MgmtRolloutMapper.toResponseRollout(findModulesAll.getContent()); - return ResponseEntity.ok(new PagedList<>(rest, findModulesAll.getTotalElements())); + final List rest = MgmtRolloutMapper.toResponseRollout(findRolloutsAll.getContent()); + return ResponseEntity.ok(new PagedList<>(rest, findRolloutsAll.getTotalElements())); } @Override @@ -114,16 +115,15 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { throw new RSQLParameterSyntaxException("Cannot create a Rollout with an empty target query filter!"); } targetFilterQueryManagement.verifyTargetFilterQuerySyntax(targetFilterQuery); - final DistributionSet distributionSet = distributionSetManagement.getValidAndComplete( - rolloutRequestBody.getDistributionSetId()); + final DistributionSet distributionSet = distributionSetManagement + .getValidAndComplete(rolloutRequestBody.getDistributionSetId()); final RolloutGroupConditions rolloutGroupConditions = MgmtRolloutMapper.fromRequest(rolloutRequestBody, true); final RolloutCreate create = MgmtRolloutMapper.fromRequest(entityFactory, rolloutRequestBody, distributionSet); Rollout rollout; if (rolloutRequestBody.getGroups() != null) { - final List rolloutGroups = rolloutRequestBody.getGroups() - .stream() + final List rolloutGroups = rolloutRequestBody.getGroups().stream() .map(mgmtRolloutGroup -> MgmtRolloutMapper.fromRequest(entityFactory, mgmtRolloutGroup)) .collect(Collectors.toList()); rollout = rolloutManagement.create(create, rolloutGroups, rolloutGroupConditions); diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java index f7b1e4f04..19a37ec5a 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java @@ -106,12 +106,11 @@ public class MgmtTargetResource implements MgmtTargetRestApi { final Slice findTargetsAll; final long countTargetsAll; if (rsqlParam != null) { - final Page findTargetPage = this.targetManagement.findByRsql(pageable, rsqlParam); - countTargetsAll = findTargetPage.getTotalElements(); - findTargetsAll = findTargetPage; + findTargetsAll = targetManagement.findByRsql(pageable, rsqlParam); + countTargetsAll = targetManagement.countByRsql(rsqlParam); } else { - findTargetsAll = this.targetManagement.findAll(pageable); - countTargetsAll = this.targetManagement.count(); + findTargetsAll = targetManagement.findAll(pageable); + countTargetsAll = targetManagement.count(); } final List rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent()); @@ -165,7 +164,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi { } @Override - public ResponseEntity assignTargetType(@PathVariable("targetId") final String targetId, @RequestBody final MgmtId targetTypeId) { + public ResponseEntity assignTargetType(@PathVariable("targetId") final String targetId, + @RequestBody final MgmtId targetTypeId) { this.targetManagement.assignType(targetId, targetTypeId.getId()); return ResponseEntity.ok().build(); } @@ -304,8 +304,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi { final List> offlineAssignments = dsAssignments.stream() .map(dsAssignment -> new SimpleEntry(targetId, dsAssignment.getId())) .collect(Collectors.toList()); - return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse( - deploymentManagement.offlineAssignedDistributionSets(offlineAssignments))); + return ResponseEntity.ok(MgmtDistributionSetMapper + .toResponse(deploymentManagement.offlineAssignedDistributionSets(offlineAssignments))); } findTargetWithExceptionIfNotFound(targetId); diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java index 45902c861..3b0610ad3 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java @@ -150,18 +150,15 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi { final Sort sorting = PagingUtility.sanitizeTargetSortParam(sortParam); final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting); - Page findTargetsAll; + final Page findTargetsAll; if (rsqlParam == null) { findTargetsAll = targetManagement.findByTag(pageable, targetTagId); - } else { findTargetsAll = targetManagement.findByRsqlAndTag(pageable, rsqlParam, targetTagId); } - final Long countTargetsAll = findTargetsAll.getTotalElements(); - final List rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent()); - return ResponseEntity.ok(new PagedList<>(rest, countTargetsAll)); + return ResponseEntity.ok(new PagedList<>(rest, findTargetsAll.getTotalElements())); } @Override diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTypeResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTypeResource.java index 029b0023b..2e19edcc9 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTypeResource.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTypeResource.java @@ -19,7 +19,6 @@ import org.eclipse.hawkbit.mgmt.json.model.targettype.MgmtTargetTypeRequestBodyP import org.eclipse.hawkbit.mgmt.json.model.targettype.MgmtTargetTypeRequestBodyPut; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTypeRestApi; -import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.TargetTypeManagement; @@ -48,7 +47,7 @@ public class MgmtTargetTypeResource implements MgmtTargetTypeRestApi { private final TargetTypeManagement targetTypeManagement; private final EntityFactory entityFactory; - public MgmtTargetTypeResource(TargetTypeManagement targetTypeManagement, final EntityFactory entityFactory) { + public MgmtTargetTypeResource(final TargetTypeManagement targetTypeManagement, final EntityFactory entityFactory) { this.targetTypeManagement = targetTypeManagement; this.entityFactory = entityFactory; } @@ -65,14 +64,15 @@ public class MgmtTargetTypeResource implements MgmtTargetTypeRestApi { final Sort sorting = PagingUtility.sanitizeTargetTypeSortParam(sortParam); final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting); - final Page findTargetTypesAll; + final Slice findTargetTypesAll; long countTargetTypesAll; if (rsqlParam != null) { - findTargetTypesAll= targetTypeManagement.findByRsql(pageable, rsqlParam); + findTargetTypesAll = targetTypeManagement.findByRsql(pageable, rsqlParam); + countTargetTypesAll = ((Page) findTargetTypesAll).getTotalElements(); } else { findTargetTypesAll = targetTypeManagement.findAll(pageable); + countTargetTypesAll = targetTypeManagement.count(); } - countTargetTypesAll = findTargetTypesAll.getTotalElements(); final List rest = MgmtTargetTypeMapper.toListResponse(findTargetTypesAll.getContent()); return ResponseEntity.ok(new PagedList<>(rest, countTargetTypesAll)); @@ -135,8 +135,8 @@ public class MgmtTargetTypeResource implements MgmtTargetTypeRestApi { public ResponseEntity addCompatibleDistributionSets(@PathVariable("targetTypeId") final Long targetTypeId, @RequestBody final List distributionSetTypeIds) { - targetTypeManagement.assignCompatibleDistributionSetTypes(targetTypeId, - distributionSetTypeIds.stream().map(MgmtDistributionSetTypeAssignment::getId).collect(Collectors.toList())); + targetTypeManagement.assignCompatibleDistributionSetTypes(targetTypeId, distributionSetTypeIds.stream() + .map(MgmtDistributionSetTypeAssignment::getId).collect(Collectors.toList())); return ResponseEntity.ok().build(); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/DsFilterParams.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/DsFilterParams.java index 4785469b0..6a4627475 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/DsFilterParams.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/DsFilterParams.java @@ -12,7 +12,6 @@ import java.io.Serializable; import java.util.Objects; import org.eclipse.hawkbit.ui.common.data.providers.DistributionSetManagementStateDataProvider; -import org.springframework.util.StringUtils; import com.google.common.base.MoreObjects; @@ -65,7 +64,7 @@ public class DsFilterParams implements Serializable { * String */ public void setSearchText(final String searchText) { - this.searchText = !StringUtils.isEmpty(searchText) ? String.format("%%%s%%", searchText) : null; + this.searchText = searchText; } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/SwFilterParams.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/SwFilterParams.java index 319ff1dcc..5167d1045 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/SwFilterParams.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/SwFilterParams.java @@ -12,7 +12,6 @@ import java.io.Serializable; import java.util.Objects; import org.eclipse.hawkbit.ui.common.data.providers.SoftwareModuleDataProvider; -import org.springframework.util.StringUtils; import com.google.common.base.MoreObjects; @@ -78,7 +77,7 @@ public class SwFilterParams implements Serializable { * String */ public void setSearchText(final String searchText) { - this.searchText = !StringUtils.isEmpty(searchText) ? String.format("%%%s%%", searchText) : null; + this.searchText = searchText; } /** diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/RolloutGroupToAdvancedDefinitionMapper.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/RolloutGroupToAdvancedDefinitionMapper.java index 6c8445044..be663dc6d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/RolloutGroupToAdvancedDefinitionMapper.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/RolloutGroupToAdvancedDefinitionMapper.java @@ -17,8 +17,8 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyAdvancedRolloutGroup; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetFilterQueryInfo; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; import org.springframework.util.StringUtils; /** @@ -55,9 +55,9 @@ public class RolloutGroupToAdvancedDefinitionMapper { final String groupTargetFilterQuery = rolloutGroup.getTargetFilterQuery(); if (!StringUtils.isEmpty(groupTargetFilterQuery)) { advancedGroupRow.setTargetFilterQuery(groupTargetFilterQuery); - final Page filterQueries = targetFilterQueryManagement.findByQuery(PageRequest.of(0, 1), + final Slice filterQueries = targetFilterQueryManagement.findByQuery(PageRequest.of(0, 1), groupTargetFilterQuery); - if (filterQueries.getTotalElements() == 1) { + if (filterQueries.getNumberOfElements() == 1) { final TargetFilterQuery tfq = filterQueries.getContent().get(0); advancedGroupRow.setTargetFilterQueryInfo( new ProxyTargetFilterQueryInfo(tfq.getId(), tfq.getName(), tfq.getQuery())); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/RolloutToProxyRolloutMapper.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/RolloutToProxyRolloutMapper.java index 0a4968775..b29d8564a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/RolloutToProxyRolloutMapper.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/RolloutToProxyRolloutMapper.java @@ -26,8 +26,7 @@ public class RolloutToProxyRolloutMapper extends AbstractNamedEntityToProxyNamed mapNamedEntityAttributes(rollout, proxyRollout); final DistributionSet ds = rollout.getDistributionSet(); - proxyRollout.setDsInfo(new ProxyDistributionSetInfo(ds.getId(), ds.getName(), ds.getVersion(), - ds.getType().getId(), ds.isValid())); + proxyRollout.setDsInfo(new ProxyDistributionSetInfo(ds.getId(), ds.getName(), ds.getVersion(), ds.isValid())); proxyRollout .setNumberOfGroups(rollout.getRolloutGroupsCreated() > 0 ? rollout.getRolloutGroupsCreated() : null); proxyRollout.setForcedTime(rollout.getForcedTime() > 0 ? rollout.getForcedTime() : null); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/TargetFilterQueryToProxyTargetFilterMapper.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/TargetFilterQueryToProxyTargetFilterMapper.java index b01d706b9..00e8a212e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/TargetFilterQueryToProxyTargetFilterMapper.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/mappers/TargetFilterQueryToProxyTargetFilterMapper.java @@ -38,8 +38,7 @@ public class TargetFilterQueryToProxyTargetFilterMapper if (distributionSet != null) { proxyTargetFilter.setAutoAssignmentEnabled(true); proxyTargetFilter.setDistributionSetInfo(new ProxyDistributionSetInfo(distributionSet.getId(), - distributionSet.getName(), distributionSet.getVersion(), distributionSet.getType().getId(), - distributionSet.isValid())); + distributionSet.getName(), distributionSet.getVersion(), distributionSet.isValid())); proxyTargetFilter.setAutoAssignActionType(targetFilterQuery.getAutoAssignActionType()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/ActionStatusDataProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/ActionStatusDataProvider.java index 6a305e482..a6da5894c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/ActionStatusDataProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/ActionStatusDataProvider.java @@ -61,6 +61,6 @@ public class ActionStatusDataProvider extends AbstractProxyDataProvider loadBackendEntities(final PageRequest pageRequest, + protected Slice loadBackendEntities(final PageRequest pageRequest, final DsDistributionsFilterParams filter) { + return distributionSetManagement.findByDistributionSetFilter(pageRequest, buildDsFilter(filter)); + } + + private DistributionSetFilter buildDsFilter(final DsDistributionsFilterParams filter) { final DistributionSetFilterBuilder builder = new DistributionSetFilterBuilder().setIsDeleted(false); if (filter != null) { - final DistributionSetType type = filter.getDsTypeId() == null ? null - : distributionSetTypeManagement.get(filter.getDsTypeId()).orElse(null); - - builder.setSearchText(filter.getSearchText()).setSelectDSWithNoTag(false).setType(type); + builder.setSearchText(filter.getSearchText()).setSelectDSWithNoTag(false).setTypeId(filter.getDsTypeId()); } - return distributionSetManagement.findByDistributionSetFilter(pageRequest, builder.build()); + return builder.build(); } @Override protected long sizeInBackEnd(final PageRequest pageRequest, final DsDistributionsFilterParams filter) { - return loadBackendEntities(PageRequest.of(0, 1), filter).getTotalElements(); + return distributionSetManagement.countByDistributionSetFilter(buildDsFilter(filter)); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DistributionSetManagementStateDataProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DistributionSetManagementStateDataProvider.java index 4b08ccd60..8a8650302 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DistributionSetManagementStateDataProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DistributionSetManagementStateDataProvider.java @@ -10,12 +10,13 @@ package org.eclipse.hawkbit.ui.common.data.providers; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.DistributionSetFilter; import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder; import org.eclipse.hawkbit.ui.common.data.filters.DsManagementFilterParams; import org.eclipse.hawkbit.ui.common.data.mappers.DistributionSetToProxyDistributionMapper; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSet; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; import org.springframework.util.StringUtils; /** @@ -46,28 +47,34 @@ public class DistributionSetManagementStateDataProvider } @Override - protected Page loadBackendEntities(final PageRequest pageRequest, + protected Slice loadBackendEntities(final PageRequest pageRequest, final DsManagementFilterParams filter) { if (filter == null) { return distributionSetManagement.findByCompleted(pageRequest, true); } final String pinnedControllerId = filter.getPinnedTargetControllerId(); - final DistributionSetFilterBuilder builder = new DistributionSetFilterBuilder().setIsDeleted(false) - .setIsComplete(true).setSearchText(filter.getSearchText()).setSelectDSWithNoTag(filter.isNoTagClicked()) - .setTagNames(filter.getDistributionSetTags()); - if (!StringUtils.isEmpty(pinnedControllerId)) { - return distributionSetManagement.findByFilterAndAssignedInstalledDsOrderedByLinkTarget(pageRequest, builder, - pinnedControllerId); + return distributionSetManagement.findByDistributionSetFilterOrderByLinkedTarget(pageRequest, + buildDsFilter(filter), pinnedControllerId); } - return distributionSetManagement.findByDistributionSetFilter(pageRequest, builder.build()); + return distributionSetManagement.findByDistributionSetFilter(pageRequest, buildDsFilter(filter)); + } + + private DistributionSetFilter buildDsFilter(final DsManagementFilterParams filter) { + return new DistributionSetFilterBuilder().setIsDeleted(false).setIsComplete(true) + .setSearchText(filter.getSearchText()).setSelectDSWithNoTag(filter.isNoTagClicked()) + .setTagNames(filter.getDistributionSetTags()).build(); } @Override protected long sizeInBackEnd(final PageRequest pageRequest, final DsManagementFilterParams filter) { - return loadBackendEntities(PageRequest.of(0, 1), filter).getTotalElements(); + if (filter == null) { + return distributionSetManagement.countByCompleted(true); + } + + return distributionSetManagement.countByDistributionSetFilter(buildDsFilter(filter)); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DistributionSetStatelessDataProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DistributionSetStatelessDataProvider.java index 88175096f..c5adc84a1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DistributionSetStatelessDataProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DistributionSetStatelessDataProvider.java @@ -10,11 +10,12 @@ package org.eclipse.hawkbit.ui.common.data.providers; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.DistributionSetFilter; import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder; import org.eclipse.hawkbit.ui.common.data.mappers.DistributionSetToProxyDistributionMapper; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSet; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.util.StringUtils; @@ -47,19 +48,22 @@ public class DistributionSetStatelessDataProvider } @Override - protected Page loadBackendEntities(final PageRequest pageRequest, final String filter) { - final DistributionSetFilterBuilder builder = new DistributionSetFilterBuilder().setIsDeleted(false) - .setIsComplete(true).setIsValid(true); + protected Slice loadBackendEntities(final PageRequest pageRequest, final String filter) { + return distributionSetManagement.findByDistributionSetFilter(pageRequest, buildDsFilter(filter)); + } + private DistributionSetFilter buildDsFilter(final String filter) { + final DistributionSetFilterBuilder dsFilterBuilder = new DistributionSetFilterBuilder().setIsDeleted(false) + .setIsComplete(true).setIsValid(true); if (!StringUtils.isEmpty(filter)) { - builder.setFilterString(filter); + dsFilterBuilder.setSearchText(filter); } - return distributionSetManagement.findByDistributionSetFilter(pageRequest, builder.build()); + return dsFilterBuilder.build(); } @Override protected long sizeInBackEnd(final PageRequest pageRequest, final String filter) { - return loadBackendEntities(PageRequest.of(0, 1), filter).getTotalElements(); + return distributionSetManagement.countByDistributionSetFilter(buildDsFilter(filter)); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DsMetaDataDataProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DsMetaDataDataProvider.java index ab8929090..7a54ac373 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DsMetaDataDataProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/DsMetaDataDataProvider.java @@ -51,6 +51,6 @@ public class DsMetaDataDataProvider extends AbstractMetaDataDataProvider loadBackendEntities(final PageRequest pageRequest, final Long dsId) { + protected Slice loadBackendEntities(final PageRequest pageRequest, final Long dsId) { if (dsId == null) { return Page.empty(pageRequest); } - return targetFilterQueryManagement.findByAutoAssignDSAndRsql(pageRequest, dsId, null); + return targetFilterQueryManagement.findByAutoAssignDistributionSetId(pageRequest, dsId); } @Override @@ -58,6 +59,6 @@ public class TargetFilterQueryDetailsDataProvider return 0L; } - return loadBackendEntities(PageRequest.of(0, 1), dsId).getTotalElements(); + return targetFilterQueryManagement.countByAutoAssignDistributionSetId(dsId); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetMetaDataDataProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetMetaDataDataProvider.java index 4358b0d7e..13675e1d6 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetMetaDataDataProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetMetaDataDataProvider.java @@ -52,7 +52,6 @@ public class TargetMetaDataDataProvider extends AbstractMetaDataDataProvider * Constructor * * @param targetTypeManagement - * TargetTypeManagement + * TargetTypeManagement * @param mapper - * Mapper + * Mapper */ - public TargetTypeDataProvider(final TargetTypeManagement targetTypeManagement, IdentifiableEntityToProxyIdentifiableEntityMapper mapper) { + public TargetTypeDataProvider(final TargetTypeManagement targetTypeManagement, + final IdentifiableEntityToProxyIdentifiableEntityMapper mapper) { super(mapper, Sort.by(Direction.ASC, "name")); this.targetTypeManagement = targetTypeManagement; } @Override - protected Page loadBackendEntities(PageRequest pageRequest, String filter) { - if (!StringUtils.isEmpty(filter)){ - return targetTypeManagement.findByName(pageRequest, filter); + protected Slice loadBackendEntities(final PageRequest pageRequest, final String filter) { + if (StringUtils.isEmpty(filter)) { + return targetTypeManagement.findAll(pageRequest); } - return targetTypeManagement.findAll(pageRequest); + + return targetTypeManagement.findByName(pageRequest, filter); } @Override - protected long sizeInBackEnd(PageRequest pageRequest, String filter) { - return loadBackendEntities(PageRequest.of(0, 1), filter).getTotalElements(); + protected long sizeInBackEnd(final PageRequest pageRequest, final String filter) { + if (StringUtils.isEmpty(filter)) { + return targetTypeManagement.count(); + } + + return targetTypeManagement.countByName(filter); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/proxies/ProxyDistributionSet.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/proxies/ProxyDistributionSet.java index a7a700621..fa9dd4e4d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/proxies/ProxyDistributionSet.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/proxies/ProxyDistributionSet.java @@ -162,7 +162,6 @@ public class ProxyDistributionSet extends ProxyNamedEntity implements VersionAwa ds.setId(dsInfo.getId()); ds.setName(dsInfo.getName()); ds.setVersion(dsInfo.getVersion()); - ds.setTypeInfo(new ProxyTypeInfo(dsInfo.getDsTypeId(), null)); ds.setNameVersion(dsInfo.getNameVersion()); ds.setIsValid(dsInfo.isValid()); @@ -170,12 +169,12 @@ public class ProxyDistributionSet extends ProxyNamedEntity implements VersionAwa } /** - * Gets the Id, name, version, dsTypeId and invalidation state of distribution - * set + * Gets the Id, name, version, dsTypeId and invalidation state of + * distribution set * * @return proxy of Id, name, version, dsTypeId and invalidation state */ public ProxyDistributionSetInfo getInfo() { - return new ProxyDistributionSetInfo(getId(), getName(), getVersion(), getTypeInfo().getId(), getIsValid()); + return new ProxyDistributionSetInfo(getId(), getName(), getVersion(), getIsValid()); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/proxies/ProxyDistributionSetInfo.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/proxies/ProxyDistributionSetInfo.java index 53bed4a2f..9a926239e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/proxies/ProxyDistributionSetInfo.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/proxies/ProxyDistributionSetInfo.java @@ -21,7 +21,6 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity { private String name; private String version; private String nameVersion; - private Long dsTypeId; private boolean isValid; /** @@ -40,18 +39,14 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity { * distribution set name * @param version * distribution set version - * @param dsTypeId - * ID of the assigned dsType * @param isValid * invalidation state */ - public ProxyDistributionSetInfo(final Long id, final String name, final String version, final Long dsTypeId, - final boolean isValid) { + public ProxyDistributionSetInfo(final Long id, final String name, final String version, final boolean isValid) { super(id); this.name = name; this.version = version; - this.dsTypeId = dsTypeId; this.isValid = isValid; this.nameVersion = HawkbitCommonUtil.getFormattedNameVersion(name, version); } @@ -88,19 +83,11 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity { this.isValid = isValid; } - public Long getDsTypeId() { - return dsTypeId; - } - - public void setDsTypeId(final Long dsTypeId) { - this.dsTypeId = dsTypeId; - } - @Override public int hashCode() { // nameVersion is ignored because it is a composition of name and // version - return Objects.hash(getId(), getName(), getVersion(), getDsTypeId(), isValid()); + return Objects.hash(getId(), getName(), getVersion(), isValid()); } // equals method requires all of the used conditions @@ -119,7 +106,6 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity { // version return Objects.equals(this.getId(), other.getId()) && Objects.equals(this.getName(), other.getName()) && Objects.equals(this.getVersion(), other.getVersion()) - && Objects.equals(this.getDsTypeId(), other.getDsTypeId()) && Objects.equals(this.isValid(), other.isValid()); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/SwModulesToDistributionSetAssignmentSupport.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/SwModulesToDistributionSetAssignmentSupport.java index 077da07b7..0d1601574 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/SwModulesToDistributionSetAssignmentSupport.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/SwModulesToDistributionSetAssignmentSupport.java @@ -115,7 +115,7 @@ public class SwModulesToDistributionSetAssignmentSupport return false; } - if (!ds.getIsValid()) { + if (Boolean.FALSE.equals(ds.getIsValid())) { /* Distribution is invalidated */ addSpecificValidationErrorMessage( i18n.getMessage(UIMessageIdProvider.MESSAGE_ERROR_DISTRIBUTIONSET_INVALID, ds.getNameVersion())); @@ -145,8 +145,8 @@ public class SwModulesToDistributionSetAssignmentSupport private boolean checkDuplicateSmToDsAssignment(final ProxySoftwareModule sm, final ProxyDistributionSet ds, final Collection smIdsAlreadyAssignedToDs) { if (!CollectionUtils.isEmpty(smIdsAlreadyAssignedToDs) && smIdsAlreadyAssignedToDs.contains(sm.getId())) { - addSpecificValidationErrorMessage(i18n.getMessage("message.software.dist.already.assigned", sm.getNameAndVersion(), - ds.getNameVersion())); + addSpecificValidationErrorMessage(i18n.getMessage("message.software.dist.already.assigned", + sm.getNameAndVersion(), ds.getNameVersion())); return false; } @@ -158,8 +158,8 @@ public class SwModulesToDistributionSetAssignmentSupport if (!dsType.containsModuleType(sm.getTypeInfo().getId())) { final String smTypeName = smTypeManagement.get(sm.getTypeInfo().getId()).map(SoftwareModuleType::getName) .orElse(""); - addSpecificValidationErrorMessage(i18n.getMessage("message.software.dist.type.notallowed", sm.getNameAndVersion(), - ds.getNameVersion(), smTypeName)); + addSpecificValidationErrorMessage(i18n.getMessage("message.software.dist.type.notallowed", + sm.getNameAndVersion(), ds.getNameVersion(), smTypeName)); return false; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetGrid.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetGrid.java index 8fbfa748f..828ad558b 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetGrid.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetGrid.java @@ -82,8 +82,7 @@ public class DistributionSetGrid extends AbstractDsGrid( - new DistributionSetDistributionsStateDataProvider(dsManagement, dsTypeManagement, - dsToProxyDistributionMapper), + new DistributionSetDistributionsStateDataProvider(dsManagement, dsToProxyDistributionMapper), DsDistributionsFilterParams::new, getSelectionSupport()::deselectAll)); initFilterMappings(); getFilterSupport().setFilter(new DsDistributionsFilterParams()); @@ -105,10 +104,10 @@ public class DistributionSetGrid extends AbstractDsGrid filterQueryChangedListener; - private Consumer distSetChangedListener; + private Consumer filterQueryChangedListener; + private Consumer distSetChangedListener; /** * Constructor for RolloutFormLayout @@ -204,7 +204,7 @@ public class RolloutFormLayout extends ValidatableLayout { private HasValue.ValueChangeListener filterQueryChangedListener() { return event -> { if (filterQueryChangedListener != null) { - filterQueryChangedListener.accept(event.getValue() != null ? event.getValue().getQuery() : null); + filterQueryChangedListener.accept(event.getValue()); } }; } @@ -212,11 +212,7 @@ public class RolloutFormLayout extends ValidatableLayout { private HasValue.ValueChangeListener distSetChangedListener() { return event -> { if (distSetChangedListener != null) { - if (event.getValue() != null && event.getValue().getTypeInfo() != null) { - distSetChangedListener.accept(event.getValue().getTypeInfo().getId()); - } else { - distSetChangedListener.accept(null); - } + distSetChangedListener.accept(event.getValue()); } }; } @@ -300,7 +296,7 @@ public class RolloutFormLayout extends ValidatableLayout { * @param filterQueryChangedListener * Changed listener */ - public void setFilterQueryChangedListener(final Consumer filterQueryChangedListener) { + public void setFilterQueryChangedListener(final Consumer filterQueryChangedListener) { this.filterQueryChangedListener = filterQueryChangedListener; } @@ -310,7 +306,7 @@ public class RolloutFormLayout extends ValidatableLayout { * @param distSetChangedListener * Changed listener */ - public void setDistSetChangedListener(final Consumer distSetChangedListener) { + public void setDistSetChangedListener(final Consumer distSetChangedListener) { this.distSetChangedListener = distSetChangedListener; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/controllers/CopyRolloutWindowController.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/controllers/CopyRolloutWindowController.java index 4b4ce3af5..e7a814e24 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/controllers/CopyRolloutWindowController.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/controllers/CopyRolloutWindowController.java @@ -25,8 +25,8 @@ import org.eclipse.hawkbit.ui.rollout.window.RolloutWindowDependencies; import org.eclipse.hawkbit.ui.rollout.window.components.AutoStartOptionGroupLayout.AutoStartOption; import org.eclipse.hawkbit.ui.rollout.window.layouts.AddRolloutWindowLayout; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; import org.springframework.util.CollectionUtils; /** @@ -94,9 +94,9 @@ public class CopyRolloutWindowController extends AddRolloutWindowController { } private void setTargetFilterId(final ProxyRolloutWindow proxyRolloutWindow) { - final Page filterQueries = targetFilterQueryManagement.findByQuery(PageRequest.of(0, 1), + final Slice filterQueries = targetFilterQueryManagement.findByQuery(PageRequest.of(0, 1), proxyRolloutWindow.getTargetFilterQuery()); - if (filterQueries.getTotalElements() > 0) { + if (filterQueries.getNumberOfElements() > 0) { final TargetFilterQuery tfq = filterQueries.getContent().get(0); proxyRolloutWindow .setTargetFilterInfo(new ProxyTargetFilterQueryInfo(tfq.getId(), tfq.getName(), tfq.getQuery())); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/layouts/AddRolloutWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/layouts/AddRolloutWindowLayout.java index 3de8a10db..4345b47c9 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/layouts/AddRolloutWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/layouts/AddRolloutWindowLayout.java @@ -11,10 +11,15 @@ package org.eclipse.hawkbit.ui.rollout.window.layouts; import java.util.Arrays; import java.util.List; +import javax.validation.constraints.NotNull; + +import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyAdvancedRolloutGroup; +import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSet; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyRolloutWindow; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyRolloutWindow.GroupDefinitionMode; +import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetFilterQuery; import org.eclipse.hawkbit.ui.rollout.window.RolloutWindowDependencies; import org.eclipse.hawkbit.ui.rollout.window.components.AdvancedGroupsLayout; import org.eclipse.hawkbit.ui.rollout.window.components.RolloutFormLayout; @@ -34,6 +39,7 @@ import com.vaadin.ui.TabSheet; public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout { private final TargetManagement targetManagement; + private final DistributionSetManagement dsManagement; private final RolloutFormLayout rolloutFormLayout; private final SimpleGroupsLayout simpleGroupsLayout; @@ -57,6 +63,7 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout { super(dependencies); this.targetManagement = dependencies.getTargetManagement(); + this.dsManagement = dependencies.getDistributionSetManagement(); this.rolloutFormLayout = rolloutComponentBuilder.createRolloutFormLayout(); this.simpleGroupsLayout = rolloutComponentBuilder.createSimpleGroupsLayout(); @@ -90,8 +97,8 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout { advancedGroupsLayout.setAdvancedGroupDefinitionsChangedListener(this::onAdvancedGroupsChanged); } - private void onFilterQueryChange(final String filterQuery) { - this.filterQuery = filterQuery; + private void onFilterQueryChange(final ProxyTargetFilterQuery targetFilterQuery) { + filterQuery = targetFilterQuery != null ? targetFilterQuery.getQuery() : null; updateTotalTargets(); if (isAdvancedGroupsTabSelected()) { @@ -99,8 +106,8 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout { } } - private void onDistSetTypeChange(final Long dsTypeId) { - this.dsTypeId = dsTypeId; + private void onDistSetTypeChange(final ProxyDistributionSet ds) { + dsTypeId = ds != null ? getDsTypeId(ds) : null; updateTotalTargets(); if (isAdvancedGroupsTabSelected()) { @@ -108,8 +115,16 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout { } } + private Long getDsTypeId(final @NotNull ProxyDistributionSet ds) { + if (ds.getTypeInfo() != null) { + return ds.getTypeInfo().getId(); + } + + return dsManagement.get(ds.getId()).map(dist -> dist.getType().getId()).orElse(null); + } + private void updateTotalTargets() { - this.totalTargets = getTotalTargets(filterQuery, dsTypeId); + totalTargets = getTotalTargets(filterQuery, dsTypeId); rolloutFormLayout.setTotalTargets(totalTargets); visualGroupDefinitionLayout.setTotalTargets(totalTargets); if (isSimpleGroupsTabSelected()) {