Optimize UI queries (#1234)

* first iteration of query optimization for target and distribution set
* fixed type distribution set filter
* adapted all ui dataproviders to use repository count
* adapted test to not check target attributes within search query
* unified search behaviuor for ds and sm
* removed unneccessary count queries for some mgmt calls
* removed unneccessary type id proprty from ProxyDistributionSetInfo to minimize lazy fetches
* refactored mgmt classes
* removed duplication of name version filter
* fixed copy rollout compatibility check
* cleaned-up management left overs
* added index to rollouts table on tenant/status queries

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io>
This commit is contained in:
Bondar Bogdan
2022-03-23 09:08:56 +01:00
committed by GitHub
parent 681df6c1f1
commit c9eafbbc26
74 changed files with 1444 additions and 1617 deletions

View File

@@ -160,6 +160,19 @@ public interface ArtifactManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<Artifact> findBySoftwareModule(@NotNull Pageable pageReq, long swId); Page<Artifact> 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}. * Loads {@link DbArtifact} from store for given {@link Artifact}.
* *

View File

@@ -331,7 +331,7 @@ public interface DeploymentManagement {
/** /**
* Retrieves all the {@link ActionStatus} entries of the given * Retrieves all the {@link ActionStatus} entries of the given
* {@link Action} and {@link Target}. * {@link Action}.
* *
* @param pageReq * @param pageReq
* pagination parameter * pagination parameter
@@ -345,6 +345,19 @@ public interface DeploymentManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<ActionStatus> findActionStatusByAction(@NotNull Pageable pageReq, long actionId); Page<ActionStatus> 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}. * Retrieves all messages for an {@link ActionStatus}.
* *
@@ -358,6 +371,19 @@ public interface DeploymentManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<String> findMessagesByActionStatusId(@NotNull Pageable pageable, long actionStatusId); Page<String> 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 * Get the {@link Action} entity for given actionId with all lazy attributes
* (i.e. distributionSet, target, target.assignedDs). * (i.e. distributionSet, target, target.assignedDs).

View File

@@ -29,7 +29,6 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldExc
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException; import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetFilter; 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.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; 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.eclipse.hawkbit.repository.model.Target;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
/** /**
@@ -244,6 +244,22 @@ public interface DistributionSetManagement
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<DistributionSetMetadata> findMetaDataByDistributionSetId(@NotNull Pageable pageable, long setId); Page<DistributionSetMetadata> 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. * Finds all meta data by the given distribution set id.
* *
@@ -272,7 +288,7 @@ public interface DistributionSetManagement
@NotNull String rsqlParam); @NotNull String rsqlParam);
/** /**
* Finds all {@link DistributionSet}s. * Finds all {@link DistributionSet}s based on completeness.
* *
* @param pageable * @param pageable
* the pagination parameter * the pagination parameter
@@ -284,7 +300,33 @@ public interface DistributionSetManagement
* @return all found {@link DistributionSet}s * @return all found {@link DistributionSet}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<DistributionSet> findByCompleted(@NotNull Pageable pageable, Boolean complete); Slice<DistributionSet> findByCompleted(@NotNull Pageable pageable, Boolean complete);
/**
* Counts all {@link DistributionSet}s based on completeness.
*
* @param complete
* to <code>true</code> for counting only completed distribution
* sets or <code>false</code> for only incomplete ones nor
* <code>null</code> 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<DistributionSet> findByDistributionSetFilter(@NotNull Pageable pageable,
@NotNull DistributionSetFilter distributionSetFilter);
/** /**
* Method retrieves all {@link DistributionSet}s from the repository in the * Method retrieves all {@link DistributionSet}s from the repository in the
@@ -301,29 +343,27 @@ public interface DistributionSetManagement
* *
* @param pageable * @param pageable
* the page request to page the result set * * the page request to page the result set *
* @param distributionSetFilterBuilder * @param distributionSetFilter
* has details of filters to be applied * has details of filters to be applied.
* @param assignedOrInstalled * @param assignedOrInstalled
* the id of the Target to be ordered by * the id of the Target to be ordered by
* *
* @return {@link DistributionSet}s * @return {@link DistributionSet}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<DistributionSet> findByFilterAndAssignedInstalledDsOrderedByLinkTarget(@NotNull Pageable pageable, Slice<DistributionSet> findByDistributionSetFilterOrderByLinkedTarget(@NotNull Pageable pageable,
@NotNull DistributionSetFilterBuilder distributionSetFilterBuilder, @NotEmpty String assignedOrInstalled); @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 * @param distributionSetFilter
* has details of filters to be applied. * 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) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<DistributionSet> findByDistributionSetFilter(@NotNull Pageable pageable, long countByDistributionSetFilter(@NotNull DistributionSetFilter distributionSetFilter);
@NotNull DistributionSetFilter distributionSetFilter);
/** /**
* Retrieves {@link DistributionSet}s by filtering on the given parameters. * Retrieves {@link DistributionSet}s by filtering on the given parameters.

View File

@@ -181,8 +181,8 @@ public interface RolloutManagement {
RolloutGroupConditions conditions); RolloutGroupConditions conditions);
/** /**
* Calculates how many targets are addressed by each rollout group and returns * Calculates how many targets are addressed by each rollout group and
* the validation information. * returns the validation information.
* *
* @param groups * @param groups
* a list of rollout groups * a list of rollout groups
@@ -226,7 +226,7 @@ public interface RolloutManagement {
* statuses * statuses
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ)
Page<Rollout> findAllWithDetailedStatus(@NotNull Pageable pageable, boolean deleted); Slice<Rollout> findAllWithDetailedStatus(@NotNull Pageable pageable, boolean deleted);
/** /**
* Retrieves all rollouts found by the given specification. * Retrieves all rollouts found by the given specification.

View File

@@ -220,6 +220,20 @@ public interface SoftwareModuleManagement
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<SoftwareModuleMetadata> findMetaDataBySoftwareModuleId(@NotNull Pageable pageable, long moduleId); Page<SoftwareModuleMetadata> 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 * Finds all meta data by the given software module id where
* {@link SoftwareModuleMetadata#isTargetVisible()}. * {@link SoftwareModuleMetadata#isTargetVisible()}.

View File

@@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
/** /**
@@ -96,7 +97,7 @@ public interface TargetFilterQueryManagement {
* @return the found {@link TargetFilterQuery}s * @return the found {@link TargetFilterQuery}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<TargetFilterQuery> findAll(@NotNull Pageable pageable); Slice<TargetFilterQuery> findAll(@NotNull Pageable pageable);
/** /**
* Counts all {@link TargetFilterQuery}s. * Counts all {@link TargetFilterQuery}s.
@@ -128,7 +129,17 @@ public interface TargetFilterQueryManagement {
* @return the page with the found {@link TargetFilterQuery}s * @return the page with the found {@link TargetFilterQuery}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<TargetFilterQuery> findByName(@NotNull Pageable pageable, @NotNull String name); Slice<TargetFilterQuery> 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 * 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 * @return the page with the found {@link TargetFilterQuery}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<TargetFilterQuery> findByQuery(@NotNull Pageable pageable, @NotNull String query); Slice<TargetFilterQuery> 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<TargetFilterQuery> findByAutoAssignDistributionSetId(@NotNull Pageable pageable, long setId);
/** /**
* Retrieves all {@link TargetFilterQuery}s which match the given * Retrieves all {@link TargetFilterQuery}s which match the given
@@ -181,7 +208,7 @@ public interface TargetFilterQueryManagement {
* @param pageable * @param pageable
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<TargetFilterQuery> findWithAutoAssignDS(@NotNull Pageable pageable); Slice<TargetFilterQuery> findWithAutoAssignDS(@NotNull Pageable pageable);
/** /**
* Finds the {@link TargetFilterQuery} by id. * Finds the {@link TargetFilterQuery} by id.

View File

@@ -8,6 +8,16 @@
*/ */
package org.eclipse.hawkbit.repository; 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.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.TargetCreate; import org.eclipse.hawkbit.repository.builder.TargetCreate;
import org.eclipse.hawkbit.repository.builder.TargetUpdate; 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.data.domain.Slice;
import org.springframework.security.access.prepost.PreAuthorize; 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. * Management service for {@link Target}s.
* *
@@ -109,7 +110,9 @@ public interface TargetManagement {
* @throws EntityNotFoundException * @throws EntityNotFoundException
* if distribution set with given ID does not exist * 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 @Deprecated
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
@@ -146,7 +149,8 @@ public interface TargetManagement {
long countByInstalledDistributionSet(long distId); 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 * @param distId
* to search for * to search for
@@ -170,8 +174,8 @@ public interface TargetManagement {
long countByRsql(@NotEmpty String rsqlParam); long countByRsql(@NotEmpty String rsqlParam);
/** /**
* Count all targets for given {@link TargetFilterQuery} and that are compatible * Count all targets for given {@link TargetFilterQuery} and that are
* with the passed {@link DistributionSetType}. * compatible with the passed {@link DistributionSetType}.
* *
* @param rsqlParam * @param rsqlParam
* filter definition in RSQL syntax * filter definition in RSQL syntax
@@ -190,7 +194,7 @@ public interface TargetManagement {
* {@link TargetFilterQuery#getId()} * {@link TargetFilterQuery#getId()}
* @return the found number of {@link Target}s * @return the found number of {@link Target}s
* *
* @throws EntityNotFoundException * @throws EntityNotFoundException
* if {@link TargetFilterQuery} with given ID does not exist * if {@link TargetFilterQuery} with given ID does not exist
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
@@ -265,9 +269,9 @@ public interface TargetManagement {
void deleteByControllerID(@NotEmpty String controllerID); void deleteByControllerID(@NotEmpty String controllerID);
/** /**
* Finds all targets for all the given parameter {@link TargetFilterQuery} and * Finds all targets for all the given parameter {@link TargetFilterQuery}
* that don't have the specified distribution set in their action history and * and that don't have the specified distribution set in their action
* are compatible with the passed {@link DistributionSetType}. * history and are compatible with the passed {@link DistributionSetType}.
* *
* @param pageRequest * @param pageRequest
* the pageRequest to enhance the query for paging and sorting * 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 * if distribution set with given ID does not exist
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<Target> findByTargetFilterQueryAndNonDSAndCompatible(@NotNull Pageable pageRequest, long distributionSetId, Slice<Target> findByTargetFilterQueryAndNonDSAndCompatible(@NotNull Pageable pageRequest, long distributionSetId,
@NotNull String rsqlParam); @NotNull String rsqlParam);
/** /**
* Counts all targets for all the given parameter {@link TargetFilterQuery} and * Counts all targets for all the given parameter {@link TargetFilterQuery}
* that don't have the specified distribution set in their action history and * and that don't have the specified distribution set in their action
* are compatible with the passed {@link DistributionSetType}. * history and are compatible with the passed {@link DistributionSetType}.
* *
* @param distributionSetId * @param distributionSetId
* id of the {@link DistributionSet} * id of the {@link DistributionSet}
@@ -302,9 +306,9 @@ public interface TargetManagement {
long countByRsqlAndNonDSAndCompatible(long distributionSetId, @NotNull String rsqlParam); long countByRsqlAndNonDSAndCompatible(long distributionSetId, @NotNull String rsqlParam);
/** /**
* Finds all targets for all the given parameter {@link TargetFilterQuery} and * Finds all targets for all the given parameter {@link TargetFilterQuery}
* that are not assigned to one of the {@link RolloutGroup}s and are compatible * and that are not assigned to one of the {@link RolloutGroup}s and are
* with the passed {@link DistributionSetType}. * compatible with the passed {@link DistributionSetType}.
* *
* @param pageRequest * @param pageRequest
* the pageRequest to enhance the query for paging and sorting * the pageRequest to enhance the query for paging and sorting
@@ -313,27 +317,27 @@ public interface TargetManagement {
* @param rsqlParam * @param rsqlParam
* filter definition in RSQL syntax * filter definition in RSQL syntax
* @param distributionSetType * @param distributionSetType
* type of the {@link DistributionSet} the targets must be compatible * type of the {@link DistributionSet} the targets must be
* with * compatible with
* @return a page of the found {@link Target}s * @return a page of the found {@link Target}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<Target> findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(@NotNull Pageable pageRequest, Slice<Target> findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(@NotNull Pageable pageRequest,
@NotEmpty Collection<Long> groups, @NotNull String rsqlParam, @NotEmpty Collection<Long> groups, @NotNull String rsqlParam,
@NotNull DistributionSetType distributionSetType); @NotNull DistributionSetType distributionSetType);
/** /**
* Counts all targets for all the given parameter {@link TargetFilterQuery} and * Counts all targets for all the given parameter {@link TargetFilterQuery}
* that are not assigned to one of the {@link RolloutGroup}s and are compatible * and that are not assigned to one of the {@link RolloutGroup}s and are
* with the passed {@link DistributionSetType}. * compatible with the passed {@link DistributionSetType}.
* *
* @param groups * @param groups
* the list of {@link RolloutGroup}s * the list of {@link RolloutGroup}s
* @param rsqlParam * @param rsqlParam
* filter definition in RSQL syntax * filter definition in RSQL syntax
* @param distributionSetType * @param distributionSetType
* type of the {@link DistributionSet} the targets must be compatible * type of the {@link DistributionSet} the targets must be
* with * compatible with
* @return count of the found {@link Target}s * @return count of the found {@link Target}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
@@ -354,7 +358,7 @@ public interface TargetManagement {
* if rollout group with given ID does not exist * if rollout group with given ID does not exist
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<Target> findByInRolloutGroupWithoutAction(@NotNull Pageable pageRequest, long group); Slice<Target> findByInRolloutGroupWithoutAction(@NotNull Pageable pageRequest, long group);
/** /**
* retrieves {@link Target}s by the assigned {@link DistributionSet}. * retrieves {@link Target}s by the assigned {@link DistributionSet}.
@@ -518,7 +522,7 @@ public interface TargetManagement {
* if the RSQL syntax is wrong * if the RSQL syntax is wrong
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<Target> findByRsql(@NotNull Pageable pageable, @NotNull String rsqlParam); Slice<Target> findByRsql(@NotNull Pageable pageable, @NotNull String rsqlParam);
/** /**
* Retrieves all target based on {@link TargetFilterQuery}. * 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 * 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 * 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 * yet assigned, they will be. Only if all of theme have the tag already
* they will be removed instead. * assigned they will be removed instead.
* *
* @param controllerIds * @param controllerIds
* to toggle for * to toggle for
@@ -627,12 +631,11 @@ public interface TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetTagAssignmentResult toggleTagAssignment(@NotEmpty Collection<String> controllerIds, @NotEmpty String tagName); TargetTagAssignmentResult toggleTagAssignment(@NotEmpty Collection<String> controllerIds, @NotEmpty String tagName);
/** /**
* Initiates {@link TargetType} assignment to given {@link Target}s. If some * Initiates {@link TargetType} assignment to given {@link Target}s. If some
* targets in the list have the {@link TargetType} not yet assigned, they will * targets in the list have the {@link TargetType} not yet assigned, they
* get assigned. If all targets are already of that type, there will be no * will get assigned. If all targets are already of that type, there will be
* un-assignment. * no un-assignment.
* *
* @param controllerIds * @param controllerIds
* to set the type to * to set the type to
@@ -648,8 +651,8 @@ public interface TargetManagement {
TargetTypeAssignmentResult assignType(@NotEmpty Collection<String> controllerIds, @NotNull Long typeId); TargetTypeAssignmentResult assignType(@NotEmpty Collection<String> controllerIds, @NotNull Long typeId);
/** /**
* Initiates {@link TargetType} un-assignment to given {@link Target}s. The type * Initiates {@link TargetType} un-assignment to given {@link Target}s. The
* of the targets will be set to {@code null} * type of the targets will be set to {@code null}
* *
* @param controllerIds * @param controllerIds
* to remove the type from * to remove the type from
@@ -851,6 +854,20 @@ public interface TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<TargetMetadata> findMetaDataByControllerId(@NotNull Pageable pageable, @NotEmpty String controllerId); Page<TargetMetadata> 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. * Finds all meta data by the given target id and query.
* *

View File

@@ -8,21 +8,23 @@
*/ */
package org.eclipse.hawkbit.repository; 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.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.builder.TargetTypeCreate; import org.eclipse.hawkbit.repository.builder.TargetTypeCreate;
import org.eclipse.hawkbit.repository.builder.TargetTypeUpdate; import org.eclipse.hawkbit.repository.builder.TargetTypeUpdate;
import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetType;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.security.access.prepost.PreAuthorize; 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. * Management service for {@link TargetType}s.
* *
@@ -43,9 +45,17 @@ public interface TargetTypeManagement {
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
long count(); 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 * @param create
* TargetTypeCreate * TargetTypeCreate
* @return targetType * @return targetType
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_CREATE_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
@@ -53,31 +63,32 @@ public interface TargetTypeManagement {
/** /**
* @param creates * @param creates
* List of TargetTypeCreate * List of TargetTypeCreate
* @return List of targetType * @return List of targetType
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_CREATE_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
List<TargetType> create(@NotEmpty @Valid Collection<TargetTypeCreate> creates); List<TargetType> create(@NotEmpty @Valid Collection<TargetTypeCreate> creates);
/** /**
* @param id targetTypeId * @param id
* targetTypeId
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_DELETE_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_DELETE_TARGET)
void delete(@NotNull Long id); void delete(@NotNull Long id);
/** /**
* @param pageable * @param pageable
* Page * Page
* @return TargetType page * @return TargetType page
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<TargetType> findAll(@NotNull Pageable pageable); Slice<TargetType> findAll(@NotNull Pageable pageable);
/** /**
* @param pageable * @param pageable
* Page * Page
* @param rsqlParam * @param rsqlParam
* query param * query param
* @return Target type * @return Target type
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
@@ -93,11 +104,11 @@ public interface TargetTypeManagement {
* @return the page of found {@link TargetType} * @return the page of found {@link TargetType}
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<TargetType> findByName(@NotNull Pageable pageable, String name); Slice<TargetType> findByName(@NotNull Pageable pageable, String name);
/** /**
* @param id * @param id
* Target type ID * Target type ID
* @return Target Type * @return Target Type
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
@@ -105,7 +116,7 @@ public interface TargetTypeManagement {
/** /**
* @param targetId * @param targetId
* Target ID * Target ID
* @return Target Type * @return Target Type
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
@@ -113,7 +124,7 @@ public interface TargetTypeManagement {
/** /**
* @param targetIds * @param targetIds
* List of Target ID * List of Target ID
* @return Target Type * @return Target Type
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
@@ -121,7 +132,7 @@ public interface TargetTypeManagement {
/** /**
* @param controllerId * @param controllerId
* Target controller ID * Target controller ID
* @return Target Type * @return Target Type
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
@@ -129,25 +140,23 @@ public interface TargetTypeManagement {
/** /**
* @param controllerIds * @param controllerIds
* List of Target controller ID * List of Target controller ID
* @return Target Type * @return Target Type
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
List<TargetType> findByTargetControllerIds(Collection<String> controllerIds); List<TargetType> findByTargetControllerIds(Collection<String> controllerIds);
/** /**
* @param ids * @param ids
* List of Target type ID * List of Target type ID
* @return Target type list * @return Target type list
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
List<TargetType> get(@NotEmpty Collection<Long> ids); List<TargetType> get(@NotEmpty Collection<Long> ids);
/** /**
* @param update * @param update
* TargetTypeUpdate * TargetTypeUpdate
* @return Target Type * @return Target Type
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
@@ -155,20 +164,20 @@ public interface TargetTypeManagement {
/** /**
* @param targetTypeId * @param targetTypeId
* Target type ID * Target type ID
* @param distributionSetTypeIds * @param distributionSetTypeIds
* Distribution set ID * Distribution set ID
* @return Target type * @return Target type
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
TargetType assignCompatibleDistributionSetTypes(long targetTypeId, TargetType assignCompatibleDistributionSetTypes(long targetTypeId,
@NotEmpty Collection<Long> distributionSetTypeIds); @NotEmpty Collection<Long> distributionSetTypeIds);
/** /**
* @param targetTypeId * @param targetTypeId
* Target type ID * Target type ID
* @param distributionSetTypeIds * @param distributionSetTypeIds
* Distribution set ID * Distribution set ID
* @return Target type * @return Target type
*/ */
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET) @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)

View File

@@ -21,9 +21,8 @@ public final class DistributionSetFilter {
private Boolean isDeleted; private Boolean isDeleted;
private Boolean isComplete; private Boolean isComplete;
private Boolean isValid; private Boolean isValid;
private DistributionSetType type; private Long typeId;
private String searchText; private String searchText;
private String filterString;
private Boolean selectDSWithNoTag; private Boolean selectDSWithNoTag;
private Collection<String> tagNames; private Collection<String> tagNames;
private String assignedTargetId; private String assignedTargetId;
@@ -68,11 +67,6 @@ public final class DistributionSetFilter {
return this; return this;
} }
public DistributionSetFilterBuilder setFilterString(final String filterString) {
this.filterString = filterString;
return this;
}
public DistributionSetFilterBuilder setSelectDSWithNoTag(final Boolean selectDSWithNoTag) { public DistributionSetFilterBuilder setSelectDSWithNoTag(final Boolean selectDSWithNoTag) {
this.selectDSWithNoTag = selectDSWithNoTag; this.selectDSWithNoTag = selectDSWithNoTag;
return this; return this;
@@ -83,8 +77,8 @@ public final class DistributionSetFilter {
return this; return this;
} }
public DistributionSetFilterBuilder setType(final DistributionSetType type) { public DistributionSetFilterBuilder setTypeId(final Long typeId) {
this.type = type; this.typeId = typeId;
return this; return this;
} }
@@ -93,9 +87,8 @@ public final class DistributionSetFilter {
private final Boolean isDeleted; private final Boolean isDeleted;
private final Boolean isComplete; private final Boolean isComplete;
private final Boolean isValid; private final Boolean isValid;
private final DistributionSetType type; private final Long typeId;
private final String searchText; private final String searchText;
private final String filterString;
private final Boolean selectDSWithNoTag; private final Boolean selectDSWithNoTag;
private final Collection<String> tagNames; private final Collection<String> tagNames;
private final String assignedTargetId; private final String assignedTargetId;
@@ -112,9 +105,8 @@ public final class DistributionSetFilter {
this.isDeleted = builder.isDeleted; this.isDeleted = builder.isDeleted;
this.isComplete = builder.isComplete; this.isComplete = builder.isComplete;
this.isValid = builder.isValid; this.isValid = builder.isValid;
this.type = builder.type; this.typeId = builder.typeId;
this.searchText = builder.searchText; this.searchText = builder.searchText;
this.filterString = builder.filterString;
this.selectDSWithNoTag = builder.selectDSWithNoTag; this.selectDSWithNoTag = builder.selectDSWithNoTag;
this.tagNames = builder.tagNames; this.tagNames = builder.tagNames;
this.assignedTargetId = builder.assignedTargetId; this.assignedTargetId = builder.assignedTargetId;
@@ -145,10 +137,6 @@ public final class DistributionSetFilter {
return searchText; return searchText;
} }
public String getFilterString() {
return filterString;
}
public Boolean getSelectDSWithNoTag() { public Boolean getSelectDSWithNoTag() {
return selectDSWithNoTag; return selectDSWithNoTag;
} }
@@ -157,8 +145,8 @@ public final class DistributionSetFilter {
return tagNames; return tagNames;
} }
public DistributionSetType getType() { public Long getTypeId() {
return type; return typeId;
} }
} }

View File

@@ -220,6 +220,13 @@ public class JpaArtifactManagement implements ArtifactManagement {
return localArtifactRepository.findBySoftwareModuleId(pageReq, swId); return localArtifactRepository.findBySoftwareModuleId(pageReq, swId);
} }
@Override
public long countBySoftwareModule(final long swId) {
throwExceptionIfSoftwareModuleDoesNotExist(swId);
return localArtifactRepository.countBySoftwareModuleId(swId);
}
private void throwExceptionIfSoftwareModuleDoesNotExist(final Long swId) { private void throwExceptionIfSoftwareModuleDoesNotExist(final Long swId) {
if (!softwareModuleRepository.existsById(swId)) { if (!softwareModuleRepository.existsById(swId)) {
throw new EntityNotFoundException(SoftwareModule.class, swId); throw new EntityNotFoundException(SoftwareModule.class, swId);

View File

@@ -12,6 +12,7 @@ import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationPrope
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
@@ -273,7 +274,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
if (target.getTargetType() != null) { 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<DistributionSetType> incompatibleDistSetTypes = distributionSetManagement.get(distSetIds).stream() final Set<DistributionSetType> incompatibleDistSetTypes = distributionSetManagement.get(distSetIds).stream()
.map(DistributionSet::getType).collect(Collectors.toSet()); .map(DistributionSet::getType).collect(Collectors.toSet());
incompatibleDistSetTypes.removeAll(target.getTargetType().getCompatibleDistributionSetTypes()); 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 * method assigns the {@link DistributionSet} to all {@link Target}s by
* IDs with a specific {@link ActionType} and {@code forcetime}. * their IDs with a specific {@link ActionType} and {@code forcetime}.
* *
* *
* In case the update was executed offline (i.e. not managed by hawkBit) the * 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 * A. it ignores targets completely that are in
* {@link TargetUpdateStatus#PENDING}.<br/> * {@link TargetUpdateStatus#PENDING}.<br/>
* B. it created completed actions.<br/> * B. it created completed actions.<br/>
* C. sets both installed and assigned DS on the target and switches the status * C. sets both installed and assigned DS on the target and switches the
* to {@link TargetUpdateStatus#IN_SYNC} <br/> * status to {@link TargetUpdateStatus#IN_SYNC} <br/>
* D. does not send a {@link TargetAssignDistributionSetEvent}.<br/> * D. does not send a {@link TargetAssignDistributionSetEvent}.<br/>
* *
* @param initiatedBy * @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 * split tIDs length into max entries in-statement because many database
* constraint of max entries in in-statements e.g. Oracle with maximum 1000 * have constraint of max entries in in-statements e.g. Oracle with maximum
* elements, so we need to split the entries here and execute multiple * 1000 elements, so we need to split the entries here and execute multiple
* statements * statements
*/ */
private static List<List<Long>> getTargetEntitiesAsChunks(final List<JpaTarget> targetEntities) { private static List<List<Long>> getTargetEntitiesAsChunks(final List<JpaTarget> targetEntities) {
@@ -579,10 +581,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return 0L; return 0L;
} }
final List<Action> targetAssignments = rolloutGroupActions.getContent().stream() final List<Action> targetAssignments = rolloutGroupActions.getContent().stream().map(JpaAction.class::cast)
.map(action -> (JpaAction) action).map(this::closeActionIfSetWasAlreadyAssigned) .map(this::closeActionIfSetWasAlreadyAssigned).filter(Objects::nonNull)
.filter(Objects::nonNull).map(this::startScheduledActionIfNoCancelationHasToBeHandledFirst) .map(this::startScheduledActionIfNoCancelationHasToBeHandledFirst).filter(Objects::nonNull)
.filter(Objects::nonNull).collect(Collectors.toList()); .collect(Collectors.toList());
if (!targetAssignments.isEmpty()) { if (!targetAssignments.isEmpty()) {
onlineDsAssignmentStrategy.sendDeploymentEvents(distributionSetId, targetAssignments); onlineDsAssignmentStrategy.sendDeploymentEvents(distributionSetId, targetAssignments);
@@ -696,20 +698,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
final Pageable pageable) { final Pageable pageable) {
throwExceptionIfTargetDoesNotExist(controllerId); throwExceptionIfTargetDoesNotExist(controllerId);
final Specification<JpaAction> byTargetSpec = createSpecificationFor(controllerId, rsqlParam); final List<Specification<JpaAction>> specList = Arrays.asList(
final Page<JpaAction> actions = actionRepository.findAll(byTargetSpec, pageable); RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database),
return convertAcPage(actions, pageable); byControllerIdSpec(controllerId));
return JpaManagementHelper.findAllWithCountBySpec(actionRepository, pageable, specList);
} }
private Specification<JpaAction> createSpecificationFor(final String controllerId, final String rsqlParam) { private Specification<JpaAction> byControllerIdSpec(final String controllerId) {
final Specification<JpaAction> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, return (root, query, cb) -> cb.equal(root.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId);
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<Action> convertAcPage(final Page<JpaAction> findAll, final Pageable pageable) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements());
} }
@Override @Override
@@ -744,7 +741,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
public long countActionsByTarget(final String rsqlParam, final String controllerId) { public long countActionsByTarget(final String rsqlParam, final String controllerId) {
throwExceptionIfTargetDoesNotExist(controllerId); throwExceptionIfTargetDoesNotExist(controllerId);
return actionRepository.count(createSpecificationFor(controllerId, rsqlParam)); final List<Specification<JpaAction>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database),
byControllerIdSpec(controllerId));
return JpaManagementHelper.countBySpec(actionRepository, specList);
} }
private void throwExceptionIfTargetDoesNotExist(final String controllerId) { private void throwExceptionIfTargetDoesNotExist(final String controllerId) {
@@ -776,24 +777,28 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
public Page<ActionStatus> findActionStatusByAction(final Pageable pageReq, final long actionId) { public Page<ActionStatus> findActionStatusByAction(final Pageable pageReq, final long actionId) {
verifyActionExists(actionId);
return actionStatusRepository.findByActionId(pageReq, actionId);
}
private void verifyActionExists(final long actionId) {
if (!actionRepository.existsById(actionId)) { if (!actionRepository.existsById(actionId)) {
throw new EntityNotFoundException(Action.class, 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 @Override
public Page<String> findMessagesByActionStatusId(final Pageable pageable, final long actionStatusId) { public Page<String> findMessagesByActionStatusId(final Pageable pageable, final long actionStatusId) {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Long> countMsgQuery = cb.createQuery(Long.class);
final Root<JpaActionStatus> countMsgQueryFrom = countMsgQuery.distinct(true).from(JpaActionStatus.class);
final ListJoin<JpaActionStatus, String> 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<String> msgQuery = cb.createQuery(String.class); final CriteriaQuery<String> msgQuery = cb.createQuery(String.class);
final Root<JpaActionStatus> as = msgQuery.from(JpaActionStatus.class); final Root<JpaActionStatus> as = msgQuery.from(JpaActionStatus.class);
final ListJoin<JpaActionStatus, String> join = as.joinList("messages", JoinType.LEFT); final ListJoin<JpaActionStatus, String> join = as.joinList("messages", JoinType.LEFT);
@@ -803,16 +808,25 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
final List<String> result = new ArrayList<>(entityManager.createQuery(selMsgQuery) final List<String> result = new ArrayList<>(entityManager.createQuery(selMsgQuery)
.setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList()); .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<Long> countMsgQuery = cb.createQuery(Long.class);
final Root<JpaActionStatus> countMsgQueryFrom = countMsgQuery.distinct(true).from(JpaActionStatus.class);
final ListJoin<JpaActionStatus, String> 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 @Override
public Page<ActionStatus> findActionStatusAll(final Pageable pageable) { public Page<ActionStatus> findActionStatusAll(final Pageable pageable) {
return convertAcSPage(actionStatusRepository.findAll(pageable), pageable); return JpaManagementHelper.findAllWithCountBySpec(actionStatusRepository, pageable, null);
}
private static Page<ActionStatus> convertAcSPage(final Page<JpaActionStatus> findAll, final Pageable pageable) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements());
} }
@Override @Override
@@ -844,7 +858,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
public Slice<Action> findActionsAll(final Pageable pageable) { public Slice<Action> findActionsAll(final Pageable pageable) {
return convertAcPage(actionRepository.findAll(pageable), pageable); return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, pageable, null);
} }
@Override @Override
@@ -866,10 +880,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return 0; return 0;
} }
/* /*
* We use a native query here because Spring JPA does not support to specify a * We use a native query here because Spring JPA does not support to
* LIMIT clause on a DELETE statement. However, for this specific use case * specify a LIMIT clause on a DELETE statement. However, for this
* (action cleanup), we must specify a row limit to reduce the overall load on * specific use case (action cleanup), we must specify a row limit to
* the database. * reduce the overall load on the database.
*/ */
final int statusCount = status.size(); final int statusCount = status.size();

View File

@@ -8,7 +8,6 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -17,12 +16,14 @@ import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.DistributionSetFields; import org.eclipse.hawkbit.repository.DistributionSetFields;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetMetadataFields; import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; 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.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetFilter; 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.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; 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.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Backoff;
@@ -148,7 +148,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Override @Override
public Optional<DistributionSet> getWithDetails(final long distid) { public Optional<DistributionSet> getWithDetails(final long distid) {
return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid)) return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid))
.map(d -> (DistributionSet) d); .map(DistributionSet.class::cast);
} }
@Override @Override
@@ -337,101 +337,59 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
} }
@Override @Override
public Page<DistributionSet> findByDistributionSetFilter(final Pageable pageable, public Slice<DistributionSet> findByDistributionSetFilter(final Pageable pageable,
final DistributionSetFilter distributionSetFilter) { final DistributionSetFilter distributionSetFilter) {
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications( final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
distributionSetFilter); distributionSetFilter);
return convertDsPage(findByCriteriaAPI(pageable, specList), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable, specList);
} }
private static Page<DistributionSet> convertDsPage(final Page<JpaDistributionSet> findAll, @Override
final Pageable pageable) { public long countByDistributionSetFilter(@NotNull final DistributionSetFilter distributionSetFilter) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<DistributionSet> convertDsPage(final Slice<JpaDistributionSet> 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<JpaDistributionSet> findDistributionSetsByFiltersAndInstalledOrAssignedTarget(
final DistributionSetFilter distributionSetFilter) {
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications( final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
distributionSetFilter); distributionSetFilter);
if (CollectionUtils.isEmpty(specList)) {
return Optional.empty(); return JpaManagementHelper.countBySpec(distributionSetRepository, specList);
}
return distributionSetRepository.findOne(SpecificationsBuilder.combineWithAnd(specList));
} }
@Override @Override
public Page<DistributionSet> findByCompleted(final Pageable pageReq, final Boolean complete) { public Slice<DistributionSet> findByCompleted(final Pageable pageReq, final Boolean complete) {
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageReq,
buildSpecsByComplete(complete));
}
List<Specification<JpaDistributionSet>> specList; private List<Specification<JpaDistributionSet>> buildSpecsByComplete(final Boolean complete) {
if (complete != null) { return complete != null
specList = Arrays.asList(DistributionSetSpecification.isDeleted(false), ? Arrays.asList(DistributionSetSpecification.isDeleted(false),
DistributionSetSpecification.isCompleted(complete)); DistributionSetSpecification.isCompleted(complete))
} else { : Collections.singletonList(DistributionSetSpecification.isDeleted(false));
specList = Collections.singletonList(DistributionSetSpecification.isDeleted(false));
}
return convertDsPage(findByCriteriaAPI(pageReq, specList), pageReq);
} }
@Override @Override
public Page<DistributionSet> findByFilterAndAssignedInstalledDsOrderedByLinkTarget(final Pageable pageable, public long countByCompleted(final Boolean complete) {
final DistributionSetFilterBuilder distributionSetFilterBuilder, final String assignedOrInstalled) { return JpaManagementHelper.countBySpec(distributionSetRepository, buildSpecsByComplete(complete));
}
final DistributionSetFilter filterWithInstalledTargets = distributionSetFilterBuilder @Override
.setInstalledTargetId(assignedOrInstalled).setAssignedTargetId(null).build(); public Slice<DistributionSet> findByDistributionSetFilterOrderByLinkedTarget(final Pageable pageable,
final Optional<JpaDistributionSet> installedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget( final DistributionSetFilter distributionSetFilter, final String assignedOrInstalled) {
filterWithInstalledTargets); final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
distributionSetFilter);
specList.add(DistributionSetSpecification.orderedByLinkedTarget(assignedOrInstalled));
final DistributionSetFilter filterWithAssignedTargets = distributionSetFilterBuilder.setInstalledTargetId(null) // remove default sort from pageable to not overwrite sorted spec
.setAssignedTargetId(assignedOrInstalled).build(); final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(),
final Optional<JpaDistributionSet> assignedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget( pageable.getPageSize(), Sort.unsorted());
filterWithAssignedTargets);
final DistributionSetFilter dsFilterWithNoTargetLinked = distributionSetFilterBuilder.setInstalledTargetId(null) return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, unsortedPage, specList);
.setAssignedTargetId(null).build();
// first fine the distribution sets filtered by the given filter
// parameters
final Page<DistributionSet> findDistributionSetsByFilters = findByDistributionSetFilter(pageable,
dsFilterWithNoTargetLinked);
final List<DistributionSet> 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());
} }
@Override @Override
public Optional<DistributionSet> getByNameAndVersion(final String distributionName, final String version) { public Optional<DistributionSet> getByNameAndVersion(final String distributionName, final String version) {
final Specification<JpaDistributionSet> spec = DistributionSetSpecification final Specification<JpaDistributionSet> spec = DistributionSetSpecification
.equalsNameAndVersionIgnoreCase(distributionName, version); .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()); assertMetaDataQuota(dsId, md.size());
final JpaDistributionSet set = touch(dsId); final JpaDistributionSet set = JpaManagementHelper.touch(entityManager, distributionSetRepository,
(JpaDistributionSet) getValid(dsId));
return Collections.unmodifiableList(md.stream() return Collections.unmodifiableList(md.stream()
.map(meta -> distributionSetMetadataRepository .map(meta -> distributionSetMetadataRepository
@@ -485,7 +444,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
toUpdate.setValue(md.getValue()); toUpdate.setValue(md.getValue());
// touch it to update the lock revision because we are modifying the // touch it to update the lock revision because we are modifying the
// DS indirectly // DS indirectly
touch(dsId); JpaManagementHelper.touch(entityManager, distributionSetRepository, (JpaDistributionSet) getValid(dsId));
return distributionSetMetadataRepository.save(toUpdate); return distributionSetMetadataRepository.save(toUpdate);
} }
@@ -498,72 +457,42 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
distributionSetId, key).orElseThrow( distributionSetId, key).orElseThrow(
() -> new EntityNotFoundException(DistributionSetMetadata.class, distributionSetId, key)); () -> new EntityNotFoundException(DistributionSetMetadata.class, distributionSetId, key));
touch(metadata.getDistributionSet()); JpaManagementHelper.touch(entityManager, distributionSetRepository,
(JpaDistributionSet) metadata.getDistributionSet());
distributionSetMetadataRepository.deleteById(metadata.getId()); 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 @Override
public Page<DistributionSetMetadata> findMetaDataByDistributionSetId(final Pageable pageable, public Page<DistributionSetMetadata> findMetaDataByDistributionSetId(final Pageable pageable,
final long distributionSetId) { final long distributionSetId) {
throwExceptionIfDistributionSetDoesNotExist(distributionSetId); throwExceptionIfDistributionSetDoesNotExist(distributionSetId);
return convertMdPage(distributionSetMetadataRepository return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable,
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal( Collections.singletonList(byDsIdSpec(distributionSetId)));
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), }
distributionSetId), pageable),
pageable); private Specification<JpaDistributionSetMetadata> 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 @Override
public Page<DistributionSetMetadata> findMetaDataByDistributionSetIdAndRsql(final Pageable pageable, public Page<DistributionSetMetadata> findMetaDataByDistributionSetIdAndRsql(final Pageable pageable,
final long distributionSetId, final String rsqlParam) { final long distributionSetId, final String rsqlParam) {
throwExceptionIfDistributionSetDoesNotExist(distributionSetId); throwExceptionIfDistributionSetDoesNotExist(distributionSetId);
final Specification<JpaDistributionSetMetadata> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, final List<Specification<JpaDistributionSetMetadata>> specList = Arrays
DistributionSetMetadataFields.class, virtualPropertyReplacer, database); .asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetMetadataFields.class,
virtualPropertyReplacer, database), byDsIdSpec(distributionSetId));
return convertMdPage( return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable, specList);
distributionSetMetadataRepository
.findAll((Specification<JpaDistributionSetMetadata>) (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<DistributionSetMetadata> convertMdPage(final Page<JpaDistributionSetMetadata> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
} }
@Override @Override
@@ -571,7 +500,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
throwExceptionIfDistributionSetDoesNotExist(setId); throwExceptionIfDistributionSetDoesNotExist(setId);
return distributionSetMetadataRepository.findById(new DsMetadataCompositeKey(setId, key)) return distributionSetMetadataRepository.findById(new DsMetadataCompositeKey(setId, key))
.map(dmd -> (DistributionSetMetadata) dmd); .map(DistributionSetMetadata.class::cast);
} }
@Override @Override
@@ -611,19 +540,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
specList.add(spec); specList.add(spec);
} }
if (distributionSetFilter.getType() != null) { if (distributionSetFilter.getTypeId() != null) {
spec = DistributionSetSpecification.byType(distributionSetFilter.getType()); spec = DistributionSetSpecification.byType(distributionSetFilter.getTypeId());
specList.add(spec); specList.add(spec);
} }
if (!StringUtils.isEmpty(distributionSetFilter.getSearchText())) { if (!StringUtils.isEmpty(distributionSetFilter.getSearchText())) {
spec = DistributionSetSpecification.likeNameOrDescriptionOrVersion(distributionSetFilter.getSearchText()); final String[] dsFilterNameAndVersionEntries = JpaManagementHelper
specList.add(spec); .getFilterNameAndVersionEntries(distributionSetFilter.getSearchText().trim());
}
if (!StringUtils.isEmpty(distributionSetFilter.getFilterString())) {
final String[] dsFilterNameAndVersionEntries = getDsFilterNameAndVersionEntries(
distributionSetFilter.getFilterString().trim());
spec = DistributionSetSpecification.likeNameAndVersion(dsFilterNameAndVersionEntries[0], spec = DistributionSetSpecification.likeNameAndVersion(dsFilterNameAndVersionEntries[0],
dsFilterNameAndVersionEntries[1]); dsFilterNameAndVersionEntries[1]);
specList.add(spec); specList.add(spec);
@@ -645,19 +569,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
return specList; 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) { private void assertDistributionSetIsNotAssignedToTargets(final Long distributionSet) {
if (actionRepository.countByDistributionSetId(distributionSet) > 0) { if (actionRepository.countByDistributionSetId(distributionSet) > 0) {
throw new EntityReadOnlyException(String.format( throw new EntityReadOnlyException(String.format(
@@ -672,26 +583,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
return isNoTagActive || isAtLeastOneTagActive; 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<JpaDistributionSet> findByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaDistributionSet>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return distributionSetRepository.findAll(pageable);
}
return distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable);
}
private void checkAndThrowIfDistributionSetMetadataAlreadyExists(final DsMetadataCompositeKey metadataId) { private void checkAndThrowIfDistributionSetMetadataAlreadyExists(final DsMetadataCompositeKey metadataId) {
if (distributionSetMetadataRepository.existsById(metadataId)) { if (distributionSetMetadataRepository.existsById(metadataId)) {
throw new EntityAlreadyExistsException( throw new EntityAlreadyExistsException(
@@ -769,7 +660,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
public Page<DistributionSet> findByTag(final Pageable pageable, final long tagId) { public Page<DistributionSet> findByTag(final Pageable pageable, final long tagId) {
throwEntityNotFoundExceptionIfDsTagDoesNotExist(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<DistributionSet> findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) { public Page<DistributionSet> findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) {
throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId); throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId);
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, final List<Specification<JpaDistributionSet>> specList = Arrays.asList(
DistributionSetFields.class, virtualPropertyReplacer, database); RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer,
database),
DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isDeleted(false));
return convertDsPage(findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.hasTag(tagId), return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, specList);
DistributionSetSpecification.isDeleted(false))), pageable);
} }
@Override @Override
public Slice<DistributionSet> findAll(final Pageable pageable) { public Slice<DistributionSet> findAll(final Pageable pageable) {
return convertDsPage( return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable,
distributionSetRepository.findAllWithoutCount(DistributionSetSpecification.isDeleted(false), pageable), Collections.singletonList(DistributionSetSpecification.isDeleted(false)));
pageable);
} }
@Override @Override
public Page<DistributionSet> findByRsql(final Pageable pageable, final String rsqlParam) { public Page<DistributionSet> findByRsql(final Pageable pageable, final String rsqlParam) {
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, final List<Specification<JpaDistributionSet>> specList = Arrays.asList(RSQLUtility
DistributionSetFields.class, virtualPropertyReplacer, database); .buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer, database),
DistributionSetSpecification.isDeleted(false));
return convertDsPage( return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, specList);
findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.isDeleted(false))),
pageable);
} }
@Override @Override

View File

@@ -31,7 +31,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
@@ -125,7 +124,7 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
@Override @Override
public Slice<DistributionSetTag> findAll(final Pageable pageable) { public Slice<DistributionSetTag> findAll(final Pageable pageable) {
return convertDsPage(distributionSetTagRepository.findAllWithoutCount(pageable), pageable); return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTagRepository, pageable, null);
} }
@Override @Override
@@ -133,7 +132,8 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
final Specification<JpaDistributionSetTag> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class, final Specification<JpaDistributionSetTag> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class,
virtualPropertyReplacer, database); virtualPropertyReplacer, database);
return convertDsPage(distributionSetTagRepository.findAll(spec, pageable), pageable); return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable,
Collections.singletonList(spec));
} }
@Override @Override
@@ -142,18 +142,8 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
throw new EntityNotFoundException(DistributionSet.class, setId); throw new EntityNotFoundException(DistributionSet.class, setId);
} }
return convertDsPage(distributionSetTagRepository.findAll(TagSpecification.ofDistributionSet(setId), pageable), return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable,
pageable); Collections.singletonList(TagSpecification.ofDistributionSet(setId)));
}
private static Page<DistributionSetTag> convertDsPage(final Page<JpaDistributionSetTag> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<DistributionSetTag> convertDsPage(final Slice<JpaDistributionSetTag> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
} }
@Override @Override
@@ -178,7 +168,7 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
@Override @Override
public Optional<DistributionSetTag> get(final long id) { public Optional<DistributionSetTag> get(final long id) {
return distributionSetTagRepository.findById(id).map(dst -> (DistributionSetTag) dst); return distributionSetTagRepository.findById(id).map(DistributionSetTag.class::cast);
} }
@Override @Override

View File

@@ -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.model.JpaTargetType;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTypeSpecification; 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.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable; import org.springframework.retry.annotation.Retryable;
@@ -227,17 +224,18 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana
@Override @Override
public Page<DistributionSetType> findByRsql(final Pageable pageable, final String rsqlParam) { public Page<DistributionSetType> findByRsql(final Pageable pageable, final String rsqlParam) {
return convertPage( return JpaManagementHelper
findByCriteriaAPI(pageable, .findAllWithCountBySpec(distributionSetTypeRepository, pageable,
Arrays.asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTypeFields.class, Arrays.asList(
virtualPropertyReplacer, database), DistributionSetTypeSpecification.isDeleted(false))), RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTypeFields.class,
pageable); virtualPropertyReplacer, database),
DistributionSetTypeSpecification.isDeleted(false)));
} }
@Override @Override
public Slice<DistributionSetType> findAll(final Pageable pageable) { public Slice<DistributionSetType> findAll(final Pageable pageable) {
return convertPage(distributionSetTypeRepository return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTypeRepository, pageable,
.findAllWithoutCount(DistributionSetTypeSpecification.isDeleted(false), pageable), pageable); Collections.singletonList(DistributionSetTypeSpecification.isDeleted(false)));
} }
@Override @Override
@@ -280,14 +278,13 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana
if (distributionSetRepository.countByTypeId(typeId) > 0) { if (distributionSetRepository.countByTypeId(typeId) > 0) {
toDelete.setDeleted(true); toDelete.setDeleted(true);
distributionSetTypeRepository.save(toDelete); distributionSetTypeRepository.save(toDelete);
} } else {
else {
distributionSetTypeRepository.deleteById(typeId); distributionSetTypeRepository.deleteById(typeId);
} }
} }
private void unassignDsTypeFromTargetTypes(long typeId) { private void unassignDsTypeFromTargetTypes(final long typeId) {
List<JpaTargetType> targetTypesByDsType = targetTypeRepository.findByDsType(typeId); final List<JpaTargetType> targetTypesByDsType = targetTypeRepository.findByDsType(typeId);
targetTypesByDsType.forEach(targetType -> { targetTypesByDsType.forEach(targetType -> {
targetType.removeDistributionSetType(typeId); targetType.removeDistributionSetType(typeId);
targetTypeRepository.save(targetType); targetTypeRepository.save(targetType);
@@ -318,26 +315,6 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana
} }
} }
private static Page<DistributionSetType> convertPage(final Page<JpaDistributionSetType> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<DistributionSetType> convertPage(final Slice<JpaDistributionSetType> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
}
private Page<JpaDistributionSetType> findByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaDistributionSetType>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return distributionSetTypeRepository.findAll(pageable);
}
return distributionSetTypeRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable);
}
@Override @Override
@Transactional @Transactional
@Retryable(include = { @Retryable(include = {

View File

@@ -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 <T, J extends T> Page<T> findAllWithCountBySpec(final JpaSpecificationExecutor<J> repository,
final Pageable pageable, final List<Specification<J>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return convertPage(repository.findAll(Specification.where(null), pageable), pageable);
}
return convertPage(repository.findAll(combineWithAnd(specList), pageable), pageable);
}
public static <T, J extends T> Page<T> convertPage(final Page<J> jpaAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(jpaAll.getContent()), pageable, jpaAll.getTotalElements());
}
private static <J> Specification<J> combineWithAnd(final List<Specification<J>> specList) {
return specList.size() == 1 ? specList.get(0) : SpecificationsBuilder.combineWithAnd(specList);
}
public static <T, J extends T> Slice<T> findAllWithoutCountBySpec(final NoCountSliceRepository<J> repository,
final Pageable pageable, final List<Specification<J>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return convertPage(repository.findAllWithoutCount(pageable), pageable);
}
return convertPage(repository.findAllWithoutCount(combineWithAnd(specList), pageable), pageable);
}
public static <T, J extends T> Slice<T> convertPage(final Slice<J> jpaAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(jpaAll.getContent()), pageable, 0);
}
public static <J> long countBySpec(final JpaSpecificationExecutor<J> repository,
final List<Specification<J>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return repository.count(Specification.where(null));
}
return repository.count(combineWithAnd(specList));
}
public static <J extends AbstractJpaBaseEntity> J touch(final EntityManager entityManager,
final CrudRepository<J, ?> 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 };
}
}

View File

@@ -55,7 +55,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort; 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 PageRequest pageRequest = PageRequest.of(0, Math.toIntExact(limit));
final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(), final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(),
RolloutGroupStatus.READY, group); RolloutGroupStatus.READY, group);
final Page<Target> targets = targetManagement.findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible( final Slice<Target> targets = targetManagement.findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(
pageRequest, readyGroups, targetFilter, rollout.getDistributionSet().getType()); pageRequest, readyGroups, targetFilter, rollout.getDistributionSet().getType());
createAssignmentOfTargetsToGroup(targets, group); createAssignmentOfTargetsToGroup(targets, group);
@@ -585,8 +584,8 @@ public class JpaRolloutExecutor implements RolloutExecutor {
} }
/** /**
* Schedules a group of the rollout. Scheduled Actions are created to achieve * Schedules a group of the rollout. Scheduled Actions are created to
* this. The creation of those Actions is allowed to fail. * achieve this. The creation of those Actions is allowed to fail.
*/ */
private boolean scheduleRolloutGroup(final JpaRollout rollout, final JpaRolloutGroup group) { private boolean scheduleRolloutGroup(final JpaRollout rollout, final JpaRolloutGroup group) {
final long targetsInGroup = rolloutTargetGroupRepository.countByRolloutGroup(group); final long targetsInGroup = rolloutTargetGroupRepository.countByRolloutGroup(group);
@@ -634,8 +633,8 @@ public class JpaRolloutExecutor implements RolloutExecutor {
final ActionType actionType = rollout.getActionType(); final ActionType actionType = rollout.getActionType();
final long forceTime = rollout.getForcedTime(); final long forceTime = rollout.getForcedTime();
final Page<Target> targets = targetManagement.findByInRolloutGroupWithoutAction(pageRequest, groupId); final Slice<Target> targets = targetManagement.findByInRolloutGroupWithoutAction(pageRequest, groupId);
if (targets.getTotalElements() > 0) { if (targets.getNumberOfElements() > 0) {
createScheduledAction(targets.getContent(), distributionSet, actionType, forceTime, rollout, group); createScheduledAction(targets.getContent(), distributionSet, actionType, forceTime, rollout, group);
} }
@@ -643,14 +642,14 @@ public class JpaRolloutExecutor implements RolloutExecutor {
}); });
} }
private void createAssignmentOfTargetsToGroup(final Page<Target> targets, final RolloutGroup group) { private void createAssignmentOfTargetsToGroup(final Slice<Target> targets, final RolloutGroup group) {
targets.forEach(target -> rolloutTargetGroupRepository.save(new RolloutTargetGroup(group, target))); targets.forEach(target -> rolloutTargetGroupRepository.save(new RolloutTargetGroup(group, target)));
} }
/** /**
* Creates an action entry into the action repository. In case of existing * Creates an action entry into the action repository. In case of existing
* scheduled actions the scheduled actions gets canceled. A scheduled action is * scheduled actions the scheduled actions gets canceled. A scheduled action
* created in-active. * is created in-active.
*/ */
private void createScheduledAction(final Collection<Target> targets, final DistributionSet distributionSet, private void createScheduledAction(final Collection<Target> targets, final DistributionSet distributionSet,
final ActionType actionType, final Long forcedTime, final Rollout rollout, final ActionType actionType, final Long forcedTime, final Rollout rollout,

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -104,15 +105,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
public Page<RolloutGroup> findByRollout(final Pageable pageable, final long rolloutId) { public Page<RolloutGroup> findByRollout(final Pageable pageable, final long rolloutId) {
throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId);
return convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, pageable), pageable); return JpaManagementHelper.convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, pageable), pageable);
}
private static Page<RolloutGroup> convertPage(final Page<JpaRolloutGroup> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Page<Target> convertTPage(final Page<JpaTarget> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
} }
@Override @Override
@@ -120,12 +113,12 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
final String rsqlParam) { final String rsqlParam) {
throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId);
final Specification<JpaRolloutGroup> specification = RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutGroupFields.class, final List<Specification<JpaRolloutGroup>> specList = Arrays.asList(
virtualPropertyReplacer, database); 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( return JpaManagementHelper.findAllWithCountBySpec(rolloutGroupRepository, pageable, specList);
criteriaBuilder.equal(root.get(JpaRolloutGroup_.rollout).get(JpaRollout_.id), rolloutId),
specification.toPredicate(root, query, criteriaBuilder)), pageable), pageable);
} }
private void throwEntityNotFoundExceptionIfRolloutDoesNotExist(final Long rolloutId) { private void throwEntityNotFoundExceptionIfRolloutDoesNotExist(final Long rolloutId) {
@@ -157,7 +150,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
rolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus); rolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus);
} }
return convertPage(rolloutGroups, pageable); return JpaManagementHelper.convertPage(rolloutGroups, pageable);
} }
@Override @Override
@@ -209,19 +202,18 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
@Override @Override
public Page<Target> findTargetsOfRolloutGroupByRsql(final Pageable pageable, final long rolloutGroupId, public Page<Target> findTargetsOfRolloutGroupByRsql(final Pageable pageable, final long rolloutGroupId,
final String rsqlParam) { final String rsqlParam) {
throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId);
final Specification<JpaTarget> rsqlSpecification = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, final List<Specification<JpaTarget>> specList = Arrays.asList(
virtualPropertyReplacer, database); RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database),
(root, query, cb) -> {
final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = root
.join(JpaTarget_.rolloutTargetGroup);
return cb.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id),
rolloutGroupId);
});
return convertTPage(targetRepository.findAll((root, query, criteriaBuilder) -> { return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList);
final ListJoin<JpaTarget, RolloutTargetGroup> 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);
} }
@Override @Override
@@ -233,11 +225,11 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
// in case of status ready the action has not been created yet and // in case of status ready the action has not been created yet and
// the relation information between target and rollout-group is // the relation information between target and rollout-group is
// stored in the #TargetRolloutGroup. // stored in the #TargetRolloutGroup.
return JpaTargetManagement.convertPage( return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page,
targetRepository.findAll(TargetSpecifications.isInRolloutGroup(rolloutGroupId), page), page); Collections.singletonList(TargetSpecifications.isInRolloutGroup(rolloutGroupId)));
} }
return JpaTargetManagement.convertPage( return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page,
targetRepository.findAll(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId), page), page); Collections.singletonList(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId)));
} }
private static boolean isRolloutStatusReady(final RolloutGroup rolloutGroup) { private static boolean isRolloutStatusReady(final RolloutGroup rolloutGroup) {

View File

@@ -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
* <code>true</code> if deleted rollouts should be included in
* the search. Otherwise <code>false</code>
* @return criteria specification with a query for name or description of a
* rollout
*/
static Specification<JpaRollout> 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<Rollout> convertPage(final Page<JpaRollout> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
static Slice<Rollout> convertPage(final Slice<JpaRollout> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
}
}

View File

@@ -12,6 +12,7 @@ import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.a
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; 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.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; 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.configuration.Constants;
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification; 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.DeploymentHelper;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper; import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
@@ -160,8 +161,8 @@ public class JpaRolloutManagement implements RolloutManagement {
@Override @Override
public Page<Rollout> findAll(final Pageable pageable, final boolean deleted) { public Page<Rollout> findAll(final Pageable pageable, final boolean deleted) {
final Specification<JpaRollout> spec = RolloutSpecification.isDeletedWithDistributionSet(deleted); return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable,
return JpaRolloutHelper.convertPage(rolloutRepository.findAll(spec, pageable), pageable); Collections.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted)));
} }
@Override @Override
@@ -171,24 +172,12 @@ public class JpaRolloutManagement implements RolloutManagement {
RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database)); RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database));
specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted)); specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted));
return JpaRolloutHelper.convertPage(findByCriteriaAPI(pageable, specList), pageable); return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable, specList);
}
/**
* Executes findAll with the given {@link Rollout} {@link Specification}s.
*/
private Page<JpaRollout> findByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaRollout>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return rolloutRepository.findAll(pageable);
}
return rolloutRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable);
} }
@Override @Override
public Optional<Rollout> get(final long rolloutId) { public Optional<Rollout> get(final long rolloutId) {
return rolloutRepository.findById(rolloutId).map(r -> (Rollout) r); return rolloutRepository.findById(rolloutId).map(Rollout.class::cast);
} }
@Override @Override
@@ -264,8 +253,7 @@ public class JpaRolloutManagement implements RolloutManagement {
// prepare the groups // prepare the groups
final List<RolloutGroup> groups = groupList.stream() final List<RolloutGroup> groups = groupList.stream()
.map(group -> JpaRolloutHelper.prepareRolloutGroupWithDefaultConditions(group, conditions)) .map(group -> prepareRolloutGroupWithDefaultConditions(group, conditions)).collect(Collectors.toList());
.collect(Collectors.toList());
groups.forEach(RolloutHelper::verifyRolloutGroupHasConditions); groups.forEach(RolloutHelper::verifyRolloutGroupHasConditions);
RolloutHelper.verifyRemainingTargets(calculateRemainingTargets(groups, savedRollout.getTargetFilterQuery(), RolloutHelper.verifyRemainingTargets(calculateRemainingTargets(groups, savedRollout.getTargetFilterQuery(),
@@ -307,6 +295,48 @@ public class JpaRolloutManagement implements RolloutManagement {
return rolloutRepository.save(savedRollout); 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) { private void publishRolloutGroupCreatedEventAfterCommit(final RolloutGroup group, final Rollout rollout) {
afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher().publishEvent( afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher().publishEvent(
new RolloutGroupCreatedEvent(group, rollout.getId(), eventPublisherHolder.getApplicationId()))); new RolloutGroupCreatedEvent(group, rollout.getId(), eventPublisherHolder.getApplicationId())));
@@ -456,7 +486,7 @@ public class JpaRolloutManagement implements RolloutManagement {
@Override @Override
public long countByFilters(final String searchText) { public long countByFilters(final String searchText) {
return rolloutRepository.count(JpaRolloutHelper.likeNameOrDescription(searchText, false)); return rolloutRepository.count(RolloutSpecification.likeName(searchText, false));
} }
@Override @Override
@@ -467,10 +497,10 @@ public class JpaRolloutManagement implements RolloutManagement {
@Override @Override
public Slice<Rollout> findByFiltersWithDetailedStatus(final Pageable pageable, final String searchText, public Slice<Rollout> findByFiltersWithDetailedStatus(final Pageable pageable, final String searchText,
final boolean deleted) { final boolean deleted) {
final Slice<JpaRollout> findAll = findByCriteriaAPI(pageable, final Slice<Rollout> findAll = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable,
Arrays.asList(JpaRolloutHelper.likeNameOrDescription(searchText, deleted))); Collections.singletonList(RolloutSpecification.likeName(searchText, deleted)));
setRolloutStatusDetails(findAll); setRolloutStatusDetails(findAll);
return JpaRolloutHelper.convertPage(findAll, pageable); return findAll;
} }
@Override @Override
@@ -521,12 +551,11 @@ public class JpaRolloutManagement implements RolloutManagement {
} }
@Override @Override
public Page<Rollout> findAllWithDetailedStatus(final Pageable pageable, final boolean deleted) { public Slice<Rollout> findAllWithDetailedStatus(final Pageable pageable, final boolean deleted) {
final Page<JpaRollout> rollouts; final Slice<Rollout> rollouts = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable,
final Specification<JpaRollout> spec = RolloutSpecification.isDeletedWithDistributionSet(deleted); Collections.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted)));
rollouts = rolloutRepository.findAll(spec, pageable);
setRolloutStatusDetails(rollouts); setRolloutStatusDetails(rollouts);
return JpaRolloutHelper.convertPage(rollouts, pageable); return rollouts;
} }
@Override @Override
@@ -579,7 +608,7 @@ public class JpaRolloutManagement implements RolloutManagement {
return fromCache; return fromCache;
} }
private void setRolloutStatusDetails(final Slice<JpaRollout> rollouts) { private void setRolloutStatusDetails(final Slice<Rollout> rollouts) {
final List<Long> rolloutIds = rollouts.getContent().stream().map(Rollout::getId).collect(Collectors.toList()); final List<Long> rolloutIds = rollouts.getContent().stream().map(Rollout::getId).collect(Collectors.toList());
final Map<Long, List<TotalTargetCountActionStatus>> allStatesForRollout = getStatusCountItemForRollout( final Map<Long, List<TotalTargetCountActionStatus>> allStatesForRollout = getStatusCountItemForRollout(
rolloutIds); rolloutIds);
@@ -588,7 +617,7 @@ public class JpaRolloutManagement implements RolloutManagement {
rollouts.forEach(rollout -> { rollouts.forEach(rollout -> {
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus( final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(
allStatesForRollout.get(rollout.getId()), rollout.getTotalTargets(), rollout.getActionType()); allStatesForRollout.get(rollout.getId()), rollout.getTotalTargets(), rollout.getActionType());
rollout.setTotalTargetCountStatus(totalTargetCountStatus); ((JpaRollout) rollout).setTotalTargetCountStatus(totalTargetCountStatus);
}); });
} }
} }

View File

@@ -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.model.SwMetadataCompositeKey;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification; 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.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; 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.dao.ConcurrencyFailureException;
import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.AuditorAware;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
@@ -183,7 +181,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
specList.add(SoftwareModuleSpecification.equalType(typeId)); specList.add(SoftwareModuleSpecification.equalType(typeId));
specList.add(SoftwareModuleSpecification.isDeletedFalse()); specList.add(SoftwareModuleSpecification.isDeletedFalse());
return convertSmPage(findByCriteriaAPI(pageable, specList), pageable); return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList);
} }
private void throwExceptionIfSoftwareModuleTypeDoesNotExist(final Long typeId) { private void throwExceptionIfSoftwareModuleTypeDoesNotExist(final Long typeId) {
@@ -192,23 +190,9 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
} }
} }
private static Slice<SoftwareModule> convertSmPage(final Slice<JpaSoftwareModule> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
}
private static Page<SoftwareModule> convertSmPage(final Page<JpaSoftwareModule> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Page<SoftwareModuleMetadata> convertSmMdPage(final Page<JpaSoftwareModuleMetadata> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
@Override @Override
public Optional<SoftwareModule> get(final long id) { public Optional<SoftwareModule> get(final long id) {
return softwareModuleRepository.findById(id).map(sm -> (SoftwareModule) sm); return softwareModuleRepository.findById(id).map(SoftwareModule.class::cast);
} }
@Override @Override
@@ -224,15 +208,6 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
return distributionSetRepository.countByModulesId(moduleId) <= 0; return distributionSetRepository.countByModulesId(moduleId) <= 0;
} }
private Slice<JpaSoftwareModule> findByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaSoftwareModule>> specList) {
return softwareModuleRepository.findAllWithoutCount(SpecificationsBuilder.combineWithAnd(specList), pageable);
}
private Long countSwModuleByCriteriaAPI(final List<Specification<JpaSoftwareModule>> specList) {
return softwareModuleRepository.count(SpecificationsBuilder.combineWithAnd(specList));
}
private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) { private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) {
for (final Artifact localArtifact : swModule.getArtifacts()) { for (final Artifact localArtifact : swModule.getArtifacts()) {
artifactManagement.clearArtifactBinary(localArtifact.getSha1Hash(), swModule.getId()); artifactManagement.clearArtifactBinary(localArtifact.getSha1Hash(), swModule.getId());
@@ -276,29 +251,18 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Override @Override
public Slice<SoftwareModule> findAll(final Pageable pageable) { public Slice<SoftwareModule> findAll(final Pageable pageable) {
final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>(2); final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>(2);
specList.add(SoftwareModuleSpecification.isDeletedFalse());
specList.add(SoftwareModuleSpecification.fetchType());
Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse(); return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList);
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);
} }
@Override @Override
public long count() { public long count() {
final Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse(); final Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
return countSwModuleByCriteriaAPI(Arrays.asList(spec)); return JpaManagementHelper.countBySpec(softwareModuleRepository, Collections.singletonList(spec));
} }
@Override @Override
@@ -306,7 +270,8 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
final Specification<JpaSoftwareModule> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, final Specification<JpaSoftwareModule> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
SoftwareModuleFields.class, virtualPropertyReplacer, database); SoftwareModuleFields.class, virtualPropertyReplacer, database);
return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable); return JpaManagementHelper.findAllWithCountBySpec(softwareModuleRepository, pageable,
Collections.singletonList(spec));
} }
@Override @Override
@@ -318,34 +283,28 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Override @Override
public Slice<SoftwareModule> findByTextAndType(final Pageable pageable, final String searchText, public Slice<SoftwareModule> findByTextAndType(final Pageable pageable, final String searchText,
final Long typeId) { final Long typeId) {
final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>(4); final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>(4);
specList.add(SoftwareModuleSpecification.isDeletedFalse());
Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec);
if (!StringUtils.isEmpty(searchText)) { if (!StringUtils.isEmpty(searchText)) {
spec = SoftwareModuleSpecification.likeNameOrVersion(searchText); specList.add(buildSmSearchQuerySpec(searchText));
specList.add(spec);
} }
if (null != typeId) { if (null != typeId) {
throwExceptionIfSoftwareModuleTypeDoesNotExist(typeId); throwExceptionIfSoftwareModuleTypeDoesNotExist(typeId);
specList.add(SoftwareModuleSpecification.equalType(typeId));
spec = SoftwareModuleSpecification.equalType(typeId);
specList.add(spec);
} }
spec = (root, query, cb) -> { specList.add(SoftwareModuleSpecification.fetchType());
if (!query.getResultType().isAssignableFrom(Long.class)) {
root.fetch(JpaSoftwareModule_.type);
}
return cb.conjunction();
};
specList.add(spec); return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList);
}
return convertSmPage(findByCriteriaAPI(pageable, specList), pageable); private Specification<JpaSoftwareModule> buildSmSearchQuerySpec(final String searchText) {
final String[] smFilterNameAndVersionEntries = JpaManagementHelper
.getFilterNameAndVersionEntries(searchText.trim());
return SoftwareModuleSpecification.likeNameAndVersion(smFilterNameAndVersionEntries[0],
smFilterNameAndVersionEntries[1]);
} }
@Override @Override
@@ -392,8 +351,9 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
private List<Specification<JpaSoftwareModule>> buildSpecificationList(final String searchText, final Long typeId) { private List<Specification<JpaSoftwareModule>> buildSpecificationList(final String searchText, final Long typeId) {
final List<Specification<JpaSoftwareModule>> specList = Lists.newArrayListWithExpectedSize(3); final List<Specification<JpaSoftwareModule>> specList = Lists.newArrayListWithExpectedSize(3);
if (!StringUtils.isEmpty(searchText)) { if (!StringUtils.isEmpty(searchText)) {
specList.add(SoftwareModuleSpecification.likeNameOrVersion(searchText)); specList.add(buildSmSearchQuerySpec(searchText));
} }
if (typeId != null) { if (typeId != null) {
throwExceptionIfSoftwareModuleTypeDoesNotExist(typeId); throwExceptionIfSoftwareModuleTypeDoesNotExist(typeId);
@@ -413,15 +373,13 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Override @Override
public long countByTextAndType(final String searchText, final Long typeId) { public long countByTextAndType(final String searchText, final Long typeId) {
final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>(3); final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>(3);
Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse(); Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec); specList.add(spec);
if (!StringUtils.isEmpty(searchText)) { if (!StringUtils.isEmpty(searchText)) {
spec = SoftwareModuleSpecification.likeNameOrVersion(searchText); specList.add(buildSmSearchQuerySpec(searchText));
specList.add(spec);
} }
if (null != typeId) { if (null != typeId) {
@@ -431,7 +389,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
specList.add(spec); specList.add(spec);
} }
return countSwModuleByCriteriaAPI(specList); return JpaManagementHelper.countBySpec(softwareModuleRepository, specList);
} }
@Override @Override
@@ -506,7 +464,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
private static Stream<JpaSoftwareModuleMetadataCreate> createJpaMetadataCreateStream( private static Stream<JpaSoftwareModuleMetadataCreate> createJpaMetadataCreateStream(
final Collection<SoftwareModuleMetadataCreate> create) { final Collection<SoftwareModuleMetadataCreate> create) {
return create.stream().map(c -> (JpaSoftwareModuleMetadataCreate) c); return create.stream().map(JpaSoftwareModuleMetadataCreate.class::cast);
} }
private SoftwareModuleMetadata saveMetadata(final JpaSoftwareModuleMetadataCreate create) { private SoftwareModuleMetadata saveMetadata(final JpaSoftwareModuleMetadataCreate create) {
@@ -522,7 +480,8 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
} }
private void assertSoftwareModuleExists(final Long moduleId) { 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.getValue().ifPresent(metadata::setValue);
update.isTargetVisible().ifPresent(metadata::setTargetVisible); update.isTargetVisible().ifPresent(metadata::setTargetVisible);
touch(metadata.getSoftwareModule()); JpaManagementHelper.touch(entityManager, softwareModuleRepository,
(JpaSoftwareModule) metadata.getSoftwareModule());
return softwareModuleMetadataRepository.save(metadata); 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 @Override
@Transactional @Transactional
@Retryable(include = { @Retryable(include = {
@@ -595,7 +527,8 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId(moduleId, final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId(moduleId,
key).orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, moduleId, key)); key).orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, moduleId, key));
touch(metadata.getSoftwareModule()); JpaManagementHelper.touch(entityManager, softwareModuleRepository,
(JpaSoftwareModule) metadata.getSoftwareModule());
softwareModuleMetadataRepository.deleteById(metadata.getId()); softwareModuleMetadataRepository.deleteById(metadata.getId());
} }
@@ -608,35 +541,32 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Override @Override
public Page<SoftwareModuleMetadata> findMetaDataByRsql(final Pageable pageable, final long softwareModuleId, public Page<SoftwareModuleMetadata> findMetaDataByRsql(final Pageable pageable, final long softwareModuleId,
final String rsqlParam) { final String rsqlParam) {
throwExceptionIfSoftwareModuleDoesNotExist(softwareModuleId); throwExceptionIfSoftwareModuleDoesNotExist(softwareModuleId);
final Specification<JpaSoftwareModuleMetadata> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, final List<Specification<JpaSoftwareModuleMetadata>> specList = Arrays
SoftwareModuleMetadataFields.class, virtualPropertyReplacer, database); .asList(RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleMetadataFields.class,
return convertSmMdPage( virtualPropertyReplacer, database), bySmIdSpec(softwareModuleId));
softwareModuleMetadataRepository return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, pageable, specList);
.findAll(
(root, query, cb) -> cb.and(
cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule)
.get(JpaSoftwareModule_.id), softwareModuleId),
spec.toPredicate(root, query, cb)),
pageable),
pageable);
} }
private static Page<SoftwareModuleMetadata> convertMdPage(final Page<JpaSoftwareModuleMetadata> findAll, private static Specification<JpaSoftwareModuleMetadata> bySmIdSpec(final long smId) {
final Pageable pageable) { return (root, query, cb) -> cb
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); .equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), smId);
} }
@Override @Override
public Page<SoftwareModuleMetadata> findMetaDataBySoftwareModuleId(final Pageable pageable, final long swId) { public Page<SoftwareModuleMetadata> findMetaDataBySoftwareModuleId(final Pageable pageable, final long swId) {
throwExceptionIfSoftwareModuleDoesNotExist(swId); throwExceptionIfSoftwareModuleDoesNotExist(swId);
return convertMdPage(softwareModuleMetadataRepository.findAll( return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, pageable,
(Specification<JpaSoftwareModuleMetadata>) (root, query, cb) -> cb Collections.singletonList(bySmIdSpec(swId)));
.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), swId), }
pageable), pageable);
@Override
public long countMetaDataBySoftwareModuleId(final long moduleId) {
throwExceptionIfSoftwareModuleDoesNotExist(moduleId);
return softwareModuleMetadataRepository.countBySoftwareModuleId(moduleId);
} }
@Override @Override
@@ -644,7 +574,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
throwExceptionIfSoftwareModuleDoesNotExist(moduleId); throwExceptionIfSoftwareModuleDoesNotExist(moduleId);
return softwareModuleMetadataRepository.findById(new SwMetadataCompositeKey(moduleId, key)) return softwareModuleMetadataRepository.findById(new SwMetadataCompositeKey(moduleId, key))
.map(smmd -> (SoftwareModuleMetadata) smmd); .map(SoftwareModuleMetadata.class::cast);
} }
private static void throwMetadataKeyAlreadyExists(final String metadataKey) { private static void throwMetadataKeyAlreadyExists(final String metadataKey) {
@@ -669,7 +599,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
final long moduleId) { final long moduleId) {
throwExceptionIfSoftwareModuleDoesNotExist(moduleId); throwExceptionIfSoftwareModuleDoesNotExist(moduleId);
return convertMdPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible( return JpaManagementHelper.convertPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible(
PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT), moduleId, true), pageable); PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT), moduleId, true), pageable);
} }

View File

@@ -29,10 +29,8 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable; import org.springframework.retry.annotation.Retryable;
@@ -60,8 +58,7 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage
public JpaSoftwareModuleTypeManagement(final DistributionSetTypeRepository distributionSetTypeRepository, public JpaSoftwareModuleTypeManagement(final DistributionSetTypeRepository distributionSetTypeRepository,
final SoftwareModuleTypeRepository softwareModuleTypeRepository, final SoftwareModuleTypeRepository softwareModuleTypeRepository,
final VirtualPropertyReplacer virtualPropertyReplacer, final VirtualPropertyReplacer virtualPropertyReplacer,
final SoftwareModuleRepository softwareModuleRepository, final SoftwareModuleRepository softwareModuleRepository, final Database database) {
final Database database) {
this.distributionSetTypeRepository = distributionSetTypeRepository; this.distributionSetTypeRepository = distributionSetTypeRepository;
this.softwareModuleTypeRepository = softwareModuleTypeRepository; this.softwareModuleTypeRepository = softwareModuleTypeRepository;
this.virtualPropertyReplacer = virtualPropertyReplacer; this.virtualPropertyReplacer = virtualPropertyReplacer;
@@ -87,18 +84,16 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage
@Override @Override
public Page<SoftwareModuleType> findByRsql(final Pageable pageable, final String rsqlParam) { public Page<SoftwareModuleType> findByRsql(final Pageable pageable, final String rsqlParam) {
return JpaManagementHelper.findAllWithCountBySpec(softwareModuleTypeRepository, pageable,
final Specification<JpaSoftwareModuleType> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleTypeFields.class, Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleTypeFields.class,
virtualPropertyReplacer, database); virtualPropertyReplacer, database)));
return convertPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable);
} }
@Override @Override
public Slice<SoftwareModuleType> findAll(final Pageable pageable) { public Slice<SoftwareModuleType> findAll(final Pageable pageable) {
return convertPage(softwareModuleTypeRepository.findAllWithoutCount( return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleTypeRepository, pageable,
(targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaSoftwareModuleType_.deleted), false), Collections.singletonList(
pageable), pageable); (smTypeRoot, query, cb) -> cb.equal(smTypeRoot.get(JpaSoftwareModuleType_.deleted), false)));
} }
@Override @Override
@@ -151,16 +146,6 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage
return creates.stream().map(this::create).collect(Collectors.toList()); return creates.stream().map(this::create).collect(Collectors.toList());
} }
private static Page<SoftwareModuleType> convertPage(final Page<JpaSoftwareModuleType> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<SoftwareModuleType> convertPage(final Slice<JpaSoftwareModuleType> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
}
@Override @Override
@Transactional @Transactional
@Retryable(include = { @Retryable(include = {

View File

@@ -8,11 +8,12 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.TargetFields; 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.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; 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.specifications.TargetFilterQuerySpecification;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper; import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
@@ -47,14 +47,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable; import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -137,8 +136,8 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
} }
@Override @Override
public Page<TargetFilterQuery> findAll(final Pageable pageable) { public Slice<TargetFilterQuery> findAll(final Pageable pageable) {
return convertPage(targetFilterQueryRepository.findAll(pageable), pageable); return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, null);
} }
@Override @Override
@@ -151,70 +150,73 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
return targetFilterQueryRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId); return targetFilterQueryRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId);
} }
private static Page<TargetFilterQuery> convertPage(final Page<JpaTargetFilterQuery> findAll, @Override
final Pageable pageable) { public Slice<TargetFilterQuery> findByName(final Pageable pageable, final String name) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); if (StringUtils.isEmpty(name)) {
return findAll(pageable);
}
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable,
Collections.singletonList(TargetFilterQuerySpecification.likeName(name)));
} }
@Override @Override
public Page<TargetFilterQuery> findByName(final Pageable pageable, final String name) { public long countByName(final String name) {
List<Specification<JpaTargetFilterQuery>> specList = Collections.emptyList(); if (StringUtils.isEmpty(name)) {
if (!StringUtils.isEmpty(name)) { return count();
specList = Collections.singletonList(TargetFilterQuerySpecification.likeName(name));
} }
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
return JpaManagementHelper.countBySpec(targetFilterQueryRepository,
Collections.singletonList(TargetFilterQuerySpecification.likeName(name)));
} }
@Override @Override
public Page<TargetFilterQuery> findByRsql(final Pageable pageable, final String rsqlFilter) { public Page<TargetFilterQuery> findByRsql(final Pageable pageable, final String rsqlFilter) {
List<Specification<JpaTargetFilterQuery>> specList = Collections.emptyList(); final List<Specification<JpaTargetFilterQuery>> specList = !StringUtils.isEmpty(rsqlFilter)
if (!StringUtils.isEmpty(rsqlFilter)) { ? Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlFilter,
specList = Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer, database))
TargetFilterQueryFields.class, virtualPropertyReplacer, database)); : Collections.emptyList();
}
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable); return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, pageable, specList);
} }
@Override @Override
public Page<TargetFilterQuery> findByQuery(final Pageable pageable, final String query) { public Slice<TargetFilterQuery> findByQuery(final Pageable pageable, final String query) {
List<Specification<JpaTargetFilterQuery>> specList = Collections.emptyList(); final List<Specification<JpaTargetFilterQuery>> specList = !StringUtils.isEmpty(query)
if (!StringUtils.isEmpty(query)) { ? Collections.singletonList(TargetFilterQuerySpecification.equalsQuery(query))
specList = Collections.singletonList(TargetFilterQuerySpecification.equalsQuery(query)); : Collections.emptyList();
}
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable); return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, specList);
}
@Override
public Slice<TargetFilterQuery> 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 @Override
public Page<TargetFilterQuery> findByAutoAssignDSAndRsql(final Pageable pageable, final long setId, public Page<TargetFilterQuery> findByAutoAssignDSAndRsql(final Pageable pageable, final long setId,
final String rsqlFilter) { final String rsqlFilter) {
final List<Specification<JpaTargetFilterQuery>> specList = Lists.newArrayListWithExpectedSize(2);
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId); final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
final List<Specification<JpaTargetFilterQuery>> specList = Lists.newArrayListWithExpectedSize(2);
specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet)); specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet));
if (!StringUtils.isEmpty(rsqlFilter)) { if (!StringUtils.isEmpty(rsqlFilter)) {
specList.add(RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class, specList.add(RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class,
virtualPropertyReplacer, database)); virtualPropertyReplacer, database));
} }
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, pageable, specList);
} }
@Override @Override
public Page<TargetFilterQuery> findWithAutoAssignDS(final Pageable pageable) { public Slice<TargetFilterQuery> findWithAutoAssignDS(final Pageable pageable) {
final List<Specification<JpaTargetFilterQuery>> specList = Collections return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable,
.singletonList(TargetFilterQuerySpecification.withAutoAssignDS()); Collections.singletonList(TargetFilterQuerySpecification.withAutoAssignDS()));
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
}
private Page<JpaTargetFilterQuery> findTargetFilterQueryByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaTargetFilterQuery>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return targetFilterQueryRepository.findAll(pageable);
}
final Specification<JpaTargetFilterQuery> specs = SpecificationsBuilder.combineWithAnd(specList);
return targetFilterQueryRepository.findAll(specs, pageable);
} }
@Override @Override

View File

@@ -8,9 +8,6 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; 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.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -21,11 +18,14 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.MapJoin; import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import javax.validation.constraints.NotEmpty;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; 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.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.model.TargetMetadataCompositeKey; import org.eclipse.hawkbit.repository.jpa.model.TargetMetadataCompositeKey;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; 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.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort; 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.Backoff;
import org.springframework.retry.annotation.Retryable; import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import com.google.common.collect.Lists;
/** /**
* JPA implementation of {@link TargetManagement}. * JPA implementation of {@link TargetManagement}.
* *
@@ -185,7 +184,7 @@ public class JpaTargetManagement implements TargetManagement {
assertMetaDataQuota(target.getId(), md.size()); assertMetaDataQuota(target.getId(), md.size());
final JpaTarget updatedTarget = touch(target); final JpaTarget updatedTarget = JpaManagementHelper.touch(entityManager, targetRepository, target);
final List<TargetMetadata> createdMetadata = Collections.unmodifiableList(md.stream() final List<TargetMetadata> createdMetadata = Collections.unmodifiableList(md.stream()
.map(meta -> targetMetadataRepository .map(meta -> targetMetadataRepository
@@ -212,21 +211,6 @@ public class JpaTargetManagement implements TargetManagement {
TargetMetadata.class, Target.class, targetMetadataRepository::countByTargetId); 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 @Override
@Transactional @Transactional
@Retryable(include = { @Retryable(include = {
@@ -240,7 +224,8 @@ public class JpaTargetManagement implements TargetManagement {
updatedMetadata.setValue(md.getValue()); updatedMetadata.setValue(md.getValue());
// touch it to update the lock revision because we are modifying the // touch it to update the lock revision because we are modifying the
// target indirectly // target indirectly
final JpaTarget target = touch(controllerId); final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository,
getByControllerIdAndThrowIfNotFound(controllerId));
final JpaTargetMetadata matadata = targetMetadataRepository.save(updatedMetadata); final JpaTargetMetadata matadata = targetMetadataRepository.save(updatedMetadata);
// target update event is set to ignore "lastModifiedAt" field so it is // target update event is set to ignore "lastModifiedAt" field so it is
// not send automatically within the touch() method // not send automatically within the touch() method
@@ -257,7 +242,8 @@ public class JpaTargetManagement implements TargetManagement {
final JpaTargetMetadata metadata = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, key) final JpaTargetMetadata metadata = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, key)
.orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, 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()); targetMetadataRepository.deleteById(metadata.getId());
// target update event is set to ignore "lastModifiedAt" field so it is // target update event is set to ignore "lastModifiedAt" field so it is
// not send automatically within the touch() method // not send automatically within the touch() method
@@ -269,32 +255,32 @@ public class JpaTargetManagement implements TargetManagement {
public Page<TargetMetadata> findMetaDataByControllerId(final Pageable pageable, final String controllerId) { public Page<TargetMetadata> findMetaDataByControllerId(final Pageable pageable, final String controllerId) {
final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId();
return convertMdPage( return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable,
targetMetadataRepository Collections.singletonList(metadataByTargetIdSpec(targetId)));
.findAll(
(Specification<JpaTargetMetadata>) (root, query, cb) -> cb
.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId),
pageable),
pageable);
} }
private static Page<TargetMetadata> convertMdPage(final Page<JpaTargetMetadata> findAll, final Pageable pageable) { private Specification<JpaTargetMetadata> metadataByTargetIdSpec(final Long targetId) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); 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 @Override
public Page<TargetMetadata> findMetaDataByControllerIdAndRsql(final Pageable pageable, final String controllerId, public Page<TargetMetadata> findMetaDataByControllerIdAndRsql(final Pageable pageable, final String controllerId,
final String rsqlParam) { final String rsqlParam) {
final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId();
final Specification<JpaTargetMetadata> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, final List<Specification<JpaTargetMetadata>> specList = Arrays.asList(RSQLUtility
TargetMetadataFields.class, virtualPropertyReplacer, database); .buildRsqlSpecification(rsqlParam, TargetMetadataFields.class, virtualPropertyReplacer, database),
metadataByTargetIdSpec(targetId));
return convertMdPage(targetMetadataRepository.findAll((Specification<JpaTargetMetadata>) (root, query, cb) -> cb return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable, specList);
.and(cb.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId),
spec.toPredicate(root, query, cb)),
pageable), pageable);
} }
@Override @Override
@@ -306,7 +292,7 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public Slice<Target> findAll(final Pageable pageable) { public Slice<Target> findAll(final Pageable pageable) {
return convertPage(targetRepository.findAllWithoutCount(pageable), pageable); return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, null);
} }
@Override @Override
@@ -314,18 +300,16 @@ public class JpaTargetManagement implements TargetManagement {
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId) final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId)
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
return findTargetsBySpec(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), TargetFields.class, return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable,
virtualPropertyReplacer, database), pageable); Collections.singletonList(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(),
TargetFields.class, virtualPropertyReplacer, database)));
} }
@Override @Override
public Page<Target> findByRsql(final Pageable pageable, final String targetFilterQuery) { public Slice<Target> findByRsql(final Pageable pageable, final String targetFilterQuery) {
return findTargetsBySpec(RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable,
virtualPropertyReplacer, database), pageable); Collections.singletonList(RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
} virtualPropertyReplacer, database)));
private Page<Target> findTargetsBySpec(final Specification<JpaTarget> spec, final Pageable pageable) {
return convertPage(targetRepository.findAll(spec, pageable), pageable);
} }
@Override @Override
@@ -385,8 +369,8 @@ public class JpaTargetManagement implements TargetManagement {
public Page<Target> findByAssignedDistributionSet(final Pageable pageReq, final long distributionSetID) { public Page<Target> findByAssignedDistributionSet(final Pageable pageReq, final long distributionSetID) {
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID); final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID);
return convertPage(targetRepository return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq,
.findAll(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()), pageReq), pageReq); Collections.singletonList(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())));
} }
@Override @Override
@@ -394,31 +378,19 @@ public class JpaTargetManagement implements TargetManagement {
final String rsqlParam) { final String rsqlParam) {
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID); final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID);
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, final List<Specification<JpaTarget>> specList = Arrays.asList(
virtualPropertyReplacer, database); RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database),
TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()));
return convertPage( return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, specList);
targetRepository
.findAll((Specification<JpaTarget>) (root, query,
cb) -> cb.and(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())
.toPredicate(root, query, cb), spec.toPredicate(root, query, cb)),
pageReq),
pageReq);
}
public static Page<Target> convertPage(final Page<JpaTarget> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<Target> convertPage(final Slice<JpaTarget> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
} }
@Override @Override
public Page<Target> findByInstalledDistributionSet(final Pageable pageReq, final long distributionSetID) { public Page<Target> findByInstalledDistributionSet(final Pageable pageReq, final long distributionSetID) {
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(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 @Override
@@ -426,34 +398,29 @@ public class JpaTargetManagement implements TargetManagement {
final String rsqlParam) { final String rsqlParam) {
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, final List<Specification<JpaTarget>> specList = Arrays.asList(
virtualPropertyReplacer, database); RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database),
TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()));
return convertPage( return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList);
targetRepository
.findAll((Specification<JpaTarget>) (root, query,
cb) -> cb.and(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())
.toPredicate(root, query, cb), spec.toPredicate(root, query, cb)),
pageable),
pageable);
} }
@Override @Override
public Page<Target> findByUpdateStatus(final Pageable pageable, final TargetUpdateStatus status) { public Page<Target> findByUpdateStatus(final Pageable pageable, final TargetUpdateStatus status) {
return convertPage(targetRepository.findAll(TargetSpecifications.hasTargetUpdateStatus(status), pageable), return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable,
pageable); Collections.singletonList(TargetSpecifications.hasTargetUpdateStatus(status)));
} }
@Override @Override
public Slice<Target> findByFilters(final Pageable pageable, final FilterParams filterParams) { public Slice<Target> findByFilters(final Pageable pageable, final FilterParams filterParams) {
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams); final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
return findByCriteriaAPI(pageable, specList); return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, specList);
} }
@Override @Override
public long countByFilters(Collection<TargetUpdateStatus> status, Boolean overdueState, String searchText, public long countByFilters(final Collection<TargetUpdateStatus> status, final Boolean overdueState,
Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, final String searchText, final Long installedOrAssignedDistributionSetId,
String... tagNames) { final Boolean selectTargetWithNoTag, final String... tagNames) {
return countByFilters(new FilterParams(status, overdueState, searchText, installedOrAssignedDistributionSetId, return countByFilters(new FilterParams(status, overdueState, searchText, installedOrAssignedDistributionSetId,
selectTargetWithNoTag, tagNames)); selectTargetWithNoTag, tagNames));
} }
@@ -461,7 +428,7 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public long countByFilters(final FilterParams filterParams) { public long countByFilters(final FilterParams filterParams) {
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams); final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
return countByCriteriaAPI(specList); return JpaManagementHelper.countBySpec(targetRepository, specList);
} }
private List<Specification<JpaTarget>> buildSpecificationList(final FilterParams filterParams) { private List<Specification<JpaTarget>> buildSpecificationList(final FilterParams filterParams) {
@@ -479,8 +446,7 @@ public class JpaTargetManagement implements TargetManagement {
specList.add(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId())); specList.add(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId()));
} }
if (!StringUtils.isEmpty(filterParams.getFilterBySearchText())) { if (!StringUtils.isEmpty(filterParams.getFilterBySearchText())) {
specList.add(TargetSpecifications specList.add(TargetSpecifications.likeControllerIdOrName(filterParams.getFilterBySearchText()));
.likeIdOrNameOrDescriptionOrAttributeValue(filterParams.getFilterBySearchText()));
} }
if (hasTagsFilterActive(filterParams)) { if (hasTagsFilterActive(filterParams)) {
specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(), specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(),
@@ -512,23 +478,6 @@ public class JpaTargetManagement implements TargetManagement {
return Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTargetType()); return Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTargetType());
} }
private Slice<Target> findByCriteriaAPI(final Pageable pageable, final List<Specification<JpaTarget>> 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<Specification<JpaTarget>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return targetRepository.count();
}
return targetRepository.count(SpecificationsBuilder.combineWithAnd(specList));
}
@Override @Override
@Transactional @Transactional
@Retryable(include = { @Retryable(include = {
@@ -585,8 +534,8 @@ public class JpaTargetManagement implements TargetManagement {
targetsWithoutSameType.forEach(target -> target.setTargetType(type)); targetsWithoutSameType.forEach(target -> target.setTargetType(type));
final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(), final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(),
Collections Collections.unmodifiableList(
.unmodifiableList(targetsWithoutSameType.stream().map(targetRepository::save).collect(Collectors.toList())), targetsWithoutSameType.stream().map(targetRepository::save).collect(Collectors.toList())),
Collections.emptyList(), type); Collections.emptyList(), type);
// no reason to persist the 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); .unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList())), null);
} }
private List<JpaTarget> findTargetsByInSpecification(Collection<String> controllerIds, private List<JpaTarget> findTargetsByInSpecification(final Collection<String> controllerIds,
Specification<JpaTarget> specification) { final Specification<JpaTarget> specification) {
return Lists.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream() return Lists.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream()
.map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification))) .map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification)))
.flatMap(List::stream).collect(Collectors.toList()); .flatMap(List::stream).collect(Collectors.toList());
@@ -690,30 +639,14 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public Slice<Target> findByFilterOrderByLinkedDistributionSet(final Pageable pageable, public Slice<Target> findByFilterOrderByLinkedDistributionSet(final Pageable pageable,
final long orderByDistributionId, final FilterParams filterParams) { final long orderByDistributionId, final FilterParams filterParams) {
Specification<JpaTarget> orderedFilterSpec = combineFiltersAndDsOrder(orderByDistributionId, filterParams);
// remove default sort from pageable to not overwrite sorted spec // remove default sort from pageable to not overwrite sorted spec
final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(), final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(),
pageable.getPageSize(), Sort.unsorted()); pageable.getPageSize(), Sort.unsorted());
return convertPage(targetRepository.findAllWithoutCount(orderedFilterSpec, unsortedPage), unsortedPage);
}
/** final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
* Applies orderedByLinkedDistributionSet spec for order and adds additional specList.add(TargetSpecifications.orderedByLinkedDistributionSet(orderByDistributionId));
* specs based on filters
* return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, unsortedPage, specList);
* @param orderByDistributionId
* distribution set used for order
* @param filterParams
* filters to generate additional specs for
* @return specification combining order and filter specs
*/
private Specification<JpaTarget> combineFiltersAndDsOrder(final long orderByDistributionId,
final FilterParams filterParams) {
Specification<JpaTarget> orderedFilterSpec = orderedByLinkedDistributionSet(orderByDistributionId);
for (Specification<JpaTarget> spec : buildSpecificationList(filterParams)) {
orderedFilterSpec = orderedFilterSpec.and(spec);
}
return orderedFilterSpec;
} }
@Override @Override
@@ -739,55 +672,52 @@ public class JpaTargetManagement implements TargetManagement {
} }
@Override @Override
public Page<Target> findByTargetFilterQueryAndNonDSAndCompatible(final Pageable pageRequest, public Slice<Target> findByTargetFilterQueryAndNonDSAndCompatible(final Pageable pageRequest,
final long distributionSetId, final String targetFilterQuery) { final long distributionSetId, final String targetFilterQuery) {
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId); final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
final Long distSetTypeId = jpaDistributionSet.getType().getId(); final Long distSetTypeId = jpaDistributionSet.getType().getId();
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, final List<Specification<JpaTarget>> specList = Arrays.asList(
virtualPropertyReplacer, database); RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
final Specification<JpaTarget> dsNotInActions = TargetSpecifications database),
.hasNotDistributionSetInActions(distributionSetId); TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
final Specification<JpaTarget> isCompatibleWithDsType = TargetSpecifications TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId));
.isCompatibleWithDistributionSetType(distSetTypeId);
return findTargetsBySpec(spec.and(dsNotInActions).and(isCompatibleWithDsType), pageRequest); return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest, specList);
} }
@Override @Override
public Page<Target> findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(final Pageable pageRequest, public Slice<Target> findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(final Pageable pageRequest,
final Collection<Long> groups, final String targetFilterQuery, final DistributionSetType dsType) { final Collection<Long> groups, final String targetFilterQuery, final DistributionSetType dsType) {
final List<Specification<JpaTarget>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
database),
TargetSpecifications.isNotInRolloutGroups(groups),
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()));
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest, specList);
virtualPropertyReplacer, database);
final Specification<JpaTarget> notInRolloutGroups = TargetSpecifications.isNotInRolloutGroups(groups);
final Specification<JpaTarget> isCompatibleWithDsType = TargetSpecifications
.isCompatibleWithDistributionSetType(dsType.getId());
return findTargetsBySpec((spec.and(notInRolloutGroups).and(isCompatibleWithDsType)), pageRequest);
} }
@Override @Override
public Page<Target> findByInRolloutGroupWithoutAction(final Pageable pageRequest, final long group) { public Slice<Target> findByInRolloutGroupWithoutAction(final Pageable pageRequest, final long group) {
if (!rolloutGroupRepository.existsById(group)) { if (!rolloutGroupRepository.existsById(group)) {
throw new EntityNotFoundException(RolloutGroup.class, group); throw new EntityNotFoundException(RolloutGroup.class, group);
} }
return findTargetsBySpec( return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest,
(root, cq, cb) -> TargetSpecifications.hasNoActionInRolloutGroup(group).toPredicate(root, cq, cb), Collections.singletonList(TargetSpecifications.hasNoActionInRolloutGroup(group)));
pageRequest);
} }
@Override @Override
public long countByRsqlAndNotInRolloutGroupsAndCompatible(final Collection<Long> groups, public long countByRsqlAndNotInRolloutGroupsAndCompatible(final Collection<Long> groups,
final String targetFilterQuery, final DistributionSetType dsType) { final String targetFilterQuery, final DistributionSetType dsType) {
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, final List<Specification<JpaTarget>> specList = Arrays.asList(
virtualPropertyReplacer, database); RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
final List<Specification<JpaTarget>> specList = Arrays.asList(spec, database),
TargetSpecifications.isNotInRolloutGroups(groups), TargetSpecifications.isNotInRolloutGroups(groups),
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId())); TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()));
return countByCriteriaAPI(specList); return JpaManagementHelper.countBySpec(targetRepository, specList);
} }
@Override @Override
@@ -795,13 +725,13 @@ public class JpaTargetManagement implements TargetManagement {
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId); final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
final Long distSetTypeId = jpaDistributionSet.getType().getId(); final Long distSetTypeId = jpaDistributionSet.getType().getId();
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, final List<Specification<JpaTarget>> specList = Arrays.asList(
virtualPropertyReplacer, database); RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
final List<Specification<JpaTarget>> specList = Arrays.asList(spec, database),
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId), TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId)); TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId));
return countByCriteriaAPI(specList); return JpaManagementHelper.countBySpec(targetRepository, specList);
} }
@Override @Override
@@ -825,7 +755,8 @@ public class JpaTargetManagement implements TargetManagement {
public Page<Target> findByTag(final Pageable pageable, final long tagId) { public Page<Target> findByTag(final Pageable pageable, final long tagId) {
throwEntityNotFoundExceptionIfTagDoesNotExist(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) { private void throwEntityNotFoundExceptionIfTagDoesNotExist(final Long tagId) {
@@ -836,15 +767,13 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public Page<Target> findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) { public Page<Target> findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) {
throwEntityNotFoundExceptionIfTagDoesNotExist(tagId); throwEntityNotFoundExceptionIfTagDoesNotExist(tagId);
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, final List<Specification<JpaTarget>> specList = Arrays.asList(
virtualPropertyReplacer, database); RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database),
TargetSpecifications.hasTag(tagId));
return convertPage(targetRepository.findAll((Specification<JpaTarget>) (root, query, cb) -> cb.and( return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList);
TargetSpecifications.hasTag(tagId).toPredicate(root, query, cb), spec.toPredicate(root, query, cb)),
pageable), pageable);
} }
@Override @Override
@@ -852,23 +781,22 @@ public class JpaTargetManagement implements TargetManagement {
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId) final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId)
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
final Specification<JpaTarget> specs = RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), return countByRsql(targetFilterQuery.getQuery());
TargetFields.class, virtualPropertyReplacer, database);
return targetRepository.count(specs);
} }
@Override @Override
public long countByRsql(final String targetFilterQuery) { public long countByRsql(final String targetFilterQuery) {
final Specification<JpaTarget> specs = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, return JpaManagementHelper.countBySpec(targetRepository, Collections.singletonList(RSQLUtility
virtualPropertyReplacer, database); .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database)));
return targetRepository.count(specs);
} }
@Override @Override
public long countByRsqlAndCompatible(final String targetFilterQuery, final Long dsTypeId) { public long countByRsqlAndCompatible(final String targetFilterQuery, final Long dsTypeId) {
final Specification<JpaTarget> rsqlSpec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, final List<Specification<JpaTarget>> specList = Arrays.asList(RSQLUtility
TargetFields.class, virtualPropertyReplacer, database); .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
return targetRepository.count(rsqlSpec.and(TargetSpecifications.isCompatibleWithDistributionSetType(dsTypeId))); TargetSpecifications.isCompatibleWithDistributionSetType(dsTypeId));
return JpaManagementHelper.countBySpec(targetRepository, specList);
} }
@Override @Override
@@ -925,8 +853,8 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public Page<Target> findByControllerAttributesRequested(final Pageable pageReq) { public Page<Target> findByControllerAttributesRequested(final Pageable pageReq) {
return convertPage(targetRepository.findAll(TargetSpecifications.hasRequestControllerAttributesTrue(), pageReq), return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq,
pageReq); Collections.singletonList(TargetSpecifications.hasRequestControllerAttributesTrue()));
} }
} }

View File

@@ -31,9 +31,7 @@ import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable; import org.springframework.retry.annotation.Retryable;
@@ -106,14 +104,8 @@ public class JpaTargetTagManagement implements TargetTagManagement {
@Override @Override
public Page<TargetTag> findByRsql(final Pageable pageable, final String rsqlParam) { public Page<TargetTag> findByRsql(final Pageable pageable, final String rsqlParam) {
return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, Collections.singletonList(
final Specification<JpaTargetTag> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class, virtualPropertyReplacer, RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class, virtualPropertyReplacer, database)));
database);
return convertTPage(targetTagRepository.findAll(spec, pageable), pageable);
}
private static Page<TargetTag> convertTPage(final Page<JpaTargetTag> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
} }
@Override @Override
@@ -140,7 +132,7 @@ public class JpaTargetTagManagement implements TargetTagManagement {
@Override @Override
public Optional<TargetTag> get(final long id) { public Optional<TargetTag> get(final long id) {
return targetTagRepository.findById(id).map(tt -> (TargetTag) tt); return targetTagRepository.findById(id).map(TargetTag.class::cast);
} }
@Override @Override
@@ -150,7 +142,7 @@ public class JpaTargetTagManagement implements TargetTagManagement {
@Override @Override
public Page<TargetTag> findAll(final Pageable pageable) { public Page<TargetTag> findAll(final Pageable pageable) {
return convertTPage(targetTagRepository.findAll(pageable), pageable); return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, null);
} }
@Override @Override
@@ -159,6 +151,7 @@ public class JpaTargetTagManagement implements TargetTagManagement {
throw new EntityNotFoundException(Target.class, controllerId); 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)));
} }
} }

View File

@@ -8,6 +8,12 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; 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.QuotaManagement;
import org.eclipse.hawkbit.repository.TargetTypeFields; import org.eclipse.hawkbit.repository.TargetTypeFields;
import org.eclipse.hawkbit.repository.TargetTypeManagement; 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.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; 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.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable; import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; 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}. * JPA implementation of {@link TargetTypeManagement}.
* *
@@ -95,6 +94,11 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
return targetTypeRepository.count(); return targetTypeRepository.count();
} }
@Override
public long countByName(final String name) {
return targetTypeRepository.countByName(name);
}
@Override @Override
@Transactional @Transactional
@Retryable(include = { @Retryable(include = {
@@ -127,21 +131,21 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
} }
@Override @Override
public Page<TargetType> findAll(final Pageable pageable) { public Slice<TargetType> findAll(final Pageable pageable) {
return convertPage(targetTypeRepository.findAll(pageable), pageable); return JpaManagementHelper.findAllWithoutCountBySpec(targetTypeRepository, pageable, null);
} }
@Override @Override
public Page<TargetType> findByRsql(final Pageable pageable, final String rsqlParam) { public Page<TargetType> findByRsql(final Pageable pageable, final String rsqlParam) {
final Specification<JpaTargetType> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetTypeFields.class, return JpaManagementHelper.findAllWithCountBySpec(targetTypeRepository, pageable,
virtualPropertyReplacer, database); Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlParam, TargetTypeFields.class,
virtualPropertyReplacer, database)));
return convertPage(targetTypeRepository.findAll(spec, pageable), pageable);
} }
@Override @Override
public Page<TargetType> findByName(Pageable pageable, String name) { public Slice<TargetType> findByName(final Pageable pageable, final String name) {
return convertPage(targetTypeRepository.findAll(TargetTypeSpecification.likeName(name), pageable), pageable); return JpaManagementHelper.findAllWithoutCountBySpec(targetTypeRepository, pageable,
Collections.singletonList(TargetTypeSpecification.likeName(name)));
} }
@Override @Override
@@ -258,9 +262,4 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxDistributionSetTypesPerTargetType(), QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxDistributionSetTypesPerTargetType(),
DistributionSetType.class, TargetType.class, targetTypeRepository::countDsSetTypesById); DistributionSetType.class, TargetType.class, targetTypeRepository::countDsSetTypesById);
} }
private static Page<TargetType> convertPage(final Page<JpaTargetType> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
} }

View File

@@ -8,6 +8,12 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; 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.model.JpaTargetType;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetTypeSpecification; import org.eclipse.hawkbit.repository.jpa.specifications.TargetTypeSpecification;
import org.eclipse.hawkbit.repository.model.TargetType; 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.lang.NonNull;
import org.springframework.transaction.annotation.Transactional; 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}. * {@link PagingAndSortingRepository} for {@link JpaTargetType}.
* *
@@ -42,23 +42,24 @@ public interface TargetTypeRepository
* *
* Calls version based on spec to allow injecting further specs * 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} * @return {@link Optional} of {@link TargetType}
*/ */
@Override @Override
@NonNull @NonNull
default Optional<JpaTargetType> findById(@NonNull Long id) { default Optional<JpaTargetType> findById(@NonNull final Long id) {
return this.findOne(Specification.where(TargetTypeSpecification.hasId(id))); return this.findOne(Specification.where(TargetTypeSpecification.hasId(id)));
} }
/** /**
* @param ids * @param ids
* List of ID * List of ID
* @return Target type list * @return Target type list
*/ */
@Override @Override
@NonNull @NonNull
default List<JpaTargetType> findAllById(Iterable<Long> ids) { default List<JpaTargetType> findAllById(final Iterable<Long> ids) {
final List<Long> collectedIds = StreamSupport.stream(ids.spliterator(), true).collect(Collectors.toList()); final List<Long> collectedIds = StreamSupport.stream(ids.spliterator(), true).collect(Collectors.toList());
return this.findAll(Specification.where(TargetTypeSpecification.hasIdIn(collectedIds))); 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 * 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 * @return {@link List} of {@link TargetType}s
*/ */
@Override @Override
@NonNull @NonNull
default Iterable<JpaTargetType> findAll(@NonNull Sort sort) { default Iterable<JpaTargetType> findAll(@NonNull final Sort sort) {
return this.findAll(Specification.where(null), 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 * 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 * @return {@link List} of {@link TargetType}s
*/ */
@Override @Override
@NonNull @NonNull
default Page<JpaTargetType> findAll(@NonNull Pageable pageable) { default Page<JpaTargetType> findAll(@NonNull final Pageable pageable) {
return this.findAll(Specification.where(null), 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 * 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 * @return true if TargetType with id exists
*/ */
@Override @Override
default boolean existsById(@NonNull Long id) { default boolean existsById(@NonNull final Long id) {
return this.exists(TargetTypeSpecification.hasId(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 * @return true if target with id exists
*/ */
default boolean exists(@NonNull Specification<JpaTargetType> spec) { default boolean exists(@NonNull final Specification<JpaTargetType> spec) {
return this.count(spec) > 0; return this.count(spec) > 0;
} }
@@ -152,7 +159,7 @@ public interface TargetTypeRepository
/** /**
* @param tenant * @param tenant
* Tenant * Tenant
*/ */
@Modifying @Modifying
@Transactional @Transactional
@@ -169,7 +176,7 @@ public interface TargetTypeRepository
* @return all {@link TargetType}s in the repository with given * @return all {@link TargetType}s in the repository with given
* {@link TargetType#getName()} * {@link TargetType#getName()}
*/ */
default List<JpaTargetType> findByDsType(@Param("id") Long dsTypeId) { default List<JpaTargetType> findByDsType(@Param("id") final Long dsTypeId) {
return this.findAll(Specification.where(TargetTypeSpecification.hasDsSetType(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 * @return all {@link TargetType}s in the repository with given
* {@link TargetType#getName()} * {@link TargetType#getName()}
*/ */
default Optional<JpaTargetType> findByName(String name){ default Optional<JpaTargetType> findByName(final String name) {
return this.findOne(Specification.where(TargetTypeSpecification.hasName(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));
}
} }

View File

@@ -23,9 +23,9 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@@ -38,8 +38,8 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAutoAssignExecutor.class); private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAutoAssignExecutor.class);
/** /**
* The message which is added to the action status when a distribution set is * The message which is added to the action status when a distribution set
* assigned to an target. First %s is the name of the target filter. * 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"; private static final String ACTION_MESSAGE = "Auto assignment by target filter: %s";
@@ -94,7 +94,7 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor {
} }
protected void forEachFilterWithAutoAssignDS(final Consumer<TargetFilterQuery> consumer) { protected void forEachFilterWithAutoAssignDS(final Consumer<TargetFilterQuery> consumer) {
Page<TargetFilterQuery> filterQueries; Slice<TargetFilterQuery> filterQueries;
Pageable query = PageRequest.of(0, PAGE_SIZE); Pageable query = PageRequest.of(0, PAGE_SIZE);
do { do {
@@ -117,8 +117,8 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor {
} }
/** /**
* Runs target assignments within a dedicated transaction for a given list of * Runs target assignments within a dedicated transaction for a given list
* controllerIDs * of controllerIDs
* *
* @param targetFilterQuery * @param targetFilterQuery
* the target filter query * 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 * Creates a list of {@link DeploymentRequest} for given list of
* and {@link TargetFilterQuery} * controllerIds and {@link TargetFilterQuery}
* *
* @param controllerIds * @param controllerIds
* list of controllerIds * list of controllerIds

View File

@@ -13,6 +13,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.JoinType; import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.ListJoin; import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.Path; 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.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
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.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
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.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@@ -52,7 +52,7 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<JpaDistributionSet> isDeleted(final Boolean isDeleted) { public static Specification<JpaDistributionSet> isDeleted(final Boolean isDeleted) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.deleted), isDeleted); return (dsRoot, query, cb) -> cb.equal(dsRoot.<Boolean> get(JpaDistributionSet_.deleted), isDeleted);
} }
@@ -66,7 +66,7 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<JpaDistributionSet> isCompleted(final Boolean isCompleted) { public static Specification<JpaDistributionSet> isCompleted(final Boolean isCompleted) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.complete), isCompleted); return (dsRoot, query, cb) -> cb.equal(dsRoot.<Boolean> get(JpaDistributionSet_.complete), isCompleted);
} }
@@ -80,7 +80,7 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<JpaDistributionSet> isValid(final Boolean isValid) { public static Specification<JpaDistributionSet> isValid(final Boolean isValid) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.valid), isValid); return (dsRoot, query, cb) -> cb.equal(dsRoot.<Boolean> get(JpaDistributionSet_.valid), isValid);
} }
@@ -93,10 +93,10 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<JpaDistributionSet> byId(final Long distid) { public static Specification<JpaDistributionSet> byId(final Long distid) {
return (targetRoot, query, cb) -> { return (dsRoot, query, cb) -> {
final Predicate predicate = cb.equal(targetRoot.<Long> get(JpaDistributionSet_.id), distid); final Predicate predicate = cb.equal(dsRoot.<Long> get(JpaDistributionSet_.id), distid);
targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT); dsRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT); dsRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
query.distinct(true); query.distinct(true);
return predicate; return predicate;
@@ -112,31 +112,16 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<JpaDistributionSet> byIds(final Collection<Long> distids) { public static Specification<JpaDistributionSet> byIds(final Collection<Long> distids) {
return (targetRoot, query, cb) -> { return (dsRoot, query, cb) -> {
final Predicate predicate = targetRoot.<Long> get(JpaDistributionSet_.id).in(distids); final Predicate predicate = dsRoot.<Long> get(JpaDistributionSet_.id).in(distids);
targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT); dsRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
targetRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT); dsRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT);
targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT); dsRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
query.distinct(true); query.distinct(true);
return predicate; 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<JpaDistributionSet> likeNameOrDescriptionOrVersion(final String subString) {
return (targetRoot, query, cb) -> cb.or(
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.name)), subString.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.version)), subString.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.description)), subString.toLowerCase()));
}
/** /**
* {@link Specification} for retrieving {@link DistributionSet}s by "like * {@link Specification} for retrieving {@link DistributionSet}s by "like
* name and like version". * name and like version".
@@ -148,9 +133,9 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<JpaDistributionSet> likeNameAndVersion(final String name, final String version) { public static Specification<JpaDistributionSet> likeNameAndVersion(final String name, final String version) {
return (targetRoot, query, cb) -> cb.and( return (dsRoot, query, cb) -> cb.and(
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.name)), name.toLowerCase()), cb.like(cb.lower(dsRoot.<String> get(JpaDistributionSet_.name)), name.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.version)), version.toLowerCase())); cb.like(cb.lower(dsRoot.<String> get(JpaDistributionSet_.version)), version.toLowerCase()));
} }
/** /**
@@ -165,16 +150,16 @@ public final class DistributionSetSpecification {
*/ */
public static Specification<JpaDistributionSet> hasTags(final Collection<String> tagNames, public static Specification<JpaDistributionSet> hasTags(final Collection<String> tagNames,
final Boolean selectDSWithNoTag) { final Boolean selectDSWithNoTag) {
return (targetRoot, query, cb) -> { return (dsRoot, query, cb) -> {
final Predicate predicate = getHasTagsPredicate(targetRoot, cb, selectDSWithNoTag, tagNames); final Predicate predicate = getHasTagsPredicate(dsRoot, cb, selectDSWithNoTag, tagNames);
query.distinct(true); query.distinct(true);
return predicate; return predicate;
}; };
} }
private static Predicate getHasTagsPredicate(final Root<JpaDistributionSet> targetRoot, final CriteriaBuilder cb, private static Predicate getHasTagsPredicate(final Root<JpaDistributionSet> dsRoot, final CriteriaBuilder cb,
final Boolean selectDSWithNoTag, final Collection<String> tagNames) { final Boolean selectDSWithNoTag, final Collection<String> tagNames) {
final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = targetRoot.join(JpaDistributionSet_.tags, final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = dsRoot.join(JpaDistributionSet_.tags,
JoinType.LEFT); JoinType.LEFT);
final Path<String> exp = tags.get(JpaDistributionSetTag_.name); final Path<String> exp = tags.get(JpaDistributionSetTag_.name);
@@ -210,9 +195,9 @@ public final class DistributionSetSpecification {
*/ */
public static Specification<JpaDistributionSet> equalsNameAndVersionIgnoreCase(final String name, public static Specification<JpaDistributionSet> equalsNameAndVersionIgnoreCase(final String name,
final String version) { final String version) {
return (targetRoot, query, cb) -> cb.and( return (dsRoot, query, cb) -> cb.and(
cb.equal(cb.lower(targetRoot.<String> get(JpaDistributionSet_.name)), name.toLowerCase()), cb.equal(cb.lower(dsRoot.<String> get(JpaDistributionSet_.name)), name.toLowerCase()),
cb.equal(cb.lower(targetRoot.<String> get(JpaDistributionSet_.version)), version.toLowerCase())); cb.equal(cb.lower(dsRoot.<String> get(JpaDistributionSet_.version)), version.toLowerCase()));
} }
@@ -220,13 +205,13 @@ public final class DistributionSetSpecification {
* {@link Specification} for retrieving {@link DistributionSet} with given * {@link Specification} for retrieving {@link DistributionSet} with given
* {@link DistributionSet#getType()}. * {@link DistributionSet#getType()}.
* *
* @param type * @param typeId
* to search * id of distribution set type to search
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<JpaDistributionSet> byType(final DistributionSetType type) { public static Specification<JpaDistributionSet> byType(final Long typeId) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<JpaDistributionSetType> get(JpaDistributionSet_.type), return (dsRoot, query, cb) -> cb.equal(dsRoot.get(JpaDistributionSet_.type).get(JpaDistributionSetType_.id),
type); typeId);
} }
@@ -269,11 +254,38 @@ public final class DistributionSetSpecification {
*/ */
public static Specification<JpaDistributionSet> hasTag(final Long tagId) { public static Specification<JpaDistributionSet> hasTag(final Long tagId) {
return (targetRoot, query, cb) -> { return (dsRoot, query, cb) -> {
final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = targetRoot.join(JpaDistributionSet_.tags, final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = dsRoot.join(JpaDistributionSet_.tags,
JoinType.LEFT); JoinType.LEFT);
return cb.equal(tags.get(JpaDistributionSetTag_.id), tagId); 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<JpaDistributionSet> orderedByLinkedTarget(final String linkedControllerId) {
return (dsRoot, query, cb) -> {
final Root<JpaTarget> targetRoot = query.from(JpaTarget.class);
final Expression<Object> 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);
};
}
} }

View File

@@ -45,4 +45,24 @@ public final class RolloutSpecification {
} }
/**
* Builds a {@link Specification} to search a rollout by name.
*
* @param searchText
* search string
* @param isDeleted
* <code>true</code> if deleted rollouts should be included in
* the search. Otherwise <code>false</code>
* @return criteria specification with a query for name of a rollout
*
*/
public static Specification<JpaRollout> 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));
};
}
} }

View File

@@ -37,16 +37,18 @@ public final class SoftwareModuleSpecification {
/** /**
* {@link Specification} for retrieving {@link SoftwareModule}s by "like * {@link Specification} for retrieving {@link SoftwareModule}s by "like
* name or like version". * name and like version".
* *
* @param subString * @param name
* to be filtered on
* @param version
* to be filtered on * to be filtered on
* @return the {@link SoftwareModule} {@link Specification} * @return the {@link SoftwareModule} {@link Specification}
*/ */
public static Specification<JpaSoftwareModule> likeNameOrVersion(final String subString) { public static Specification<JpaSoftwareModule> likeNameAndVersion(final String name, final String version) {
return (targetRoot, query, cb) -> cb.or( return (smRoot, query, cb) -> cb.and(
cb.like(cb.lower(targetRoot.<String> get(JpaSoftwareModule_.name)), subString.toLowerCase()), cb.like(cb.lower(smRoot.<String> get(JpaSoftwareModule_.name)), name.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(JpaSoftwareModule_.version)), subString.toLowerCase())); cb.like(cb.lower(smRoot.<String> get(JpaSoftwareModule_.version)), version.toLowerCase()));
} }
/** /**
@@ -58,8 +60,22 @@ public final class SoftwareModuleSpecification {
* @return the {@link SoftwareModule} {@link Specification} * @return the {@link SoftwareModule} {@link Specification}
*/ */
public static Specification<JpaSoftwareModule> equalType(final Long type) { public static Specification<JpaSoftwareModule> equalType(final Long type) {
return (targetRoot, query, cb) -> cb.equal( return (smRoot, query, cb) -> cb.equal(
targetRoot.<JpaSoftwareModuleType> get(JpaSoftwareModule_.type).get(JpaSoftwareModuleType_.id), type); smRoot.<JpaSoftwareModuleType> get(JpaSoftwareModule_.type).get(JpaSoftwareModuleType_.id), type);
}
/**
* {@link Specification} for fetching {@link SoftwareModule}s type.
*
* @return the {@link SoftwareModule} {@link Specification}
*/
public static Specification<JpaSoftwareModule> fetchType() {
return (smRoot, query, cb) -> {
if (!query.getResultType().isAssignableFrom(Long.class)) {
smRoot.fetch(JpaSoftwareModule_.type);
}
return cb.conjunction();
};
} }
} }

View File

@@ -126,8 +126,8 @@ public final class TargetSpecifications {
} }
/** /**
* {@link Specification} for retrieving {@link Target}s that have the request * {@link Specification} for retrieving {@link Target}s that have the
* controller attributes flag set * request controller attributes flag set
* *
* @return the {@link Target} {@link Specification} * @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 Specification} for retrieving {@link Target}s by "equal to any
* {@link TargetUpdateStatus}". * given {@link TargetUpdateStatus}".
* *
* @param updateStatus * @param updateStatus
* to be filtered on * 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 Specification} for retrieving {@link Target}s by "not equal to
* {@link TargetUpdateStatus}". * given {@link TargetUpdateStatus}".
* *
* @param updateStatus * @param updateStatus
* to be filtered on * to be filtered on
@@ -194,14 +194,15 @@ public final class TargetSpecifications {
/** /**
* {@link Specification} for retrieving {@link Target}s that are overdue. A * {@link Specification} for retrieving {@link Target}s that are overdue. A
* target is overdue if it did not respond during the configured intervals:<br> * target is overdue if it did not respond during the configured
* intervals:<br>
* <em>poll_itvl + overdue_itvl</em> * <em>poll_itvl + overdue_itvl</em>
* *
* @param overdueTimestamp * @param overdueTimestamp
* the calculated timestamp to compare with the last respond of a * the calculated timestamp to compare with the last respond of a
* target (lastTargetQuery).<br> * target (lastTargetQuery).<br>
* The <code>overdueTimestamp</code> has to be calculated with the * The <code>overdueTimestamp</code> has to be calculated with
* following expression:<br> * the following expression:<br>
* <em>overdueTimestamp = nowTimestamp - poll_itvl - * <em>overdueTimestamp = nowTimestamp - poll_itvl -
* overdue_itvl</em> * overdue_itvl</em>
* *
@@ -212,23 +213,6 @@ public final class TargetSpecifications {
overdueTimestamp); 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<JpaTarget> 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 * {@link Specification} for retrieving {@link Target}s by "like attribute
* value". * value".
@@ -248,19 +232,24 @@ public final class TargetSpecifications {
} }
/** /**
* {@link Specification} for retrieving {@link Target}s by "like controllerId or * {@link Specification} for retrieving {@link Target}s by "like
* like name or like description or like attribute value". * controllerId or like name".
* *
* @param searchText * @param searchText
* to be filtered on * to be filtered on
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<JpaTarget> likeIdOrNameOrDescriptionOrAttributeValue(final String searchText) { public static Specification<JpaTarget> likeControllerIdOrName(final String searchText) {
return Specification.where(likeIdOrNameOrDescription(searchText)).or(likeAttributeValue(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 * @param distributionId
* to be filtered on * to be filtered on
@@ -271,8 +260,8 @@ public final class TargetSpecifications {
} }
/** /**
* Finds all targets by given {@link Target#getControllerId()}s and which are * Finds all targets by given {@link Target#getControllerId()}s and which
* not yet assigned to given {@link DistributionSet}. * are not yet assigned to given {@link DistributionSet}.
* *
* @param tIDs * @param tIDs
* to search for. * to search for.
@@ -305,8 +294,8 @@ public final class TargetSpecifications {
} }
/** /**
* {@link Specification} for retrieving {@link Target}s by "has no tag names"or * {@link Specification} for retrieving {@link Target}s by "has no tag
* "has at least on of the given tag names". * names"or "has at least on of the given tag names".
* *
* @param tagNames * @param tagNames
* to be filtered on * to be filtered on
@@ -348,8 +337,8 @@ public final class TargetSpecifications {
} }
/** /**
* {@link Specification} for retrieving {@link Target}s by assigned distribution * {@link Specification} for retrieving {@link Target}s by assigned
* set. * distribution set.
* *
* @param distributionSetId * @param distributionSetId
* the ID of the distribution set which must be assigned * 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 * {@link Specification} for retrieving {@link Target}s that are compatible
* given {@link DistributionSetType}. Compatibility is evaluated by checking the * with given {@link DistributionSetType}. Compatibility is evaluated by
* {@link TargetType} of a target. Targets that don't have a {@link TargetType} * checking the {@link TargetType} of a target. Targets that don't have a
* are compatible with all {@link DistributionSetType} * {@link TargetType} are compatible with all {@link DistributionSetType}
* *
* @param distributionSetTypeId * @param distributionSetTypeId
* the ID of the distribution set type which must be compatible * the ID of the distribution set type which must be compatible
@@ -399,15 +388,16 @@ public final class TargetSpecifications {
}; };
} }
private static Predicate getTargetTypeIsNullPredicate(Root<JpaTarget> targetRoot) { private static Predicate getTargetTypeIsNullPredicate(final Root<JpaTarget> targetRoot) {
return targetRoot.get(JpaTarget_.targetType).isNull(); return targetRoot.get(JpaTarget_.targetType).isNull();
} }
/** /**
* {@link Specification} for retrieving {@link Target}s that are NOT compatible * {@link Specification} for retrieving {@link Target}s that are NOT
* with given {@link DistributionSetType}. Compatibility is evaluated by * compatible with given {@link DistributionSetType}. Compatibility is
* checking the {@link TargetType} of a target. Targets that don't have a * evaluated by checking the {@link TargetType} of a target. Targets that
* {@link TargetType} are compatible with all {@link DistributionSetType} * don't have a {@link TargetType} are compatible with all
* {@link DistributionSetType}
* *
* @param distributionSetTypeId * @param distributionSetTypeId
* the ID of the distribution set type which must be incompatible * 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 * {@link Specification} for retrieving {@link Target}s that are in an
* for a given {@link RolloutGroup} * action for a given {@link RolloutGroup}
* *
* @param group * @param group
* the {@link RolloutGroup} * the {@link RolloutGroup}
@@ -490,8 +480,8 @@ public final class TargetSpecifications {
} }
/** /**
* {@link Specification} for retrieving {@link Target}s that have no Action of * {@link Specification} for retrieving {@link Target}s that have no Action
* the {@link RolloutGroup}. * of the {@link RolloutGroup}.
* *
* @param group * @param group
* the {@link RolloutGroup} * the {@link RolloutGroup}
@@ -512,8 +502,8 @@ public final class TargetSpecifications {
} }
/** /**
* {@link Specification} for retrieving {@link Target}s by assigned distribution * {@link Specification} for retrieving {@link Target}s by assigned
* set. * distribution set.
* *
* @param distributionSetId * @param distributionSetId
* the ID of the distribution set which must be assigned * 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} * @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 * {@link Specification} for retrieving {@link Target}s that don't have
* type assigned * target type assigned
* *
* @param typeId * @param typeId
* the id of the target type * 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 * Can be added to specification chain to order result by provided
* set * distribution set
* *
* Order: 1. Targets with DS installed, 2. Targets with DS assigned, 3. Based on * Order: 1. Targets with DS installed, 2. Targets with DS assigned, 3.
* target id * Based on target id
* *
* NOTE: Other specs, pagables and sort objects may alter the queries orderBy * NOTE: Other specs, pagables and sort objects may alter the queries
* entry too, possibly invalidating the applied order, keep in mind when using * orderBy entry too, possibly invalidating the applied order, keep in mind
* this * when using this
* *
* @param distributionSetIdForOrder * @param distributionSetIdForOrder
* distribution set to consider * distribution set to consider

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status);

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status);

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status);

View File

@@ -0,0 +1,3 @@
CREATE INDEX sp_idx_rollout_status_tenant
ON sp_rollout
USING BTREE (tenant, status);

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status);

View File

@@ -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.jpa.model.JpaDistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.DistributionSetFilter.DistributionSetFilterBuilder;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation; import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType; import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
@@ -215,9 +216,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("entity with invalid description should not be created") .as("entity with invalid description should not be created")
.isThrownBy(() -> distributionSetManagement.create( .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a")
entityFactory.distributionSet().create().name("a").version("a") .version("a").description(INVALID_TEXT_HTML)));
.description(INVALID_TEXT_HTML)));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("entity with too long description should not be updated") .as("entity with too long description should not be updated")
@@ -225,8 +225,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
.description(RandomStringUtils.randomAlphanumeric(513)))); .description(RandomStringUtils.randomAlphanumeric(513))));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("entity with invalid characters should not be updated") .as("entity with invalid characters should not be updated").isThrownBy(() -> distributionSetManagement
.isThrownBy(() -> distributionSetManagement
.update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML))); .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)))); .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("entity with invalid characters should not be updated") .as("entity with invalid characters should not be updated").isThrownBy(() -> distributionSetManagement
.isThrownBy(() -> distributionSetManagement
.update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML))); .update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML)));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
@@ -383,7 +381,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
// add some meta data entries // add some meta data entries
final DistributionSet ds3 = testdataFactory.createDistributionSet("ds3"); 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) { for (int i = 0; i < firstHalf; ++i) {
createDistributionSetMetadata(ds3.getId(), new JpaDistributionSetMetadata("k" + i, ds3, "v" + 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) assignedDS.stream().map(c -> (JpaDistributionSet) c)
.forEach(ds -> assertThat(ds.getTags().size()).as("ds has wrong tag size").isEqualTo(1)); .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") assertThat(assignedDS.size()).as("assigned ds has wrong size")
.isEqualTo(distributionSetManagement.findByTag(PAGE, tag.getId()).getNumberOfElements()); .isEqualTo(distributionSetManagement.findByTag(PAGE, tag.getId()).getNumberOfElements());
@@ -549,7 +547,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
// assign some software modules // assign some software modules
final DistributionSet ds3 = testdataFactory.createDistributionSetWithNoSoftwareModules("ds3", "1.0"); 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) { for (int i = 0; i < firstHalf; ++i) {
distributionSetManagement.assignSoftwareModules(ds3.getId(), singletonList(modules.get(i))); distributionSetManagement.assignSoftwareModules(ds3.getId(), singletonList(modules.get(i)));
} }
@@ -566,9 +564,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs(); final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs();
assertThatExceptionOfType(InvalidDistributionSetException.class) assertThatExceptionOfType(InvalidDistributionSetException.class)
.as("Invalid distributionSet should throw an exception") .as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement
.isThrownBy(() -> distributionSetManagement.assignSoftwareModules(distributionSet.getId(), .assignSoftwareModules(distributionSet.getId(), singletonList(softwareModule.getId())));
singletonList(softwareModule.getId())));
} }
@Test @Test
@@ -576,10 +573,9 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
void verifyUnassignSoftwareModulesToInvalidDistributionSet() { void verifyUnassignSoftwareModulesToInvalidDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet(); final DistributionSet distributionSet = testdataFactory.createDistributionSet();
final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs(); final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs();
distributionSetManagement.assignSoftwareModules(distributionSet.getId(), distributionSetManagement.assignSoftwareModules(distributionSet.getId(), singletonList(softwareModule.getId()));
singletonList(softwareModule.getId())); distributionSetInvalidationManagement.invalidateDistributionSet(
distributionSetInvalidationManagement.invalidateDistributionSet(new DistributionSetInvalidation( new DistributionSetInvalidation(singletonList(distributionSet.getId()), CancelationType.NONE, false));
singletonList(distributionSet.getId()), CancelationType.NONE, false));
assertThatExceptionOfType(InvalidDistributionSetException.class) assertThatExceptionOfType(InvalidDistributionSetException.class)
.as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement .as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement
@@ -647,13 +643,12 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
assignDistributionSet(dsFour.getId(), tSecond.getControllerId()); assignDistributionSet(dsFour.getId(), tSecond.getControllerId());
final DistributionSetFilterBuilder distributionSetFilterBuilder = new DistributionSetFilterBuilder() final DistributionSetFilter distributionSetFilter = new DistributionSetFilterBuilder().setIsDeleted(false)
.setIsDeleted(false).setIsComplete(true).setSelectDSWithNoTag(Boolean.FALSE); .setIsComplete(true).setSelectDSWithNoTag(Boolean.FALSE).build();
// target first only has an assigned DS-three so check order correct // target first only has an assigned DS-three so check order correct
final List<DistributionSet> tFirstPin = distributionSetManagement final List<DistributionSet> tFirstPin = distributionSetManagement
.findByFilterAndAssignedInstalledDsOrderedByLinkTarget(PAGE, distributionSetFilterBuilder, .findByDistributionSetFilterOrderByLinkedTarget(PAGE, distributionSetFilter, tFirst.getControllerId())
tFirst.getControllerId())
.getContent(); .getContent();
assertThat(tFirstPin.get(0)).isEqualTo(dsThree); assertThat(tFirstPin.get(0)).isEqualTo(dsThree);
assertThat(tFirstPin).hasSize(10); 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 // target second has installed DS-2 and assigned DS-4 so check order
// correct // correct
final List<DistributionSet> tSecondPin = distributionSetManagement final List<DistributionSet> tSecondPin = distributionSetManagement
.findByFilterAndAssignedInstalledDsOrderedByLinkTarget(PAGE, distributionSetFilterBuilder, .findByDistributionSetFilterOrderByLinkedTarget(PAGE, distributionSetFilter, tSecond.getControllerId())
tSecond.getControllerId())
.getContent(); .getContent();
assertThat(tSecondPin.get(0)).isEqualTo(dsSecond); assertThat(tSecondPin.get(0)).isEqualTo(dsSecond);
assertThat(tSecondPin.get(1)).isEqualTo(dsFour); assertThat(tSecondPin.get(1)).isEqualTo(dsFour);
@@ -724,15 +718,14 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
validateDeleted(dsDeleted, sizeOfAllDistributionSets - 1); validateDeleted(dsDeleted, sizeOfAllDistributionSets - 1);
validateCompleted(dsInComplete, sizeOfAllDistributionSets - 1); validateCompleted(dsInComplete, sizeOfAllDistributionSets - 1);
validateType(newType, dsNewType, sizeOfAllDistributionSets - 1); validateType(newType, dsNewType, sizeOfAllDistributionSets - 1);
validateSearchText(dsGroup2, "%" + dsGroup2Prefix); validateSearchText(allDistributionSets, dsGroup2Prefix);
validateFilterString(allDistributionSets, dsGroup2Prefix);
validateTags(dsTagA, dsTagB, dsTagC, dsGroup1WithGroup2, dsGroup1); validateTags(dsTagA, dsTagB, dsTagC, dsGroup1WithGroup2, dsGroup1);
validateDeletedAndCompleted(dsGroup1WithGroup2, dsNewType, dsDeleted); validateDeletedAndCompleted(dsGroup1WithGroup2, dsNewType, dsDeleted);
validateDeletedAndCompletedAndType(dsGroup1WithGroup2, dsDeleted, newType, dsNewType); validateDeletedAndCompletedAndType(dsGroup1WithGroup2, dsDeleted, newType, dsNewType);
validateDeletedAndCompletedAndTypeAndSearchText(dsGroup2, newType, "%" + dsGroup2Prefix); validateDeletedAndCompletedAndTypeAndSearchText(dsGroup2, newType, dsGroup2Prefix);
validateDeletedAndCompletedAndTypeAndFilterString(dsGroup1WithGroup2, dsDeleted, dsInComplete, dsNewType, validateDeletedAndCompletedAndTypeAndSearchText(dsGroup1WithGroup2, dsDeleted, dsInComplete, dsNewType, newType,
newType, ":1"); ":1");
validateDeletedAndCompletedAndTypeAndSearchTextAndTag(dsGroup2, dsTagA, "%" + dsGroup2Prefix); validateDeletedAndCompletedAndTypeAndSearchTextAndTag(dsGroup2, dsTagA, dsGroup2Prefix);
} }
@Step @Step
@@ -764,59 +757,51 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
@Step @Step
private void validateType(final DistributionSetType newType, final DistributionSet dsNewType, private void validateType(final DistributionSetType newType, final DistributionSet dsNewType,
final int standardDsTypeSize) { final int standardDsTypeSize) {
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setTypeId(newType.getId()),
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setType(newType),
singletonList(dsNewType)); singletonList(dsNewType));
assertThatFilterHasSizeAndDoesNotContainDistributionSet( assertThatFilterHasSizeAndDoesNotContainDistributionSet(
getDistributionSetFilterBuilder().setType(standardDsType), standardDsTypeSize, dsNewType); getDistributionSetFilterBuilder().setTypeId(standardDsType.getId()), standardDsTypeSize, dsNewType);
} }
@Step @Step
private void validateSearchText(final List<DistributionSet> withText, final String text) { private void validateSearchText(final List<DistributionSet> allDistributionSets, final String dsNamePrefix) {
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(text),
withText);
}
@Step
private void validateFilterString(final List<DistributionSet> allDistributionSets, final String dsNamePrefix) {
final List<DistributionSet> withTestNamePrefix = allDistributionSets.stream() final List<DistributionSet> withTestNamePrefix = allDistributionSets.stream()
.filter(ds -> ds.getName().startsWith(dsNamePrefix)).collect(Collectors.toList()); .filter(ds -> ds.getName().startsWith(dsNamePrefix)).collect(Collectors.toList());
assertThatFilterContainsOnlyGivenDistributionSets( assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(dsNamePrefix),
getDistributionSetFilterBuilder().setFilterString(dsNamePrefix), withTestNamePrefix); withTestNamePrefix);
final List<DistributionSet> withTestNameExact = withTestNamePrefix.stream() final List<DistributionSet> withTestNameExact = withTestNamePrefix.stream()
.filter(ds -> ds.getName().equals(dsNamePrefix)).collect(Collectors.toList()); .filter(ds -> ds.getName().equals(dsNamePrefix)).collect(Collectors.toList());
assertThatFilterContainsOnlyGivenDistributionSets( assertThatFilterContainsOnlyGivenDistributionSets(
getDistributionSetFilterBuilder().setFilterString(dsNamePrefix + ":"), withTestNameExact); getDistributionSetFilterBuilder().setSearchText(dsNamePrefix + ":"), withTestNameExact);
final List<DistributionSet> withTestNameExactAndVersionPrefix = withTestNameExact.stream() final List<DistributionSet> withTestNameExactAndVersionPrefix = withTestNameExact.stream()
.filter(ds -> ds.getVersion().startsWith("1")).collect(Collectors.toList()); .filter(ds -> ds.getVersion().startsWith("1")).collect(Collectors.toList());
assertThatFilterContainsOnlyGivenDistributionSets( assertThatFilterContainsOnlyGivenDistributionSets(
getDistributionSetFilterBuilder().setFilterString(dsNamePrefix + ":1"), getDistributionSetFilterBuilder().setSearchText(dsNamePrefix + ":1"),
withTestNameExactAndVersionPrefix); withTestNameExactAndVersionPrefix);
final List<DistributionSet> dsWithExactNameAndVersion = withTestNameExactAndVersionPrefix.stream() final List<DistributionSet> dsWithExactNameAndVersion = withTestNameExactAndVersionPrefix.stream()
.filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList()); .filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList());
assertThat(dsWithExactNameAndVersion).hasSize(1); assertThat(dsWithExactNameAndVersion).hasSize(1);
assertThatFilterContainsOnlyGivenDistributionSets( assertThatFilterContainsOnlyGivenDistributionSets(
getDistributionSetFilterBuilder().setFilterString(dsNamePrefix + ":1.0.0"), dsWithExactNameAndVersion); getDistributionSetFilterBuilder().setSearchText(dsNamePrefix + ":1.0.0"), dsWithExactNameAndVersion);
final List<DistributionSet> withVersionPrefix = allDistributionSets.stream() final List<DistributionSet> withVersionPrefix = allDistributionSets.stream()
.filter(ds -> ds.getVersion().startsWith("1.0.")).collect(Collectors.toList()); .filter(ds -> ds.getVersion().startsWith("1.0.")).collect(Collectors.toList());
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setFilterString(":1.0."), assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(":1.0."),
withVersionPrefix); withVersionPrefix);
final List<DistributionSet> withVersionExact = withVersionPrefix.stream() final List<DistributionSet> withVersionExact = withVersionPrefix.stream()
.filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList()); .filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList());
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setFilterString(":1.0.0"), assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(":1.0.0"),
withVersionExact); withVersionExact);
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setFilterString(":"), assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(":"),
allDistributionSets); allDistributionSets);
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setFilterString(" : "), assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(" : "),
allDistributionSets); allDistributionSets);
} }
@@ -864,18 +849,14 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
@Step @Step
private void validateDeletedAndCompletedAndType(final List<DistributionSet> deletedAndCompletedAndStandardType, private void validateDeletedAndCompletedAndType(final List<DistributionSet> deletedAndCompletedAndStandardType,
final DistributionSet dsDeleted, final DistributionSetType newType, final DistributionSet dsNewType) { final DistributionSet dsDeleted, final DistributionSetType newType, final DistributionSet dsNewType) {
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsDeleted(Boolean.FALSE) assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsDeleted(Boolean.FALSE)
.setIsComplete(Boolean.TRUE).setType(standardDsType), deletedAndCompletedAndStandardType); .setIsComplete(Boolean.TRUE).setTypeId(standardDsType.getId()), deletedAndCompletedAndStandardType);
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) 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) assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setIsDeleted(Boolean.TRUE)
.setIsComplete(Boolean.FALSE).setType(standardDsType)); .setIsComplete(Boolean.FALSE).setTypeId(standardDsType.getId()));
assertThatFilterContainsOnlyGivenDistributionSets( assertThatFilterContainsOnlyGivenDistributionSets(
getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setType(newType), getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setTypeId(newType.getId()),
singletonList(dsNewType)); singletonList(dsNewType));
} }
@@ -884,21 +865,23 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
final List<DistributionSet> completedAndStandardTypeAndSearchText, final DistributionSetType newType, final List<DistributionSet> completedAndStandardTypeAndSearchText, final DistributionSetType newType,
final String text) { final String text) {
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsDeleted(Boolean.FALSE)
.setType(standardDsType).setSearchText(text), completedAndStandardTypeAndSearchText); .setIsComplete(Boolean.TRUE).setTypeId(standardDsType.getId()).setSearchText(text),
completedAndStandardTypeAndSearchText);
assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE)
.setIsDeleted(Boolean.TRUE).setType(standardDsType).setSearchText(text)); .setIsDeleted(Boolean.TRUE).setTypeId(standardDsType.getId()).setSearchText(text + ":"));
assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setType(standardDsType) assertThatFilterDoesNotContainAnyDistributionSet(
.setSearchText(text).setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE)); 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)); .setSearchText(text).setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE));
} }
@Step @Step
private void validateDeletedAndCompletedAndTypeAndFilterString( private void validateDeletedAndCompletedAndTypeAndSearchText(
final List<DistributionSet> completedAndNotDeletedStandardTypeAndFilterString, final List<DistributionSet> completedAndNotDeletedStandardTypeAndFilterString,
final DistributionSet dsDeleted, final DistributionSet dsInComplete, final DistributionSet dsNewType, final DistributionSet dsDeleted, final DistributionSet dsInComplete, final DistributionSet dsNewType,
final DistributionSetType newType, final String filterString) { final DistributionSetType newType, final String filterString) {
@@ -907,23 +890,25 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
completedAndNotDeletedStandardTypeAndFilterString); completedAndNotDeletedStandardTypeAndFilterString);
completedAndStandardTypeAndFilterString.add(dsDeleted); completedAndStandardTypeAndFilterString.add(dsDeleted);
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE)
.setType(standardDsType).setFilterString(filterString), completedAndStandardTypeAndFilterString); .setTypeId(standardDsType.getId()).setSearchText(filterString),
completedAndStandardTypeAndFilterString);
assertThatFilterContainsOnlyGivenDistributionSets( assertThatFilterContainsOnlyGivenDistributionSets(
getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE) getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE)
.setType(standardDsType).setFilterString(filterString), .setTypeId(standardDsType.getId()).setSearchText(filterString),
completedAndNotDeletedStandardTypeAndFilterString); completedAndNotDeletedStandardTypeAndFilterString);
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE)
.setIsDeleted(Boolean.TRUE).setType(standardDsType).setFilterString(filterString), .setIsDeleted(Boolean.TRUE).setTypeId(standardDsType.getId()).setSearchText(filterString),
singletonList(dsDeleted)); singletonList(dsDeleted));
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setType(standardDsType) assertThatFilterContainsOnlyGivenDistributionSets(
.setFilterString(filterString).setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE), getDistributionSetFilterBuilder().setTypeId(standardDsType.getId()).setSearchText(filterString)
.setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE),
singletonList(dsInComplete)); singletonList(dsInComplete));
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setType(newType) assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setTypeId(newType.getId())
.setFilterString(filterString).setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE), .setSearchText(filterString).setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE),
singletonList(dsNewType)); singletonList(dsNewType));
} }
@@ -933,13 +918,13 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
final String text) { final String text) {
assertThatFilterContainsOnlyGivenDistributionSets( assertThatFilterContainsOnlyGivenDistributionSets(
getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setType(standardDsType) getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setTypeId(standardDsType.getId())
.setSearchText(text).setTagNames(singletonList(dsTagA.getName())), .setSearchText(text).setTagNames(singletonList(dsTagA.getName())),
completedAndStandartTypeAndSearchTextAndTagA); completedAndStandartTypeAndSearchTextAndTagA);
assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setType(standardDsType) assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder()
.setSearchText(text).setTagNames(singletonList(dsTagA.getName())).setIsComplete(Boolean.FALSE) .setTypeId(standardDsType.getId()).setSearchText(text).setTagNames(singletonList(dsTagA.getName()))
.setIsDeleted(Boolean.FALSE)); .setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE));
} }
private DistributionSetFilterBuilder getDistributionSetFilterBuilder() { private DistributionSetFilterBuilder getDistributionSetFilterBuilder() {
@@ -983,7 +968,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
distributionSetManagement.delete(ds1.getId()); distributionSetManagement.delete(ds1.getId());
// not assigned so not marked as deleted but fully deleted // not assigned so not marked as deleted but fully deleted
assertThat(distributionSetRepository.findAll()).hasSize(1); assertThat(distributionSetRepository.findAll()).hasSize(1);
assertThat(distributionSetManagement.findByCompleted(PAGE, true).getTotalElements()).isEqualTo(1); assertThat(distributionSetManagement.findByCompleted(PAGE, true)).hasSize(1);
} }
@Test @Test
@@ -1027,11 +1012,15 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
final Page<DistributionSetMetadata> metadataOfDs2 = distributionSetManagement final Page<DistributionSetMetadata> metadataOfDs2 = distributionSetManagement
.findMetaDataByDistributionSetId(PageRequest.of(0, 100), ds2.getId()); .findMetaDataByDistributionSetId(PageRequest.of(0, 100), ds2.getId());
assertThat(metadataOfDs1.getNumberOfElements()).isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet()); assertThat(metadataOfDs1.getNumberOfElements())
assertThat(metadataOfDs1.getTotalElements()).isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet()); .isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet());
assertThat(metadataOfDs1.getTotalElements())
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet());
assertThat(metadataOfDs2.getNumberOfElements()).isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1); assertThat(metadataOfDs2.getNumberOfElements())
assertThat(metadataOfDs2.getTotalElements()).isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1); .isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1);
assertThat(metadataOfDs2.getTotalElements())
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1);
} }
@Test @Test
@@ -1056,7 +1045,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
// not assigned so not marked as deleted // not assigned so not marked as deleted
assertThat(distributionSetRepository.findAll()).hasSize(4); assertThat(distributionSetRepository.findAll()).hasSize(4);
assertThat(distributionSetManagement.findByCompleted(PAGE, true).getTotalElements()).isEqualTo(2); assertThat(distributionSetManagement.findByCompleted(PAGE, true)).hasSize(2);
} }
@Test @Test
@@ -1131,7 +1120,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
} }
// can be removed with java-11 // can be removed with java-11
private <T> T getOrThrow(Optional<T> opt) { private <T> T getOrThrow(final Optional<T> opt) {
return opt.orElseThrow(NoSuchElementException::new); return opt.orElseThrow(NoSuchElementException::new);
} }
} }

View File

@@ -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.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.builder.TagCreate; 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.Description;
import io.qameta.allure.Feature; import io.qameta.allure.Feature;
import io.qameta.allure.Step;
import io.qameta.allure.Story; 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(tagB.getName()).get());
toggleTagAssignment(dsABCs, distributionSetTagManagement.getByName(tagC.getName()).get()); toggleTagAssignment(dsABCs, distributionSetTagManagement.getByName(tagC.getName()).get());
DistributionSetFilterBuilder distributionSetFilterBuilder;
// search for not deleted // search for not deleted
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true) final DistributionSetFilterBuilder distributionSetFilterBuilder = getDistributionSetFilterBuilder()
.setTagNames(Arrays.asList(tagA.getName())); .setIsComplete(true);
assertEquals(dsAs.spliterator().getExactSizeIfKnown() + dsABs.spliterator().getExactSizeIfKnown() verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagA.getName())),
+ dsACs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(), Stream.of(dsAs, dsABs, dsACs, dsABCs));
distributionSetManagement.findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()) verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagB.getName())),
.getTotalElements(), Stream.of(dsBs, dsABs, dsBCs, dsABCs));
"filter works not correct"); verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagC.getName())),
Stream.of(dsCs, dsACs, dsBCs, dsABCs));
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true) verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagX.getName())),
.setTagNames(Arrays.asList(tagB.getName())); Stream.empty());
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");
assertThat(distributionSetTagRepository.findAll()).hasSize(5);
distributionSetTagManagement.delete(tagY.getName()); distributionSetTagManagement.delete(tagY.getName());
assertEquals(4, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown(), "wrong tag size"); assertThat(distributionSetTagRepository.findAll()).hasSize(4);
distributionSetTagManagement.delete(tagX.getName()); distributionSetTagManagement.delete(tagX.getName());
assertEquals(3, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown(), "wrong tag size"); assertThat(distributionSetTagRepository.findAll()).hasSize(3);
distributionSetTagManagement.delete(tagB.getName()); distributionSetTagManagement.delete(tagB.getName());
assertEquals(2, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown(), "wrong tag size"); assertThat(distributionSetTagRepository.findAll()).hasSize(2);
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagA.getName())),
.setTagNames(Arrays.asList(tagA.getName())); Stream.of(dsAs, dsABs, dsACs, dsABCs));
assertEquals(dsAs.spliterator().getExactSizeIfKnown() + dsABs.spliterator().getExactSizeIfKnown() verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagB.getName())),
+ dsACs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(), Stream.empty());
distributionSetManagement.findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()) verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.setTagNames(Arrays.asList(tagC.getName())),
.getTotalElements(), Stream.of(dsCs, dsACs, dsBCs, dsABCs));
"filter works not correct"); }
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) @Step
.setTagNames(Arrays.asList(tagB.getName())); private void verifyExpectedFilteredDistributionSets(final DistributionSetFilterBuilder distributionSetFilterBuilder,
assertEquals(0, distributionSetManagement final Stream<Collection<DistributionSet>> expectedFilteredDistributionSets) {
.findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()).getTotalElements(), final Collection<Long> retrievedFilteredDsIds = distributionSetManagement
"filter works not correct"); .findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()).stream()
.map(DistributionSet::getId).collect(Collectors.toList());
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE) final Collection<Long> expectedFilteredDsIds = expectedFilteredDistributionSets.flatMap(Collection::stream)
.setTagNames(Arrays.asList(tagC.getName())); .map(DistributionSet::getId).collect(Collectors.toList());
assertEquals(dsCs.spliterator().getExactSizeIfKnown() + dsACs.spliterator().getExactSizeIfKnown() assertThat(retrievedFilteredDsIds).hasSameElementsAs(expectedFilteredDsIds);
+ dsBCs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(),
distributionSetManagement.findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build())
.getTotalElements(),
"filter works not correct");
} }
@Test @Test
@@ -182,11 +155,11 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest
// toggle A only -> A is now assigned // toggle A only -> A is now assigned
DistributionSetTagAssignmentResult result = toggleTagAssignment(groupA, tag); DistributionSetTagAssignmentResult result = toggleTagAssignment(groupA, tag);
assertThat(result.getAlreadyAssigned()).isEqualTo(0); assertThat(result.getAlreadyAssigned()).isZero();
assertThat(result.getAssigned()).isEqualTo(20); assertThat(result.getAssigned()).isEqualTo(20);
assertThat(result.getAssignedEntity()).containsAll(distributionSetManagement assertThat(result.getAssignedEntity()).containsAll(distributionSetManagement
.get(groupA.stream().map(DistributionSet::getId).collect(Collectors.toList()))); .get(groupA.stream().map(DistributionSet::getId).collect(Collectors.toList())));
assertThat(result.getUnassigned()).isEqualTo(0); assertThat(result.getUnassigned()).isZero();
assertThat(result.getUnassignedEntity()).isEmpty(); assertThat(result.getUnassignedEntity()).isEmpty();
assertThat(result.getDistributionSetTag()).isEqualTo(tag); assertThat(result.getDistributionSetTag()).isEqualTo(tag);
@@ -196,14 +169,14 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest
assertThat(result.getAssigned()).isEqualTo(20); assertThat(result.getAssigned()).isEqualTo(20);
assertThat(result.getAssignedEntity()).containsAll(distributionSetManagement assertThat(result.getAssignedEntity()).containsAll(distributionSetManagement
.get(groupB.stream().map(DistributionSet::getId).collect(Collectors.toList()))); .get(groupB.stream().map(DistributionSet::getId).collect(Collectors.toList())));
assertThat(result.getUnassigned()).isEqualTo(0); assertThat(result.getUnassigned()).isZero();
assertThat(result.getUnassignedEntity()).isEmpty(); assertThat(result.getUnassignedEntity()).isEmpty();
assertThat(result.getDistributionSetTag()).isEqualTo(tag); assertThat(result.getDistributionSetTag()).isEqualTo(tag);
// toggle A+B -> both unassigned // toggle A+B -> both unassigned
result = toggleTagAssignment(concat(groupA, groupB), tag); result = toggleTagAssignment(concat(groupA, groupB), tag);
assertThat(result.getAlreadyAssigned()).isEqualTo(0); assertThat(result.getAlreadyAssigned()).isZero();
assertThat(result.getAssigned()).isEqualTo(0); assertThat(result.getAssigned()).isZero();
assertThat(result.getAssignedEntity()).isEmpty(); assertThat(result.getAssignedEntity()).isEmpty();
assertThat(result.getUnassigned()).isEqualTo(40); assertThat(result.getUnassigned()).isEqualTo(40);
assertThat(result.getUnassignedEntity()).containsAll(distributionSetManagement assertThat(result.getUnassignedEntity()).containsAll(distributionSetManagement

View File

@@ -22,6 +22,7 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.validation.ConstraintViolationException; import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException; import javax.validation.ValidationException;
@@ -139,8 +140,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that a running action is auto canceled by a rollout which assigns another distribution-set.") @Description("Verifies that a running action is auto canceled by a rollout which assigns another distribution-set.")
void rolloutAssignsNewDistributionSetAndAutoCloseActiveActions() { void rolloutAssignsNewDistributionSetAndAutoCloseActiveActions() {
tenantConfigurationManagement.addOrUpdateConfiguration( tenantConfigurationManagement
TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, true); .addOrUpdateConfiguration(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, true);
try { try {
// manually assign distribution set to target // manually assign distribution set to target
@@ -197,9 +198,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
@Expect(type = RolloutGroupUpdatedEvent.class, count = 5), @Expect(type = RolloutGroupUpdatedEvent.class, count = 5),
@Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = RolloutCreatedEvent.class, count = 1), @Expect(type = RolloutCreatedEvent.class, count = 1), @Expect(type = RolloutUpdatedEvent.class, count = 1),
@Expect(type = RolloutUpdatedEvent.class, count = 1), @Expect(type = TargetCreatedEvent.class, count = 125) })
@Expect(type = TargetCreatedEvent.class, count = 125)})
void entityQueriesReferringToNotExistingEntitiesThrowsException() { void entityQueriesReferringToNotExistingEntitiesThrowsException() {
testdataFactory.createRollout("xxx"); testdataFactory.createRollout("xxx");
@@ -255,7 +255,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
scheduledGroups.forEach(group -> assertThat(group.getStatus()) scheduledGroups.forEach(group -> assertThat(group.getStatus())
.as("group which should be in scheduled state is in " + group.getStatus() + " state") .as("group which should be in scheduled state is in " + group.getStatus() + " state")
.isEqualTo(RolloutGroupStatus.SCHEDULED)); .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<Action> runningActions = findActionsByRolloutAndStatus(createdRollout, Status.RUNNING); final List<Action> runningActions = findActionsByRolloutAndStatus(createdRollout, Status.RUNNING);
assertThat(runningActions).hasSize(amountTargetsForRollout / amountGroups) assertThat(runningActions).hasSize(amountTargetsForRollout / amountGroups)
.as("Created actions are initiated by rollout creator") .as("Created actions are initiated by rollout creator")
@@ -522,8 +523,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
rolloutManagement.handleRollouts(); rolloutManagement.handleRollouts();
// finish running actions, 2 actions should be finished // finish running actions, 2 actions should be finished
assertThat(changeStatusForAllRunningActions(createdRollout, Status.FINISHED)).isEqualTo(2); assertThat(changeStatusForAllRunningActions(createdRollout, Status.FINISHED)).isEqualTo(2);
assertThat(getRollout(createdRollout.getId()).getStatus()) assertThat(getRollout(createdRollout.getId()).getStatus()).isEqualTo(RolloutStatus.RUNNING);
.isEqualTo(RolloutStatus.RUNNING);
} }
// check rollout to see that all actions and all groups are finished and // 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); changeStatusForAllRunningActions(rolloutD, Status.FINISHED);
rolloutManagement.handleRollouts(); rolloutManagement.handleRollouts();
final Page<Rollout> rolloutPage = rolloutManagement final Slice<Rollout> rolloutPage = rolloutManagement
.findAllWithDetailedStatus(new OffsetBasedPageRequest(0, 100, Sort.by(Direction.ASC, "name")), false); .findAllWithDetailedStatus(new OffsetBasedPageRequest(0, 100, Sort.by(Direction.ASC, "name")), false);
final List<Rollout> rolloutList = rolloutPage.getContent(); final List<Rollout> rolloutList = rolloutPage.getContent();
@@ -1387,12 +1387,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
// group1 exceeds the quota // group1 exceeds the quota
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create(
entityFactory.rollout() entityFactory.rollout().create().name(rolloutName).description(rolloutName)
.create() .targetFilterQuery("controllerId==" + rolloutName + "-*").set(distributionSet),
.name(rolloutName) Arrays.asList(group1, group2), conditions));
.description(rolloutName)
.targetFilterQuery("controllerId==" + rolloutName + "-*")
.set(distributionSet), Arrays.asList(group1, group2), conditions));
// create group definitions // create group definitions
final RolloutGroupCreate group3 = entityFactory.rolloutGroup().create().conditions(conditions).name("group3") final RolloutGroupCreate group3 = entityFactory.rolloutGroup().create().conditions(conditions).name("group3")
@@ -1402,37 +1399,23 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
// group4 exceeds the quota // group4 exceeds the quota
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create(
entityFactory.rollout() entityFactory.rollout().create().name(rolloutName).description(rolloutName)
.create() .targetFilterQuery("controllerId==" + rolloutName + "-*").set(distributionSet),
.name(rolloutName) Arrays.asList(group3, group4), conditions));
.description(rolloutName)
.targetFilterQuery("controllerId==" + rolloutName + "-*")
.set(distributionSet), Arrays.asList(group3, group4), conditions));
// create group definitions // create group definitions
final RolloutGroupCreate group5 = entityFactory.rolloutGroup() final RolloutGroupCreate group5 = entityFactory.rolloutGroup().create().conditions(conditions).name("group5")
.create()
.conditions(conditions)
.name("group5")
.targetPercentage(33.3F); .targetPercentage(33.3F);
final RolloutGroupCreate group6 = entityFactory.rolloutGroup() final RolloutGroupCreate group6 = entityFactory.rolloutGroup().create().conditions(conditions).name("group6")
.create()
.conditions(conditions)
.name("group6")
.targetPercentage(66.6F); .targetPercentage(66.6F);
final RolloutGroupCreate group7 = entityFactory.rolloutGroup() final RolloutGroupCreate group7 = entityFactory.rolloutGroup().create().conditions(conditions).name("group7")
.create()
.conditions(conditions)
.name("group7")
.targetPercentage(100.0F); .targetPercentage(100.0F);
// should work fine // should work fine
assertThat(rolloutManagement.create(entityFactory.rollout() assertThat(rolloutManagement.create(
.create() entityFactory.rollout().create().name(rolloutName).description(rolloutName)
.name(rolloutName) .targetFilterQuery("controllerId==" + rolloutName + "-*").set(distributionSet),
.description(rolloutName) Arrays.asList(group5, group6, group7), conditions)).isNotNull();
.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 RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build();
final RolloutCreate rollout = generateTargetsAndRollout(rolloutName, targets); final RolloutCreate rollout = generateTargetsAndRollout(rolloutName, targets);
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy( assertThatExceptionOfType(AssignmentQuotaExceededException.class)
() -> rolloutManagement.create(rollout, maxGroups + 1, conditions)) .isThrownBy(() -> rolloutManagement.create(rollout, maxGroups + 1, conditions))
.withMessageContaining("not be greater than " + maxGroups); .withMessageContaining("not be greater than " + maxGroups);
} }
@@ -1625,8 +1608,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
.errorCondition(RolloutGroupErrorCondition.THRESHOLD, errorCondition) .errorCondition(RolloutGroupErrorCondition.THRESHOLD, errorCondition)
.errorAction(RolloutGroupErrorAction.PAUSE, null).build(); .errorAction(RolloutGroupErrorAction.PAUSE, null).build();
final RolloutCreate rolloutToCreate = entityFactory.rollout().create().name(rolloutName) final RolloutCreate rolloutToCreate = entityFactory.rollout().create().name(rolloutName)
.description("some description").targetFilterQuery("id==" + rolloutName + "-*") .description("some description").targetFilterQuery("id==" + rolloutName + "-*").set(distributionSet);
.set(distributionSet);
Rollout myRollout = rolloutManagement.create(rolloutToCreate, amountGroups, conditions); Rollout myRollout = rolloutManagement.create(rolloutToCreate, amountGroups, conditions);
myRollout = getRollout(myRollout.getId()); myRollout = getRollout(myRollout.getId());
@@ -1783,8 +1765,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
@Description("Creating a rollout without weight value when multi assignment in enabled.") @Description("Creating a rollout without weight value when multi assignment in enabled.")
void weightNotRequiredInMultiAssignmentMode() { void weightNotRequiredInMultiAssignmentMode() {
enableMultiAssignments(); enableMultiAssignments();
final Rollout rollout = createSimpleTestRolloutWithTargetsAndDistributionSet( final Rollout rollout = createSimpleTestRolloutWithTargetsAndDistributionSet(10, 10, 2, "50", "80",
10, 10, 2, "50", "80", ActionType.FORCED, null); ActionType.FORCED, null);
assertThat(rollout).isNotNull(); assertThat(rollout).isNotNull();
} }
@@ -1854,8 +1836,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
void createRolloutWithInvalidDistributionSet() { void createRolloutWithInvalidDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet(); final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
assertThatExceptionOfType(InvalidDistributionSetException.class).as( assertThatExceptionOfType(InvalidDistributionSetException.class)
"Invalid distributionSet should throw an exception") .as("Invalid distributionSet should throw an exception")
.isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithInvalidDistributionSet", .isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithInvalidDistributionSet",
"desc", 2, "name==*", distributionSet, "50", "80")); "desc", 2, "name==*", distributionSet, "50", "80"));
} }
@@ -1865,8 +1847,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
void createRolloutWithIncompleteDistributionSet() { void createRolloutWithIncompleteDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet(); final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
assertThatExceptionOfType(IncompleteDistributionSetException.class).as( assertThatExceptionOfType(IncompleteDistributionSetException.class)
"Incomplete distributionSet should throw an exception") .as("Incomplete distributionSet should throw an exception")
.isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithIncompleteDistributionSet", .isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithIncompleteDistributionSet",
"desc", 2, "name==*", distributionSet, "50", "80")); "desc", 2, "name==*", distributionSet, "50", "80"));
} }
@@ -1880,10 +1862,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
"desc", 2, "name==*", distributionSet, "50", "80"); "desc", 2, "name==*", distributionSet, "50", "80");
final DistributionSet invalidDistributionSet = testdataFactory.createAndInvalidateDistributionSet(); final DistributionSet invalidDistributionSet = testdataFactory.createAndInvalidateDistributionSet();
assertThatExceptionOfType(InvalidDistributionSetException.class).as( assertThatExceptionOfType(InvalidDistributionSetException.class)
"Invalid distributionSet should throw an exception") .as("Invalid distributionSet should throw an exception").isThrownBy(() -> rolloutManagement
.isThrownBy(() -> rolloutManagement.update( .update(entityFactory.rollout().update(rollout.getId()).set(invalidDistributionSet.getId())));
entityFactory.rollout().update(rollout.getId()).set(invalidDistributionSet.getId())));
} }
@Test @Test
@@ -1895,9 +1876,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
"desc", 2, "name==*", distributionSet, "50", "80"); "desc", 2, "name==*", distributionSet, "50", "80");
final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet(); final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet();
assertThatExceptionOfType(IncompleteDistributionSetException.class).as( assertThatExceptionOfType(IncompleteDistributionSetException.class)
"Incomplete distributionSet should throw an exception") .as("Incomplete distributionSet should throw an exception").isThrownBy(() -> rolloutManagement.update(
.isThrownBy(() -> rolloutManagement.update(
entityFactory.rollout().update(rollout.getId()).set(incompleteDistributionSet.getId()))); entityFactory.rollout().update(rollout.getId()).set(incompleteDistributionSet.getId())));
} }
@@ -1920,11 +1900,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
targets.addAll(targetsWithoutType); targets.addAll(targetsWithoutType);
final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build();
final RolloutCreate rolloutToCreate = entityFactory.rollout() final RolloutCreate rolloutToCreate = entityFactory.rollout().create().name(rolloutName)
.create() .targetFilterQuery("name==*").set(testDs);
.name(rolloutName)
.targetFilterQuery("name==*")
.set(testDs);
final Rollout createdRollout = rolloutManagement.create(rolloutToCreate, 1, conditions); final Rollout createdRollout = rolloutManagement.create(rolloutToCreate, 1, conditions);
@@ -1932,19 +1909,18 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
rolloutManagement.handleRollouts(); rolloutManagement.handleRollouts();
final Rollout testRollout = reloadRollout(createdRollout); final Rollout testRollout = reloadRollout(createdRollout);
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement.findByRollout(Pageable.unpaged(), final List<RolloutGroup> rolloutGroups = rolloutGroupManagement
testRollout.getId()).getContent(); .findByRollout(Pageable.unpaged(), testRollout.getId()).getContent();
assertThat(testRollout.getStatus()).isEqualTo(RolloutStatus.READY); assertThat(testRollout.getStatus()).isEqualTo(RolloutStatus.READY);
assertThat(testRollout.getTotalTargets()).isEqualTo(targets.size()); assertThat(testRollout.getTotalTargets()).isEqualTo(targets.size());
assertThat(rolloutGroups).hasSize(1); assertThat(rolloutGroups).hasSize(1);
assertThat(rolloutGroups.get(0).getTotalTargets()).isEqualTo(targets.size()); assertThat(rolloutGroups.get(0).getTotalTargets()).isEqualTo(targets.size());
final List<Target> rolloutGroupTargets = rolloutGroupManagement.findTargetsOfRolloutGroup(Pageable.unpaged(), final List<Target> rolloutGroupTargets = rolloutGroupManagement
rolloutGroups.get(0).getId()).getContent(); .findTargetsOfRolloutGroup(Pageable.unpaged(), rolloutGroups.get(0).getId()).getContent();
assertThat(rolloutGroupTargets).hasSize(targets.size()) assertThat(rolloutGroupTargets).hasSize(targets.size()).containsExactlyInAnyOrderElementsOf(targets)
.containsExactlyInAnyOrderElementsOf(targets)
.doesNotContainAnyElementsOf(incompatibleTargets); .doesNotContainAnyElementsOf(incompatibleTargets);
} }
@@ -2049,13 +2025,10 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
} }
private void awaitRunningState(final Long myRolloutId) { private void awaitRunningState(final Long myRolloutId) {
Awaitility.await() Awaitility.await().atMost(Duration.TEN_SECONDS).pollInterval(Duration.FIVE_HUNDRED_MILLISECONDS).with()
.atMost(Duration.TEN_SECONDS) .until(() -> WithSpringAuthorityRule
.pollInterval(Duration.FIVE_HUNDRED_MILLISECONDS) .runAsPrivileged(
.with()
.until(() -> WithSpringAuthorityRule.runAsPrivileged(
() -> rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new)) () -> rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new))
.getStatus() .getStatus().equals(RolloutStatus.RUNNING));
.equals(RolloutStatus.RUNNING));
} }
} }

View File

@@ -81,9 +81,8 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
final SoftwareModule module = testdataFactory.createSoftwareModuleApp(); final SoftwareModule module = testdataFactory.createSoftwareModuleApp();
verifyThrownExceptionBy( verifyThrownExceptionBy(
() -> softwareModuleManagement () -> softwareModuleManagement.create(Collections
.create(Collections .singletonList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))),
.singletonList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))),
"SoftwareModuleType"); "SoftwareModuleType");
verifyThrownExceptionBy( verifyThrownExceptionBy(
() -> softwareModuleManagement () -> 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()).hasSize(1);
assertThat(softwareModuleManagement.findByTextAndType(PAGE, "poky", osType.getId()).getContent().get(0)) assertThat(softwareModuleManagement.findByTextAndType(PAGE, "poky", osType.getId()).getContent().get(0))
.isEqualTo(os); .isEqualTo(os);
assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle%", runtimeType.getId()).getContent()) assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle", runtimeType.getId()).getContent())
.hasSize(1); .hasSize(1);
assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle%", runtimeType.getId()).getContent().get(0)) assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle", runtimeType.getId()).getContent().get(0))
.isEqualTo(jvm); .isEqualTo(jvm);
assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0.1", appType.getId()).getContent()).hasSize(1); assertThat(softwareModuleManagement.findByTextAndType(PAGE, ":1.0.1", appType.getId()).getContent()).hasSize(1)
assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0.1", appType.getId()).getContent().get(0)) .first().isEqualTo(ah);
.isEqualTo(ah); assertThat(softwareModuleManagement.findByTextAndType(PAGE, ":1.0", appType.getId()).getContent()).hasSize(2);
assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0%", appType.getId()).getContent()).hasSize(2);
// no we search with on entity marked as deleted // no we search with on entity marked as deleted
softwareModuleManagement.delete( softwareModuleManagement.delete(
softwareModuleRepository.findByAssignedToAndType(PAGE, ds, appType).getContent().get(0).getId()); 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()).hasSize(1);
assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0%", appType.getId()).getContent().get(0)) assertThat(softwareModuleManagement.findByTextAndType(PAGE, ":1.0", appType.getId()).getContent().get(0))
.isEqualTo(ah); .isEqualTo(ah);
} }
@@ -694,7 +692,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
// add some meta data entries // add some meta data entries
final SoftwareModule module3 = testdataFactory.createSoftwareModuleApp("m3"); 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) { for (int i = 0; i < firstHalf; ++i) {
softwareModuleManagement.createMetaData( softwareModuleManagement.createMetaData(
entityFactory.softwareModuleMetadata().create(module3.getId()).key("k" + i).value("v" + i)); entityFactory.softwareModuleMetadata().create(module3.getId()).key("k" + i).value("v" + i));

View File

@@ -46,6 +46,7 @@ import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import io.qameta.allure.Description; import io.qameta.allure.Description;
import io.qameta.allure.Feature; import io.qameta.allure.Feature;
@@ -417,26 +418,33 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest
final Page<TargetFilterQuery> tfqList = targetFilterQueryManagement final Page<TargetFilterQuery> tfqList = targetFilterQueryManagement
.findByAutoAssignDSAndRsql(PageRequest.of(0, 500), distributionSet.getId(), rsql); .findByAutoAssignDSAndRsql(PageRequest.of(0, 500), distributionSet.getId(), rsql);
assertThat(tfqList.getTotalElements()).isEqualTo(expectedFilterQueries.length);
verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries); verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries);
} }
private void verifyExpectedFilterQueriesInList(final Page<TargetFilterQuery> tfqList, private void verifyExpectedFilterQueriesInList(final Slice<TargetFilterQuery> tfqList,
final TargetFilterQuery... expectedFilterQueries) { final TargetFilterQuery... expectedFilterQueries) {
assertThat(expectedFilterQueries.length).as("Target filter query count")
.isEqualTo((int) tfqList.getTotalElements());
assertThat(tfqList.map(TargetFilterQuery::getId)).containsExactly( assertThat(tfqList.map(TargetFilterQuery::getId)).containsExactly(
Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new)); Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new));
} }
@Step @Step
private void verifyFindForAllWithAutoAssignDs(final TargetFilterQuery... expectedFilterQueries) { private void verifyFindForAllWithAutoAssignDs(final TargetFilterQuery... expectedFilterQueries) {
final Page<TargetFilterQuery> tfqList = targetFilterQueryManagement final Slice<TargetFilterQuery> tfqList = targetFilterQueryManagement
.findWithAutoAssignDS(PageRequest.of(0, 500)); .findWithAutoAssignDS(PageRequest.of(0, 500));
assertThat(tfqList.getNumberOfElements()).isEqualTo(expectedFilterQueries.length);
verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries); verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries);
} }
private void verifyExpectedFilterQueriesInList(final Page<TargetFilterQuery> 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 @Test
@Description("Creating or updating a target filter query with autoassignment and no-value weight when multi assignment in enabled.") @Description("Creating or updating a target filter query with autoassignment and no-value weight when multi assignment in enabled.")
public void weightNotRequiredInMultiAssignmentMode() { public void weightNotRequiredInMultiAssignmentMode() {

View File

@@ -15,13 +15,10 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.UpdateMode;
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
@@ -110,19 +107,6 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
final String installedC = targCs.iterator().next().getControllerId(); final String installedC = targCs.iterator().next().getControllerId();
final Long actionId = getFirstAssignedActionId(assignDistributionSet(installedSet.getId(), assignedC)); final Long actionId = getFirstAssignedActionId(assignDistributionSet(installedSet.getId(), assignedC));
// add attributes to match against only attribute value or attribute
// value and name
final Map<String, String> 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<String, String> idAttributes = new HashMap<>();
idAttributes.put("key", targAttributeId.getControllerId());
targAttributeId = controllerManagement.updateControllerAttributes(targAttributeId.getControllerId(),
idAttributes, UpdateMode.REPLACE);
// set one installed DS also // set one installed DS also
controllerManagement.addUpdateActionStatus( controllerManagement.addUpdateActionStatus(
entityFactory.actionStatus().create(actionId).status(Status.FINISHED).message("message")); 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 // try to find several targets with different filter settings
verifyThat1TargetHasNameAndId("targ-A-special", targSpecialName.getControllerId()); verifyThat1TargetHasNameAndId("targ-A-special", targSpecialName.getControllerId());
verifyThat1TargetHasAttributeValue("%c-attribute%", targAttribute.getControllerId());
verifyThat1TargetHasAttributeValue("%" + targAttributeId.getControllerId() + "%",
targAttributeId.getControllerId());
verifyThatRepositoryContains500Targets(); verifyThatRepositoryContains500Targets();
verifyThat200TargetsHaveTagD(targTagW, concat(targBs, targCs)); verifyThat200TargetsHaveTagD(targTagW, concat(targBs, targCs));
verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(targTagY, targTagW, targBs); verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(targTagY, targTagW, targBs);
@@ -183,8 +164,10 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(installedSet, pending, verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(installedSet, pending,
targetManagement.getByControllerID(installedC).get()); targetManagement.getByControllerID(installedC).get());
verifyThat1TargetHasTypeAndDSAssigned(targetTypeX, setB, targetManagement.getByControllerID(assignedE).get()); verifyThat1TargetHasTypeAndDSAssigned(targetTypeX, setB, targetManagement.getByControllerID(assignedE).get());
verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(setA, targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC))); verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(setA,
verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(installedSet, targetManagement.getByControllerID(Collections.singletonList(installedC))); targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC)));
verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(installedSet,
targetManagement.getByControllerID(Collections.singletonList(installedC)));
verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(targetTypeX, targEs); verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(targetTypeX, targEs);
verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(concat(targAs, targBs, targCs, targDs)); verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(concat(targAs, targBs, targCs, targDs));
@@ -481,14 +464,6 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParamsByControllerId))); .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 @Step
private void verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(final TargetTag targTagY, private void verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(final TargetTag targTagY,
final TargetTag targTagW, final List<Target> expected) { final TargetTag targTagW, final List<Target> expected) {
@@ -544,7 +519,8 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
} }
@Step @Step
private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set, final List<Target> expected) { private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set,
final List<Target> expected) {
final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.TRUE, null); final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.TRUE, null);
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(expected.size()).as("that number is also returned by count query") .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, private void verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(final TargetType targetType,
final List<Target> expected) { final List<Target> expected) {
final FilterParams filterParams = new FilterParams("%targ-E%", null, Boolean.FALSE, targetType.getId()); final FilterParams filterParams = new FilterParams("%targ-E%", null, Boolean.FALSE, targetType.getId());
List<Target> filteredTargets = targetManagement.findByFilters(PAGE, filterParams).getContent(); final List<Target> filteredTargets = targetManagement.findByFilters(PAGE, filterParams).getContent();
assertThat(filteredTargets).as("has number of elements").hasSize(100) assertThat(filteredTargets).as("has number of elements").hasSize(100)
.as("that number is also returned by count query") .as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams))); .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 // comparison of the objects is not possible
assertThat(filteredTargets.stream().map(Target::getControllerId).collect(Collectors.toList())) assertThat(filteredTargets.stream().map(Target::getControllerId).collect(Collectors.toList()))
.containsAll(expected.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 @Test
@Description("Verifies that targets with given target type are returned from repository.") @Description("Verifies that targets with given target type are returned from repository.")
public void findTargetByTargetType() { public void findTargetByTargetType() {
TargetType testType = testdataFactory.createTargetType("testType", Collections.singletonList(standardDsType)); final TargetType testType = testdataFactory.createTargetType("testType",
List<Target> unassigned = testdataFactory.createTargets(9, "unassigned"); Collections.singletonList(standardDsType));
List<Target> assigned = testdataFactory.createTargetsWithType(11, "assigned", testType); final List<Target> unassigned = testdataFactory.createTargets(9, "unassigned");
final List<Target> assigned = testdataFactory.createTargetsWithType(11, "assigned", testType);
assertThat(targetManagement.findByFilters(PAGE, assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, false, testType.getId())))
new FilterParams(null,null, false, testType.getId())))
.as("Contains the targets with set type").containsAll(assigned) .as("Contains the targets with set type").containsAll(assigned)
.as("and that means the following expected amount").hasSize(11); .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); .as("Count the targets with set type").isEqualTo(11);
assertThat(targetManagement.findByFilters(PAGE, assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, true, null)))
new FilterParams(null, null, true, null)))
.as("Contains the targets without a type").containsAll(unassigned) .as("Contains the targets without a type").containsAll(unassigned)
.as("and that means the following expected amount").hasSize(9); .as("and that means the following expected amount").hasSize(9);
assertThat(targetManagement.countByFilters(new FilterParams(null, null, true, null))) assertThat(targetManagement.countByFilters(new FilterParams(null, null, true, null)))

View File

@@ -69,6 +69,7 @@ import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@@ -160,10 +161,9 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
verifyThrownExceptionBy(() -> targetManagement.deleteMetaData(target.getControllerId(), NOT_EXIST_ID), verifyThrownExceptionBy(() -> targetManagement.deleteMetaData(target.getControllerId(), NOT_EXIST_ID),
"TargetMetadata"); "TargetMetadata");
verifyThrownExceptionBy(() -> targetManagement.getMetaDataByControllerId(NOT_EXIST_ID, "xxx"), "Target"); 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"); "Target");
verifyThrownExceptionBy(
() -> targetManagement.findMetaDataByControllerIdAndRsql(PAGE, NOT_EXIST_ID, "key==*"), "Target");
verifyThrownExceptionBy( verifyThrownExceptionBy(
() -> targetManagement.updateMetadata(NOT_EXIST_ID, entityFactory.generateTargetMetadata("xxx", "xxx")), () -> targetManagement.updateMetadata(NOT_EXIST_ID, entityFactory.generateTargetMetadata("xxx", "xxx")),
"Target"); "Target");
@@ -222,8 +222,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verify that a target with with invalid properties cannot be created or updated") @Description("Verify that a target with with invalid properties cannot be created or updated")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class) })
@Expect(type = TargetUpdatedEvent.class) })
void createAndUpdateTargetWithInvalidFields() { void createAndUpdateTargetWithInvalidFields() {
final Target target = testdataFactory.createTarget(); final Target target = testdataFactory.createTarget();
@@ -243,8 +242,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.description(RandomStringUtils.randomAlphanumeric(513)))); .description(RandomStringUtils.randomAlphanumeric(513))));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("target with invalid description should not be created") .as("target with invalid description should not be created").isThrownBy(() -> targetManagement
.isThrownBy(() -> targetManagement
.create(entityFactory.target().create().controllerId("a").description(INVALID_TEXT_HTML))); .create(entityFactory.target().create().controllerId("a").description(INVALID_TEXT_HTML)));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
@@ -253,9 +251,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.description(RandomStringUtils.randomAlphanumeric(513)))); .description(RandomStringUtils.randomAlphanumeric(513))));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("target with invalid description should not be updated") .as("target with invalid description should not be updated").isThrownBy(() -> targetManagement.update(
.isThrownBy(() -> targetManagement entityFactory.target().update(target.getControllerId()).description(INVALID_TEXT_HTML)));
.update(entityFactory.target().update(target.getControllerId()).description(INVALID_TEXT_HTML)));
} }
@Step @Step
@@ -267,8 +264,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("target with invalid name should not be created") .as("target with invalid name should not be created").isThrownBy(() -> targetManagement
.isThrownBy(() -> targetManagement
.create(entityFactory.target().create().controllerId("a").name(INVALID_TEXT_HTML))); .create(entityFactory.target().create().controllerId("a").name(INVALID_TEXT_HTML)));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
@@ -277,14 +273,12 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("target with invalid name should not be updated") .as("target with invalid name should not be updated").isThrownBy(() -> targetManagement
.isThrownBy(() -> targetManagement
.update(entityFactory.target().update(target.getControllerId()).name(INVALID_TEXT_HTML))); .update(entityFactory.target().update(target.getControllerId()).name(INVALID_TEXT_HTML)));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("target with too short name should not be updated") .as("target with too short name should not be updated").isThrownBy(() -> targetManagement
.isThrownBy( .update(entityFactory.target().update(target.getControllerId()).name("")));
() -> 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)))); .securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1))));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("target with invalid token should not be created") .as("target with invalid token should not be created").isThrownBy(() -> targetManagement
.isThrownBy(() -> targetManagement
.create(entityFactory.target().create().controllerId("a").securityToken(INVALID_TEXT_HTML))); .create(entityFactory.target().create().controllerId("a").securityToken(INVALID_TEXT_HTML)));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
@@ -307,13 +300,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1)))); .securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1))));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("target with invalid token should not be updated") .as("target with invalid token should not be updated").isThrownBy(() -> targetManagement.update(
.isThrownBy(() -> targetManagement.update(
entityFactory.target().update(target.getControllerId()).securityToken(INVALID_TEXT_HTML))); entityFactory.target().update(target.getControllerId()).securityToken(INVALID_TEXT_HTML)));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("target with too short token should not be updated") .as("target with too short token should not be updated").isThrownBy(() -> targetManagement
.isThrownBy(() -> targetManagement
.update(entityFactory.target().update(target.getControllerId()).securityToken(""))); .update(entityFactory.target().update(target.getControllerId()).securityToken("")));
} }
@@ -325,8 +316,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a")
.address(RandomStringUtils.randomAlphanumeric(513)))); .address(RandomStringUtils.randomAlphanumeric(513))));
assertThatExceptionOfType(InvalidTargetAddressException.class) assertThatExceptionOfType(InvalidTargetAddressException.class).as("target with invalid should not be created")
.as("target with invalid should not be created")
.isThrownBy(() -> targetManagement .isThrownBy(() -> targetManagement
.create(entityFactory.target().create().controllerId("a").address(INVALID_TEXT_HTML))); .create(entityFactory.target().create().controllerId("a").address(INVALID_TEXT_HTML)));
@@ -336,8 +326,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.address(RandomStringUtils.randomAlphanumeric(513)))); .address(RandomStringUtils.randomAlphanumeric(513))));
assertThatExceptionOfType(InvalidTargetAddressException.class) assertThatExceptionOfType(InvalidTargetAddressException.class)
.as("target with invalid address should not be updated") .as("target with invalid address should not be updated").isThrownBy(() -> targetManagement
.isThrownBy(() -> targetManagement
.update(entityFactory.target().update(target.getControllerId()).address(INVALID_TEXT_HTML))); .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)))); .controllerId(RandomStringUtils.randomAlphanumeric(Target.CONTROLLER_ID_MAX_SIZE + 1))));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class)
.as("target with invalid controller id should not be created") .as("target with invalid controller id should not be created").isThrownBy(
.isThrownBy(
() -> targetManagement.create(entityFactory.target().create().controllerId(INVALID_TEXT_HTML))); () -> targetManagement.create(entityFactory.target().create().controllerId(INVALID_TEXT_HTML)));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR)
.as(WHITESPACE_ERROR)
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" "))); .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" ")));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR)
.as(WHITESPACE_ERROR)
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a b"))); .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a b")));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR)
.as(WHITESPACE_ERROR)
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" "))); .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" ")));
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR)
.as(WHITESPACE_ERROR)
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("aaa bbb"))); .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("aaa bbb")));
} }
@@ -402,7 +386,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
assignedTargets.forEach(target -> assertThat( assignedTargets.forEach(target -> assertThat(
targetTagManagement.findByTarget(PAGE, target.getControllerId()).getNumberOfElements()).isEqualTo(1)); 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") assertThat(assignedTargets.size()).as("Assigned targets are wrong")
.isEqualTo(targetManagement.findByTag(PAGE, targetTag.getId()).getNumberOfElements()); .isEqualTo(targetManagement.findByTag(PAGE, targetTag.getId()).getNumberOfElements());
@@ -473,20 +457,15 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet testDs2 = testdataFactory.createDistributionSet("test2"); final DistributionSet testDs2 = testdataFactory.createDistributionSet("test2");
assertThat(targetManagement.countByAssignedDistributionSet(testDs1.getId())) assertThat(targetManagement.countByAssignedDistributionSet(testDs1.getId()))
.as("For newly created distributions sets the assigned target count should be zero") .as("For newly created distributions sets the assigned target count should be zero").isZero();
.isZero();
assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId())) assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId()))
.as("For newly created distributions sets the installed target count should be zero") .as("For newly created distributions sets the installed target count should be zero").isZero();
.isZero();
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId())) assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId()))
.as("Exists assigned or installed query should return false for new distribution sets") .as("Exists assigned or installed query should return false for new distribution sets").isFalse();
.isFalse();
assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId())) assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId()))
.as("For newly created distributions sets the assigned target count should be zero") .as("For newly created distributions sets the assigned target count should be zero").isZero();
.isZero();
assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId())) assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId()))
.as("For newly created distributions sets the installed target count should be zero") .as("For newly created distributions sets the installed target count should be zero").isZero();
.isZero();
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs2.getId())) assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs2.getId()))
.as("For newly created distributions sets the assigned target count should be zero").isFalse(); .as("For newly created distributions sets the assigned target count should be zero").isFalse();
@@ -508,8 +487,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.isZero(); .isZero();
assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId())).as("Target count is wrong") assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId())).as("Target count is wrong")
.isEqualTo(1); .isEqualTo(1);
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId())).as("Target count is wrong") assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId()))
.isTrue(); .as("Target count is wrong").isTrue();
assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId())).as("Target count is wrong") assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId())).as("Target count is wrong")
.isEqualTo(1); .isEqualTo(1);
assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId())).as("Target count is wrong") assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId())).as("Target count is wrong")
@@ -520,14 +499,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet assignedDs = deploymentManagement.getAssignedDistributionSet("4711") final DistributionSet assignedDs = deploymentManagement.getAssignedDistributionSet("4711")
.orElseThrow(NoSuchElementException::new); .orElseThrow(NoSuchElementException::new);
assertThat(assignedDs).as("Assigned ds size is wrong") assertThat(assignedDs).as("Assigned ds size is wrong").isEqualTo(testDs2);
.isEqualTo(testDs2);
final DistributionSet installedDs = deploymentManagement.getInstalledDistributionSet("4711") final DistributionSet installedDs = deploymentManagement.getInstalledDistributionSet("4711")
.orElseThrow(NoSuchElementException::new); .orElseThrow(NoSuchElementException::new);
assertThat(installedDs) assertThat(installedDs).as("Installed ds is wrong").isEqualTo(testDs1);
.as("Installed ds is wrong")
.isEqualTo(testDs1);
} }
@Test @Test
@@ -556,14 +532,14 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
} }
/** /**
* verifies, that all {@link TargetTag} of parameter. NOTE: it's accepted that * verifies, that all {@link TargetTag} of parameter. NOTE: it's accepted
* the target have additional tags assigned to them which are not contained * that the target have additional tags assigned to them which are not
* within parameter tags. * contained within parameter tags.
* *
* @param strict * @param strict
* if true, the given targets MUST contain EXACTLY ALL given tags, * if true, the given targets MUST contain EXACTLY ALL given
* AND NO OTHERS. If false, the given targets MUST contain ALL given * tags, AND NO OTHERS. If false, the given targets MUST contain
* tags, BUT MAY CONTAIN FURTHER ONE * ALL given tags, BUT MAY CONTAIN FURTHER ONE
* @param targets * @param targets
* targets to be verified * targets to be verified
* @param tags * @param tags
@@ -615,7 +591,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
assertThat(createdAt).as("CreatedAt compared with modifiedAt").isEqualTo(modifiedAt); 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( savedTarget = targetManagement.update(
entityFactory.target().update(savedTarget.getControllerId()).description("changed description")); entityFactory.target().update(savedTarget.getControllerId()).description("changed description"));
@@ -625,7 +601,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.isNotEqualTo(savedTarget.getLastModifiedAt()); .isNotEqualTo(savedTarget.getLastModifiedAt());
modifiedAt = 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(foundTarget).as("The target should not be null").isNotNull();
assertThat(myCtrlID).as("ControllerId compared with saved controllerId") assertThat(myCtrlID).as("ControllerId compared with saved controllerId")
.isEqualTo(foundTarget.getControllerId()); .isEqualTo(foundTarget.getControllerId());
@@ -718,13 +695,15 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final List<TargetTag> t2Tags = testdataFactory.createTargetTags(noT2Tags, "tag2"); final List<TargetTag> t2Tags = testdataFactory.createTargetTags(noT2Tags, "tag2");
t2Tags.forEach(tag -> targetManagement.assignTag(Collections.singletonList(t2.getControllerId()), tag.getId())); 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") assertThat(targetTagManagement.findByTarget(PAGE, t11.getControllerId()).getContent()).as("Tag size is wrong")
.hasSize(noT1Tags).containsAll(t1Tags); .hasSize(noT1Tags).containsAll(t1Tags);
assertThat(targetTagManagement.findByTarget(PAGE, t11.getControllerId()).getContent()).as("Tag size is wrong") assertThat(targetTagManagement.findByTarget(PAGE, t11.getControllerId()).getContent()).as("Tag size is wrong")
.hasSize(noT1Tags).doesNotContain(Iterables.toArray(t2Tags, TargetTag.class)); .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") assertThat(targetTagManagement.findByTarget(PAGE, t21.getControllerId()).getContent()).as("Tag size is wrong")
.hasSize(noT2Tags).containsAll(t2Tags); .hasSize(noT2Tags).containsAll(t2Tags);
assertThat(targetTagManagement.findByTarget(PAGE, t21.getControllerId()).getContent()).as("Tag size is wrong") 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"); testdataFactory.createTargets(25, "target-id-B", "first description");
final Page<Target> foundTargets = targetManagement.findByRsql(PAGE, rsqlFilter); final Slice<Target> foundTargets = targetManagement.findByRsql(PAGE, rsqlFilter);
final long foundTargetsCount = targetManagement.countByRsql(rsqlFilter);
assertThat(targetManagement.count()).as("Total targets").isEqualTo(50L); 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 @Test
@@ -1033,11 +1014,12 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
// create target meta data entry // create target meta data entry
insertTargetMetadata(knownKey, knownValue, target); 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); assertThat(changedLockRevisionTarget.getOptLockRevision()).isEqualTo(2);
// Unsure if needed maybe to wait for a db flush? // Unsure if needed maybe to wait for a db flush?
// Thread.sleep(100); // Thread.sleep(100);
// update the target metadata // update the target metadata
final JpaTargetMetadata updated = (JpaTargetMetadata) targetManagement.updateMetadata(target.getControllerId(), final JpaTargetMetadata updated = (JpaTargetMetadata) targetManagement.updateMetadata(target.getControllerId(),
@@ -1150,7 +1132,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
checkTargetsHaveType(typeATargets, typeA); checkTargetsHaveType(typeATargets, typeA);
checkTargetsHaveType(typeBTargets, typeB); 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()); targetManagement.deleteByControllerID(typeATargets.get(0).getControllerId());
final TargetTypeAssignmentResult resultC = initiateTypeAssignment(typeATargets, typeB); final TargetTypeAssignmentResult resultC = initiateTypeAssignment(typeATargets, typeB);
assertThat(resultC.getAssigned()).isEqualTo(9); assertThat(resultC.getAssigned()).isEqualTo(9);
@@ -1159,7 +1142,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
} }
private void checkTargetsHaveType(final List<Target> targets, final TargetType type) { private void checkTargetsHaveType(final List<Target> targets, final TargetType type) {
List<JpaTarget> foundTargets = targetRepository final List<JpaTarget> foundTargets = targetRepository
.findAllById(targets.stream().map(Identifiable::getId).collect(Collectors.toList())); .findAllById(targets.stream().map(Identifiable::getId).collect(Collectors.toList()));
for (final Target target : foundTargets) { for (final Target target : foundTargets) {
if (!type.getName().equals(type.getName())) { if (!type.getName().equals(type.getName())) {
@@ -1205,14 +1188,13 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
// create a target // create a target
final Target target = testdataFactory.createTarget("target1", "testtarget"); final Target target = testdataFactory.createTarget("target1", "testtarget");
// initial opt lock revision must be one // initial opt lock revision must be one
Optional<JpaTarget> targetFound = targetRepository.findById(target.getId()); final Optional<JpaTarget> targetFound = targetRepository.findById(target.getId());
assertThat(targetFound).isPresent(); assertThat(targetFound).isPresent();
assertThat(targetFound.get().getOptLockRevision()).isEqualTo(1); assertThat(targetFound.get().getOptLockRevision()).isEqualTo(1);
assertThat(targetFound.get().getTargetType()).isNull(); assertThat(targetFound.get().getTargetType()).isNull();
// assign target type to target // assign target type to target
assertThatExceptionOfType(ConstraintViolationException.class) assertThatExceptionOfType(ConstraintViolationException.class).as("target type with id=null cannot be assigned")
.as("target type with id=null cannot be assigned")
.isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), null)); .isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), null));
assertThatExceptionOfType(EntityNotFoundException.class) assertThatExceptionOfType(EntityNotFoundException.class)
@@ -1220,7 +1202,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), 114L)); .isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), 114L));
// opt lock revision is not changed // opt lock revision is not changed
Optional<JpaTarget> targetFound1 = targetRepository.findById(target.getId()); final Optional<JpaTarget> targetFound1 = targetRepository.findById(target.getId());
assertThat(targetFound1).isPresent(); assertThat(targetFound1).isPresent();
assertThat(targetFound1.get().getOptLockRevision()).isEqualTo(1); assertThat(targetFound1.get().getOptLockRevision()).isEqualTo(1);
} }
@@ -1230,12 +1212,12 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@Description("Checks that target type can be unassigned from target.") @Description("Checks that target type can be unassigned from target.")
void unAssignTargetTypeFromTarget() { void unAssignTargetTypeFromTarget() {
// create a target type // create a target type
TargetType targetType = testdataFactory.findOrCreateTargetType("targettype"); final TargetType targetType = testdataFactory.findOrCreateTargetType("targettype");
assertThat(targetType).isNotNull(); assertThat(targetType).isNotNull();
// create a target // create a target
final Target target = testdataFactory.createTarget("target1", "testtarget", targetType.getId()); final Target target = testdataFactory.createTarget("target1", "testtarget", targetType.getId());
// initial opt lock revision must be one // initial opt lock revision must be one
Optional<JpaTarget> targetFound = targetRepository.findById(target.getId()); final Optional<JpaTarget> targetFound = targetRepository.findById(target.getId());
assertThat(targetFound).isPresent(); assertThat(targetFound).isPresent();
assertThat(targetFound.get().getOptLockRevision()).isEqualTo(1); assertThat(targetFound.get().getOptLockRevision()).isEqualTo(1);
assertThat(targetFound.get().getTargetType().getName()).isEqualTo(targetType.getName()); assertThat(targetFound.get().getTargetType().getName()).isEqualTo(targetType.getName());
@@ -1244,7 +1226,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
targetManagement.unAssignType(targetFound.get().getControllerId()); targetManagement.unAssignType(targetFound.get().getControllerId());
// opt lock revision must be changed // opt lock revision must be changed
Optional<JpaTarget> targetFound1 = targetRepository.findById(target.getId()); final Optional<JpaTarget> targetFound1 = targetRepository.findById(target.getId());
assertThat(targetFound1).isPresent(); assertThat(targetFound1).isPresent();
assertThat(targetFound1.get().getOptLockRevision()).isEqualTo(2); assertThat(targetFound1.get().getOptLockRevision()).isEqualTo(2);
assertThat(targetFound1.get().getTargetType()).isNull(); assertThat(targetFound1.get().getTargetType()).isNull();
@@ -1275,9 +1257,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
} }
private void validateFoundTargetsByRsql(final String rsqlFilter, final String... controllerIds) { private void validateFoundTargetsByRsql(final String rsqlFilter, final String... controllerIds) {
final Page<Target> foundTargetsByMetadataAndControllerId = targetManagement.findByRsql(PAGE, rsqlFilter); final Slice<Target> 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); .isEqualTo(controllerIds.length);
assertThat(foundTargetsByMetadataAndControllerId.getContent().stream().map(Target::getControllerId)) assertThat(foundTargetsByMetadataAndControllerId.getContent().stream().map(Target::getControllerId))
.as("Targets found by RSQL filter have wrong controller ids").containsExactlyInAnyOrder(controllerIds); .as("Targets found by RSQL filter have wrong controller ids").containsExactlyInAnyOrder(controllerIds);

View File

@@ -28,7 +28,7 @@ import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; 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.Description;
import io.qameta.allure.Feature; import io.qameta.allure.Feature;
@@ -88,8 +88,10 @@ class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
assignDistributionSet(ds.getId(), target.getControllerId()); assignDistributionSet(ds.getId(), target.getControllerId());
targetType1 = targetTypeManagement.create(entityFactory.targetType().create().name("Type1").description("Desc. Type1")); targetType1 = targetTypeManagement
targetType2 = targetTypeManagement.create(entityFactory.targetType().create().name("Type2").description("Desc. Type2")); .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(target.getControllerId(), targetType1.getId());
targetManagement.assignType(target2.getControllerId(), targetType2.getId()); targetManagement.assignType(target2.getControllerId(), targetType2.getId());
@@ -317,10 +319,10 @@ class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
} }
private void assertRSQLQuery(final String rsqlParam, final long expectedTargets) { private void assertRSQLQuery(final String rsqlParam, final long expectedTargets) {
final Page<Target> findTargetPage = targetManagement.findByRsql(PAGE, rsqlParam); final Slice<Target> findTargetPage = targetManagement.findByRsql(PAGE, rsqlParam);
final long countTargetsAll = findTargetPage.getTotalElements(); final long countTargetsAll = targetManagement.countByRsql(rsqlParam);
assertThat(findTargetPage).isNotNull(); assertThat(findTargetPage).isNotNull();
assertThat(countTargetsAll).isEqualTo(expectedTargets); assertThat(findTargetPage.getNumberOfElements()).isEqualTo(countTargetsAll).isEqualTo(expectedTargets);
} }
private void assertRSQLQueryThrowsException(final String rsqlParam) { private void assertRSQLQueryThrowsException(final String rsqlParam) {

View File

@@ -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.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithUser; import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import io.qameta.allure.Description; import io.qameta.allure.Description;
@@ -155,11 +154,11 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
createDistributionSetForTenant(anotherTenant); createDistributionSetForTenant(anotherTenant);
// ensure both tenants see their distribution sets // ensure both tenants see their distribution sets
final Page<DistributionSet> findDistributionSetsForTenant = findDistributionSetForTenant(tenant); final Slice<DistributionSet> findDistributionSetsForTenant = findDistributionSetForTenant(tenant);
assertThat(findDistributionSetsForTenant).hasSize(1); assertThat(findDistributionSetsForTenant).hasSize(1);
assertThat(findDistributionSetsForTenant.getContent().get(0).getTenant().toUpperCase()) assertThat(findDistributionSetsForTenant.getContent().get(0).getTenant().toUpperCase())
.isEqualTo(tenant.toUpperCase()); .isEqualTo(tenant.toUpperCase());
final Page<DistributionSet> findDistributionSetsForAnotherTenant = findDistributionSetForTenant(anotherTenant); final Slice<DistributionSet> findDistributionSetsForAnotherTenant = findDistributionSetForTenant(anotherTenant);
assertThat(findDistributionSetsForAnotherTenant).hasSize(1); assertThat(findDistributionSetsForAnotherTenant).hasSize(1);
assertThat(findDistributionSetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase()) assertThat(findDistributionSetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase())
.isEqualTo(anotherTenant.toUpperCase()); .isEqualTo(anotherTenant.toUpperCase());
@@ -188,7 +187,7 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
return runAsTenant(tenant, () -> testdataFactory.createDistributionSet()); return runAsTenant(tenant, () -> testdataFactory.createDistributionSet());
} }
private Page<DistributionSet> findDistributionSetForTenant(final String tenant) throws Exception { private Slice<DistributionSet> findDistributionSetForTenant(final String tenant) throws Exception {
return runAsTenant(tenant, () -> distributionSetManagement.findByCompleted(PAGE, true)); return runAsTenant(tenant, () -> distributionSetManagement.findByCompleted(PAGE, true));
} }
} }

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.mgmt.rest.resource;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.validation.ValidationException; import javax.validation.ValidationException;
import org.eclipse.hawkbit.mgmt.json.model.PagedList; 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 Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
final Page<Rollout> findModulesAll; final Page<Rollout> findRolloutsAll;
if (rsqlParam != null) { if (rsqlParam != null) {
findModulesAll = this.rolloutManagement.findByRsql(pageable, rsqlParam, false); findRolloutsAll = this.rolloutManagement.findByRsql(pageable, rsqlParam, false);
} else { } else {
findModulesAll = this.rolloutManagement.findAll(pageable, false); findRolloutsAll = this.rolloutManagement.findAll(pageable, false);
} }
final List<MgmtRolloutResponseBody> rest = MgmtRolloutMapper.toResponseRollout(findModulesAll.getContent()); final List<MgmtRolloutResponseBody> rest = MgmtRolloutMapper.toResponseRollout(findRolloutsAll.getContent());
return ResponseEntity.ok(new PagedList<>(rest, findModulesAll.getTotalElements())); return ResponseEntity.ok(new PagedList<>(rest, findRolloutsAll.getTotalElements()));
} }
@Override @Override
@@ -114,16 +115,15 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
throw new RSQLParameterSyntaxException("Cannot create a Rollout with an empty target query filter!"); throw new RSQLParameterSyntaxException("Cannot create a Rollout with an empty target query filter!");
} }
targetFilterQueryManagement.verifyTargetFilterQuerySyntax(targetFilterQuery); targetFilterQueryManagement.verifyTargetFilterQuerySyntax(targetFilterQuery);
final DistributionSet distributionSet = distributionSetManagement.getValidAndComplete( final DistributionSet distributionSet = distributionSetManagement
rolloutRequestBody.getDistributionSetId()); .getValidAndComplete(rolloutRequestBody.getDistributionSetId());
final RolloutGroupConditions rolloutGroupConditions = MgmtRolloutMapper.fromRequest(rolloutRequestBody, true); final RolloutGroupConditions rolloutGroupConditions = MgmtRolloutMapper.fromRequest(rolloutRequestBody, true);
final RolloutCreate create = MgmtRolloutMapper.fromRequest(entityFactory, rolloutRequestBody, distributionSet); final RolloutCreate create = MgmtRolloutMapper.fromRequest(entityFactory, rolloutRequestBody, distributionSet);
Rollout rollout; Rollout rollout;
if (rolloutRequestBody.getGroups() != null) { if (rolloutRequestBody.getGroups() != null) {
final List<RolloutGroupCreate> rolloutGroups = rolloutRequestBody.getGroups() final List<RolloutGroupCreate> rolloutGroups = rolloutRequestBody.getGroups().stream()
.stream()
.map(mgmtRolloutGroup -> MgmtRolloutMapper.fromRequest(entityFactory, mgmtRolloutGroup)) .map(mgmtRolloutGroup -> MgmtRolloutMapper.fromRequest(entityFactory, mgmtRolloutGroup))
.collect(Collectors.toList()); .collect(Collectors.toList());
rollout = rolloutManagement.create(create, rolloutGroups, rolloutGroupConditions); rollout = rolloutManagement.create(create, rolloutGroups, rolloutGroupConditions);

View File

@@ -106,12 +106,11 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
final Slice<Target> findTargetsAll; final Slice<Target> findTargetsAll;
final long countTargetsAll; final long countTargetsAll;
if (rsqlParam != null) { if (rsqlParam != null) {
final Page<Target> findTargetPage = this.targetManagement.findByRsql(pageable, rsqlParam); findTargetsAll = targetManagement.findByRsql(pageable, rsqlParam);
countTargetsAll = findTargetPage.getTotalElements(); countTargetsAll = targetManagement.countByRsql(rsqlParam);
findTargetsAll = findTargetPage;
} else { } else {
findTargetsAll = this.targetManagement.findAll(pageable); findTargetsAll = targetManagement.findAll(pageable);
countTargetsAll = this.targetManagement.count(); countTargetsAll = targetManagement.count();
} }
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent()); final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent());
@@ -165,7 +164,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
} }
@Override @Override
public ResponseEntity<Void> assignTargetType(@PathVariable("targetId") final String targetId, @RequestBody final MgmtId targetTypeId) { public ResponseEntity<Void> assignTargetType(@PathVariable("targetId") final String targetId,
@RequestBody final MgmtId targetTypeId) {
this.targetManagement.assignType(targetId, targetTypeId.getId()); this.targetManagement.assignType(targetId, targetTypeId.getId());
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
@@ -304,8 +304,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
final List<Entry<String, Long>> offlineAssignments = dsAssignments.stream() final List<Entry<String, Long>> offlineAssignments = dsAssignments.stream()
.map(dsAssignment -> new SimpleEntry<String, Long>(targetId, dsAssignment.getId())) .map(dsAssignment -> new SimpleEntry<String, Long>(targetId, dsAssignment.getId()))
.collect(Collectors.toList()); .collect(Collectors.toList());
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse( return ResponseEntity.ok(MgmtDistributionSetMapper
deploymentManagement.offlineAssignedDistributionSets(offlineAssignments))); .toResponse(deploymentManagement.offlineAssignedDistributionSets(offlineAssignments)));
} }
findTargetWithExceptionIfNotFound(targetId); findTargetWithExceptionIfNotFound(targetId);

View File

@@ -150,18 +150,15 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
final Sort sorting = PagingUtility.sanitizeTargetSortParam(sortParam); final Sort sorting = PagingUtility.sanitizeTargetSortParam(sortParam);
final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting); final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
Page<Target> findTargetsAll; final Page<Target> findTargetsAll;
if (rsqlParam == null) { if (rsqlParam == null) {
findTargetsAll = targetManagement.findByTag(pageable, targetTagId); findTargetsAll = targetManagement.findByTag(pageable, targetTagId);
} else { } else {
findTargetsAll = targetManagement.findByRsqlAndTag(pageable, rsqlParam, targetTagId); findTargetsAll = targetManagement.findByRsqlAndTag(pageable, rsqlParam, targetTagId);
} }
final Long countTargetsAll = findTargetsAll.getTotalElements();
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent()); final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent());
return ResponseEntity.ok(new PagedList<>(rest, countTargetsAll)); return ResponseEntity.ok(new PagedList<>(rest, findTargetsAll.getTotalElements()));
} }
@Override @Override

View File

@@ -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.json.model.targettype.MgmtTargetTypeRequestBodyPut;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTypeRestApi; 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.EntityFactory;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement;
@@ -48,7 +47,7 @@ public class MgmtTargetTypeResource implements MgmtTargetTypeRestApi {
private final TargetTypeManagement targetTypeManagement; private final TargetTypeManagement targetTypeManagement;
private final EntityFactory entityFactory; private final EntityFactory entityFactory;
public MgmtTargetTypeResource(TargetTypeManagement targetTypeManagement, final EntityFactory entityFactory) { public MgmtTargetTypeResource(final TargetTypeManagement targetTypeManagement, final EntityFactory entityFactory) {
this.targetTypeManagement = targetTypeManagement; this.targetTypeManagement = targetTypeManagement;
this.entityFactory = entityFactory; this.entityFactory = entityFactory;
} }
@@ -65,14 +64,15 @@ public class MgmtTargetTypeResource implements MgmtTargetTypeRestApi {
final Sort sorting = PagingUtility.sanitizeTargetTypeSortParam(sortParam); final Sort sorting = PagingUtility.sanitizeTargetTypeSortParam(sortParam);
final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting); final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
final Page<TargetType> findTargetTypesAll; final Slice<TargetType> findTargetTypesAll;
long countTargetTypesAll; long countTargetTypesAll;
if (rsqlParam != null) { if (rsqlParam != null) {
findTargetTypesAll= targetTypeManagement.findByRsql(pageable, rsqlParam); findTargetTypesAll = targetTypeManagement.findByRsql(pageable, rsqlParam);
countTargetTypesAll = ((Page<TargetType>) findTargetTypesAll).getTotalElements();
} else { } else {
findTargetTypesAll = targetTypeManagement.findAll(pageable); findTargetTypesAll = targetTypeManagement.findAll(pageable);
countTargetTypesAll = targetTypeManagement.count();
} }
countTargetTypesAll = findTargetTypesAll.getTotalElements();
final List<MgmtTargetType> rest = MgmtTargetTypeMapper.toListResponse(findTargetTypesAll.getContent()); final List<MgmtTargetType> rest = MgmtTargetTypeMapper.toListResponse(findTargetTypesAll.getContent());
return ResponseEntity.ok(new PagedList<>(rest, countTargetTypesAll)); return ResponseEntity.ok(new PagedList<>(rest, countTargetTypesAll));
@@ -135,8 +135,8 @@ public class MgmtTargetTypeResource implements MgmtTargetTypeRestApi {
public ResponseEntity<Void> addCompatibleDistributionSets(@PathVariable("targetTypeId") final Long targetTypeId, public ResponseEntity<Void> addCompatibleDistributionSets(@PathVariable("targetTypeId") final Long targetTypeId,
@RequestBody final List<MgmtDistributionSetTypeAssignment> distributionSetTypeIds) { @RequestBody final List<MgmtDistributionSetTypeAssignment> distributionSetTypeIds) {
targetTypeManagement.assignCompatibleDistributionSetTypes(targetTypeId, targetTypeManagement.assignCompatibleDistributionSetTypes(targetTypeId, distributionSetTypeIds.stream()
distributionSetTypeIds.stream().map(MgmtDistributionSetTypeAssignment::getId).collect(Collectors.toList())); .map(MgmtDistributionSetTypeAssignment::getId).collect(Collectors.toList()));
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }

View File

@@ -12,7 +12,6 @@ import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
import org.eclipse.hawkbit.ui.common.data.providers.DistributionSetManagementStateDataProvider; import org.eclipse.hawkbit.ui.common.data.providers.DistributionSetManagementStateDataProvider;
import org.springframework.util.StringUtils;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
@@ -65,7 +64,7 @@ public class DsFilterParams implements Serializable {
* String * String
*/ */
public void setSearchText(final String searchText) { public void setSearchText(final String searchText) {
this.searchText = !StringUtils.isEmpty(searchText) ? String.format("%%%s%%", searchText) : null; this.searchText = searchText;
} }
@Override @Override

View File

@@ -12,7 +12,6 @@ import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
import org.eclipse.hawkbit.ui.common.data.providers.SoftwareModuleDataProvider; import org.eclipse.hawkbit.ui.common.data.providers.SoftwareModuleDataProvider;
import org.springframework.util.StringUtils;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
@@ -78,7 +77,7 @@ public class SwFilterParams implements Serializable {
* String * String
*/ */
public void setSearchText(final String searchText) { public void setSearchText(final String searchText) {
this.searchText = !StringUtils.isEmpty(searchText) ? String.format("%%%s%%", searchText) : null; this.searchText = searchText;
} }
/** /**

View File

@@ -17,8 +17,8 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyAdvancedRolloutGroup; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyAdvancedRolloutGroup;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetFilterQueryInfo; 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.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@@ -55,9 +55,9 @@ public class RolloutGroupToAdvancedDefinitionMapper {
final String groupTargetFilterQuery = rolloutGroup.getTargetFilterQuery(); final String groupTargetFilterQuery = rolloutGroup.getTargetFilterQuery();
if (!StringUtils.isEmpty(groupTargetFilterQuery)) { if (!StringUtils.isEmpty(groupTargetFilterQuery)) {
advancedGroupRow.setTargetFilterQuery(groupTargetFilterQuery); advancedGroupRow.setTargetFilterQuery(groupTargetFilterQuery);
final Page<TargetFilterQuery> filterQueries = targetFilterQueryManagement.findByQuery(PageRequest.of(0, 1), final Slice<TargetFilterQuery> filterQueries = targetFilterQueryManagement.findByQuery(PageRequest.of(0, 1),
groupTargetFilterQuery); groupTargetFilterQuery);
if (filterQueries.getTotalElements() == 1) { if (filterQueries.getNumberOfElements() == 1) {
final TargetFilterQuery tfq = filterQueries.getContent().get(0); final TargetFilterQuery tfq = filterQueries.getContent().get(0);
advancedGroupRow.setTargetFilterQueryInfo( advancedGroupRow.setTargetFilterQueryInfo(
new ProxyTargetFilterQueryInfo(tfq.getId(), tfq.getName(), tfq.getQuery())); new ProxyTargetFilterQueryInfo(tfq.getId(), tfq.getName(), tfq.getQuery()));

View File

@@ -26,8 +26,7 @@ public class RolloutToProxyRolloutMapper extends AbstractNamedEntityToProxyNamed
mapNamedEntityAttributes(rollout, proxyRollout); mapNamedEntityAttributes(rollout, proxyRollout);
final DistributionSet ds = rollout.getDistributionSet(); final DistributionSet ds = rollout.getDistributionSet();
proxyRollout.setDsInfo(new ProxyDistributionSetInfo(ds.getId(), ds.getName(), ds.getVersion(), proxyRollout.setDsInfo(new ProxyDistributionSetInfo(ds.getId(), ds.getName(), ds.getVersion(), ds.isValid()));
ds.getType().getId(), ds.isValid()));
proxyRollout proxyRollout
.setNumberOfGroups(rollout.getRolloutGroupsCreated() > 0 ? rollout.getRolloutGroupsCreated() : null); .setNumberOfGroups(rollout.getRolloutGroupsCreated() > 0 ? rollout.getRolloutGroupsCreated() : null);
proxyRollout.setForcedTime(rollout.getForcedTime() > 0 ? rollout.getForcedTime() : null); proxyRollout.setForcedTime(rollout.getForcedTime() > 0 ? rollout.getForcedTime() : null);

View File

@@ -38,8 +38,7 @@ public class TargetFilterQueryToProxyTargetFilterMapper
if (distributionSet != null) { if (distributionSet != null) {
proxyTargetFilter.setAutoAssignmentEnabled(true); proxyTargetFilter.setAutoAssignmentEnabled(true);
proxyTargetFilter.setDistributionSetInfo(new ProxyDistributionSetInfo(distributionSet.getId(), proxyTargetFilter.setDistributionSetInfo(new ProxyDistributionSetInfo(distributionSet.getId(),
distributionSet.getName(), distributionSet.getVersion(), distributionSet.getType().getId(), distributionSet.getName(), distributionSet.getVersion(), distributionSet.isValid()));
distributionSet.isValid()));
proxyTargetFilter.setAutoAssignActionType(targetFilterQuery.getAutoAssignActionType()); proxyTargetFilter.setAutoAssignActionType(targetFilterQuery.getAutoAssignActionType());
} }

View File

@@ -61,6 +61,6 @@ public class ActionStatusDataProvider extends AbstractProxyDataProvider<ProxyAct
return 0L; return 0L;
} }
return loadBackendEntities(PageRequest.of(0, 1), actionId).getTotalElements(); return deploymentManagement.countActionStatusByAction(actionId);
} }
} }

View File

@@ -105,6 +105,6 @@ public class ActionStatusMsgDataProvider extends AbstractGenericDataProvider<Pro
return 0L; return 0L;
} }
return loadBackendEntities(PageRequest.of(0, 1), actionStatusId).getTotalElements(); return deploymentManagement.countMessagesByActionStatusId(actionStatusId);
} }
} }

View File

@@ -59,6 +59,6 @@ public class ArtifactDataProvider extends AbstractProxyDataProvider<ProxyArtifac
return 0L; return 0L;
} }
return loadBackendEntities(PageRequest.of(0, 1), smId).getTotalElements(); return artifactManagement.countBySoftwareModule(smId);
} }
} }

View File

@@ -9,15 +9,14 @@
package org.eclipse.hawkbit.ui.common.data.providers; package org.eclipse.hawkbit.ui.common.data.providers;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.DistributionSetFilter.DistributionSetFilterBuilder;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.ui.common.data.filters.DsDistributionsFilterParams; import org.eclipse.hawkbit.ui.common.data.filters.DsDistributionsFilterParams;
import org.eclipse.hawkbit.ui.common.data.mappers.DistributionSetToProxyDistributionMapper; import org.eclipse.hawkbit.ui.common.data.mappers.DistributionSetToProxyDistributionMapper;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSet; 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.PageRequest;
import org.springframework.data.domain.Slice;
/** /**
* Data provider for {@link DistributionSet}, which dynamically loads a batch of * Data provider for {@link DistributionSet}, which dynamically loads a batch of
@@ -30,44 +29,40 @@ public class DistributionSetDistributionsStateDataProvider
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final transient DistributionSetManagement distributionSetManagement; private final transient DistributionSetManagement distributionSetManagement;
private final transient DistributionSetTypeManagement distributionSetTypeManagement;
/** /**
* Constructor for DistributionSetDistributionsStateDataProvider * Constructor for DistributionSetDistributionsStateDataProvider
* *
* @param distributionSetManagement * @param distributionSetManagement
* DistributionSetManagement * DistributionSetManagement
* @param distributionSetTypeManagement
* DistributionSetTypeManagement
* @param entityMapper * @param entityMapper
* DistributionSetToProxyDistributionMapper * DistributionSetToProxyDistributionMapper
*/ */
public DistributionSetDistributionsStateDataProvider(final DistributionSetManagement distributionSetManagement, public DistributionSetDistributionsStateDataProvider(final DistributionSetManagement distributionSetManagement,
final DistributionSetTypeManagement distributionSetTypeManagement,
final DistributionSetToProxyDistributionMapper entityMapper) { final DistributionSetToProxyDistributionMapper entityMapper) {
super(entityMapper); super(entityMapper);
this.distributionSetManagement = distributionSetManagement; this.distributionSetManagement = distributionSetManagement;
this.distributionSetTypeManagement = distributionSetTypeManagement;
} }
@Override @Override
protected Page<DistributionSet> loadBackendEntities(final PageRequest pageRequest, protected Slice<DistributionSet> loadBackendEntities(final PageRequest pageRequest,
final DsDistributionsFilterParams filter) { final DsDistributionsFilterParams filter) {
return distributionSetManagement.findByDistributionSetFilter(pageRequest, buildDsFilter(filter));
}
private DistributionSetFilter buildDsFilter(final DsDistributionsFilterParams filter) {
final DistributionSetFilterBuilder builder = new DistributionSetFilterBuilder().setIsDeleted(false); final DistributionSetFilterBuilder builder = new DistributionSetFilterBuilder().setIsDeleted(false);
if (filter != null) { if (filter != null) {
final DistributionSetType type = filter.getDsTypeId() == null ? null builder.setSearchText(filter.getSearchText()).setSelectDSWithNoTag(false).setTypeId(filter.getDsTypeId());
: distributionSetTypeManagement.get(filter.getDsTypeId()).orElse(null);
builder.setSearchText(filter.getSearchText()).setSelectDSWithNoTag(false).setType(type);
} }
return distributionSetManagement.findByDistributionSetFilter(pageRequest, builder.build()); return builder.build();
} }
@Override @Override
protected long sizeInBackEnd(final PageRequest pageRequest, final DsDistributionsFilterParams filter) { protected long sizeInBackEnd(final PageRequest pageRequest, final DsDistributionsFilterParams filter) {
return loadBackendEntities(PageRequest.of(0, 1), filter).getTotalElements(); return distributionSetManagement.countByDistributionSetFilter(buildDsFilter(filter));
} }
} }

View File

@@ -10,12 +10,13 @@ package org.eclipse.hawkbit.ui.common.data.providers;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.DistributionSetFilter.DistributionSetFilterBuilder;
import org.eclipse.hawkbit.ui.common.data.filters.DsManagementFilterParams; 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.mappers.DistributionSetToProxyDistributionMapper;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSet; 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.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@@ -46,28 +47,34 @@ public class DistributionSetManagementStateDataProvider
} }
@Override @Override
protected Page<DistributionSet> loadBackendEntities(final PageRequest pageRequest, protected Slice<DistributionSet> loadBackendEntities(final PageRequest pageRequest,
final DsManagementFilterParams filter) { final DsManagementFilterParams filter) {
if (filter == null) { if (filter == null) {
return distributionSetManagement.findByCompleted(pageRequest, true); return distributionSetManagement.findByCompleted(pageRequest, true);
} }
final String pinnedControllerId = filter.getPinnedTargetControllerId(); 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)) { if (!StringUtils.isEmpty(pinnedControllerId)) {
return distributionSetManagement.findByFilterAndAssignedInstalledDsOrderedByLinkTarget(pageRequest, builder, return distributionSetManagement.findByDistributionSetFilterOrderByLinkedTarget(pageRequest,
pinnedControllerId); 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 @Override
protected long sizeInBackEnd(final PageRequest pageRequest, final DsManagementFilterParams filter) { 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));
} }
} }

View File

@@ -10,11 +10,12 @@ package org.eclipse.hawkbit.ui.common.data.providers;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.DistributionSetFilter.DistributionSetFilterBuilder;
import org.eclipse.hawkbit.ui.common.data.mappers.DistributionSetToProxyDistributionMapper; import org.eclipse.hawkbit.ui.common.data.mappers.DistributionSetToProxyDistributionMapper;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSet; 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.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Direction;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@@ -47,19 +48,22 @@ public class DistributionSetStatelessDataProvider
} }
@Override @Override
protected Page<DistributionSet> loadBackendEntities(final PageRequest pageRequest, final String filter) { protected Slice<DistributionSet> loadBackendEntities(final PageRequest pageRequest, final String filter) {
final DistributionSetFilterBuilder builder = new DistributionSetFilterBuilder().setIsDeleted(false) return distributionSetManagement.findByDistributionSetFilter(pageRequest, buildDsFilter(filter));
.setIsComplete(true).setIsValid(true); }
private DistributionSetFilter buildDsFilter(final String filter) {
final DistributionSetFilterBuilder dsFilterBuilder = new DistributionSetFilterBuilder().setIsDeleted(false)
.setIsComplete(true).setIsValid(true);
if (!StringUtils.isEmpty(filter)) { if (!StringUtils.isEmpty(filter)) {
builder.setFilterString(filter); dsFilterBuilder.setSearchText(filter);
} }
return distributionSetManagement.findByDistributionSetFilter(pageRequest, builder.build()); return dsFilterBuilder.build();
} }
@Override @Override
protected long sizeInBackEnd(final PageRequest pageRequest, final String filter) { protected long sizeInBackEnd(final PageRequest pageRequest, final String filter) {
return loadBackendEntities(PageRequest.of(0, 1), filter).getTotalElements(); return distributionSetManagement.countByDistributionSetFilter(buildDsFilter(filter));
} }
} }

View File

@@ -51,6 +51,6 @@ public class DsMetaDataDataProvider extends AbstractMetaDataDataProvider<Distrib
return 0L; return 0L;
} }
return loadBackendEntities(PageRequest.of(0, 1), dsId).getTotalElements(); return distributionSetManagement.countMetaDataByDistributionSetId(dsId);
} }
} }

View File

@@ -59,6 +59,6 @@ public class SmMetaDataDataProvider extends AbstractMetaDataDataProvider<Softwar
return 0L; return 0L;
} }
return loadBackendEntities(PageRequest.of(0, 1), smId).getTotalElements(); return softwareModuleManagement.countMetaDataBySoftwareModuleId(smId);
} }
} }

View File

@@ -59,6 +59,6 @@ public class TargetFilterQueryDataProvider
return targetFilterQueryManagement.count(); return targetFilterQueryManagement.count();
} }
return targetFilterQueryManagement.findByName(PageRequest.of(0, 1), filter).getTotalElements(); return targetFilterQueryManagement.countByName(filter);
} }
} }

View File

@@ -14,6 +14,7 @@ import org.eclipse.hawkbit.ui.common.data.mappers.TargetFilterQueryToProxyTarget
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetFilterQuery; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetFilterQuery;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Direction;
@@ -44,12 +45,12 @@ public class TargetFilterQueryDetailsDataProvider
} }
@Override @Override
protected Page<TargetFilterQuery> loadBackendEntities(final PageRequest pageRequest, final Long dsId) { protected Slice<TargetFilterQuery> loadBackendEntities(final PageRequest pageRequest, final Long dsId) {
if (dsId == null) { if (dsId == null) {
return Page.empty(pageRequest); return Page.empty(pageRequest);
} }
return targetFilterQueryManagement.findByAutoAssignDSAndRsql(pageRequest, dsId, null); return targetFilterQueryManagement.findByAutoAssignDistributionSetId(pageRequest, dsId);
} }
@Override @Override
@@ -58,6 +59,6 @@ public class TargetFilterQueryDetailsDataProvider
return 0L; return 0L;
} }
return loadBackendEntities(PageRequest.of(0, 1), dsId).getTotalElements(); return targetFilterQueryManagement.countByAutoAssignDistributionSetId(dsId);
} }
} }

View File

@@ -52,7 +52,6 @@ public class TargetMetaDataDataProvider extends AbstractMetaDataDataProvider<Tar
return 0L; return 0L;
} }
return targetManagement.findMetaDataByControllerId(PageRequest.of(0, 1), currentlySelectedControllerId) return targetManagement.countMetaDataByControllerId(currentlySelectedControllerId);
.getTotalElements();
} }
} }

View File

@@ -49,7 +49,7 @@ public class TargetTagDataProvider extends AbstractProxyDataProvider<ProxyTag, T
@Override @Override
protected long sizeInBackEnd(final PageRequest pageRequest, final Void filter) { protected long sizeInBackEnd(final PageRequest pageRequest, final Void filter) {
return loadBackendEntities(PageRequest.of(0, 1), filter).getTotalElements(); return tagManagementService.count();
} }
} }

View File

@@ -12,8 +12,8 @@ import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.ui.common.data.mappers.IdentifiableEntityToProxyIdentifiableEntityMapper; import org.eclipse.hawkbit.ui.common.data.mappers.IdentifiableEntityToProxyIdentifiableEntityMapper;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Direction;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@@ -35,26 +35,32 @@ public class TargetTypeDataProvider<T extends ProxyIdentifiableEntity>
* Constructor * Constructor
* *
* @param targetTypeManagement * @param targetTypeManagement
* TargetTypeManagement * TargetTypeManagement
* @param mapper * @param mapper
* Mapper * Mapper
*/ */
public TargetTypeDataProvider(final TargetTypeManagement targetTypeManagement, IdentifiableEntityToProxyIdentifiableEntityMapper<T, TargetType> mapper) { public TargetTypeDataProvider(final TargetTypeManagement targetTypeManagement,
final IdentifiableEntityToProxyIdentifiableEntityMapper<T, TargetType> mapper) {
super(mapper, Sort.by(Direction.ASC, "name")); super(mapper, Sort.by(Direction.ASC, "name"));
this.targetTypeManagement = targetTypeManagement; this.targetTypeManagement = targetTypeManagement;
} }
@Override @Override
protected Page<TargetType> loadBackendEntities(PageRequest pageRequest, String filter) { protected Slice<TargetType> loadBackendEntities(final PageRequest pageRequest, final String filter) {
if (!StringUtils.isEmpty(filter)){ if (StringUtils.isEmpty(filter)) {
return targetTypeManagement.findByName(pageRequest, filter); return targetTypeManagement.findAll(pageRequest);
} }
return targetTypeManagement.findAll(pageRequest);
return targetTypeManagement.findByName(pageRequest, filter);
} }
@Override @Override
protected long sizeInBackEnd(PageRequest pageRequest, String filter) { protected long sizeInBackEnd(final PageRequest pageRequest, final String filter) {
return loadBackendEntities(PageRequest.of(0, 1), filter).getTotalElements(); if (StringUtils.isEmpty(filter)) {
return targetTypeManagement.count();
}
return targetTypeManagement.countByName(filter);
} }
} }

View File

@@ -162,7 +162,6 @@ public class ProxyDistributionSet extends ProxyNamedEntity implements VersionAwa
ds.setId(dsInfo.getId()); ds.setId(dsInfo.getId());
ds.setName(dsInfo.getName()); ds.setName(dsInfo.getName());
ds.setVersion(dsInfo.getVersion()); ds.setVersion(dsInfo.getVersion());
ds.setTypeInfo(new ProxyTypeInfo(dsInfo.getDsTypeId(), null));
ds.setNameVersion(dsInfo.getNameVersion()); ds.setNameVersion(dsInfo.getNameVersion());
ds.setIsValid(dsInfo.isValid()); 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 * Gets the Id, name, version, dsTypeId and invalidation state of
* set * distribution set
* *
* @return proxy of Id, name, version, dsTypeId and invalidation state * @return proxy of Id, name, version, dsTypeId and invalidation state
*/ */
public ProxyDistributionSetInfo getInfo() { public ProxyDistributionSetInfo getInfo() {
return new ProxyDistributionSetInfo(getId(), getName(), getVersion(), getTypeInfo().getId(), getIsValid()); return new ProxyDistributionSetInfo(getId(), getName(), getVersion(), getIsValid());
} }
} }

View File

@@ -21,7 +21,6 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity {
private String name; private String name;
private String version; private String version;
private String nameVersion; private String nameVersion;
private Long dsTypeId;
private boolean isValid; private boolean isValid;
/** /**
@@ -40,18 +39,14 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity {
* distribution set name * distribution set name
* @param version * @param version
* distribution set version * distribution set version
* @param dsTypeId
* ID of the assigned dsType
* @param isValid * @param isValid
* invalidation state * invalidation state
*/ */
public ProxyDistributionSetInfo(final Long id, final String name, final String version, final Long dsTypeId, public ProxyDistributionSetInfo(final Long id, final String name, final String version, final boolean isValid) {
final boolean isValid) {
super(id); super(id);
this.name = name; this.name = name;
this.version = version; this.version = version;
this.dsTypeId = dsTypeId;
this.isValid = isValid; this.isValid = isValid;
this.nameVersion = HawkbitCommonUtil.getFormattedNameVersion(name, version); this.nameVersion = HawkbitCommonUtil.getFormattedNameVersion(name, version);
} }
@@ -88,19 +83,11 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity {
this.isValid = isValid; this.isValid = isValid;
} }
public Long getDsTypeId() {
return dsTypeId;
}
public void setDsTypeId(final Long dsTypeId) {
this.dsTypeId = dsTypeId;
}
@Override @Override
public int hashCode() { public int hashCode() {
// nameVersion is ignored because it is a composition of name and // nameVersion is ignored because it is a composition of name and
// version // version
return Objects.hash(getId(), getName(), getVersion(), getDsTypeId(), isValid()); return Objects.hash(getId(), getName(), getVersion(), isValid());
} }
// equals method requires all of the used conditions // equals method requires all of the used conditions
@@ -119,7 +106,6 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity {
// version // version
return Objects.equals(this.getId(), other.getId()) && Objects.equals(this.getName(), other.getName()) return Objects.equals(this.getId(), other.getId()) && Objects.equals(this.getName(), other.getName())
&& Objects.equals(this.getVersion(), other.getVersion()) && Objects.equals(this.getVersion(), other.getVersion())
&& Objects.equals(this.getDsTypeId(), other.getDsTypeId())
&& Objects.equals(this.isValid(), other.isValid()); && Objects.equals(this.isValid(), other.isValid());
} }
} }

View File

@@ -115,7 +115,7 @@ public class SwModulesToDistributionSetAssignmentSupport
return false; return false;
} }
if (!ds.getIsValid()) { if (Boolean.FALSE.equals(ds.getIsValid())) {
/* Distribution is invalidated */ /* Distribution is invalidated */
addSpecificValidationErrorMessage( addSpecificValidationErrorMessage(
i18n.getMessage(UIMessageIdProvider.MESSAGE_ERROR_DISTRIBUTIONSET_INVALID, ds.getNameVersion())); 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, private boolean checkDuplicateSmToDsAssignment(final ProxySoftwareModule sm, final ProxyDistributionSet ds,
final Collection<Long> smIdsAlreadyAssignedToDs) { final Collection<Long> smIdsAlreadyAssignedToDs) {
if (!CollectionUtils.isEmpty(smIdsAlreadyAssignedToDs) && smIdsAlreadyAssignedToDs.contains(sm.getId())) { if (!CollectionUtils.isEmpty(smIdsAlreadyAssignedToDs) && smIdsAlreadyAssignedToDs.contains(sm.getId())) {
addSpecificValidationErrorMessage(i18n.getMessage("message.software.dist.already.assigned", sm.getNameAndVersion(), addSpecificValidationErrorMessage(i18n.getMessage("message.software.dist.already.assigned",
ds.getNameVersion())); sm.getNameAndVersion(), ds.getNameVersion()));
return false; return false;
} }
@@ -158,8 +158,8 @@ public class SwModulesToDistributionSetAssignmentSupport
if (!dsType.containsModuleType(sm.getTypeInfo().getId())) { if (!dsType.containsModuleType(sm.getTypeInfo().getId())) {
final String smTypeName = smTypeManagement.get(sm.getTypeInfo().getId()).map(SoftwareModuleType::getName) final String smTypeName = smTypeManagement.get(sm.getTypeInfo().getId()).map(SoftwareModuleType::getName)
.orElse(""); .orElse("");
addSpecificValidationErrorMessage(i18n.getMessage("message.software.dist.type.notallowed", sm.getNameAndVersion(), addSpecificValidationErrorMessage(i18n.getMessage("message.software.dist.type.notallowed",
ds.getNameVersion(), smTypeName)); sm.getNameAndVersion(), ds.getNameVersion(), smTypeName));
return false; return false;
} }

View File

@@ -82,8 +82,7 @@ public class DistributionSetGrid extends AbstractDsGrid<DsDistributionsFilterPar
} }
setFilterSupport(new FilterSupport<>( setFilterSupport(new FilterSupport<>(
new DistributionSetDistributionsStateDataProvider(dsManagement, dsTypeManagement, new DistributionSetDistributionsStateDataProvider(dsManagement, dsToProxyDistributionMapper),
dsToProxyDistributionMapper),
DsDistributionsFilterParams::new, getSelectionSupport()::deselectAll)); DsDistributionsFilterParams::new, getSelectionSupport()::deselectAll));
initFilterMappings(); initFilterMappings();
getFilterSupport().setFilter(new DsDistributionsFilterParams()); getFilterSupport().setFilter(new DsDistributionsFilterParams());
@@ -105,10 +104,10 @@ public class DistributionSetGrid extends AbstractDsGrid<DsDistributionsFilterPar
private static String getRowStyle(final ProxyDistributionSet ds) { private static String getRowStyle(final ProxyDistributionSet ds) {
final StringBuilder style = new StringBuilder(); final StringBuilder style = new StringBuilder();
if (!ds.getIsComplete()) { if (Boolean.FALSE.equals(ds.getIsComplete())) {
style.append(SPUIDefinitions.INCOMPLETE_DISTRIBUTION); style.append(SPUIDefinitions.INCOMPLETE_DISTRIBUTION);
} }
if (!ds.getIsValid()) { if (Boolean.FALSE.equals(ds.getIsValid())) {
style.append(" "); style.append(" ");
style.append(SPUIDefinitions.INVALID_DISTRIBUTION); style.append(SPUIDefinitions.INVALID_DISTRIBUTION);
} }

View File

@@ -72,8 +72,8 @@ public class RolloutFormLayout extends ValidatableLayout {
private Long rolloutId; private Long rolloutId;
private Long totalTargets; private Long totalTargets;
private Consumer<String> filterQueryChangedListener; private Consumer<ProxyTargetFilterQuery> filterQueryChangedListener;
private Consumer<Long> distSetChangedListener; private Consumer<ProxyDistributionSet> distSetChangedListener;
/** /**
* Constructor for RolloutFormLayout * Constructor for RolloutFormLayout
@@ -204,7 +204,7 @@ public class RolloutFormLayout extends ValidatableLayout {
private HasValue.ValueChangeListener<ProxyTargetFilterQuery> filterQueryChangedListener() { private HasValue.ValueChangeListener<ProxyTargetFilterQuery> filterQueryChangedListener() {
return event -> { return event -> {
if (filterQueryChangedListener != null) { 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<ProxyDistributionSet> distSetChangedListener() { private HasValue.ValueChangeListener<ProxyDistributionSet> distSetChangedListener() {
return event -> { return event -> {
if (distSetChangedListener != null) { if (distSetChangedListener != null) {
if (event.getValue() != null && event.getValue().getTypeInfo() != null) { distSetChangedListener.accept(event.getValue());
distSetChangedListener.accept(event.getValue().getTypeInfo().getId());
} else {
distSetChangedListener.accept(null);
}
} }
}; };
} }
@@ -300,7 +296,7 @@ public class RolloutFormLayout extends ValidatableLayout {
* @param filterQueryChangedListener * @param filterQueryChangedListener
* Changed listener * Changed listener
*/ */
public void setFilterQueryChangedListener(final Consumer<String> filterQueryChangedListener) { public void setFilterQueryChangedListener(final Consumer<ProxyTargetFilterQuery> filterQueryChangedListener) {
this.filterQueryChangedListener = filterQueryChangedListener; this.filterQueryChangedListener = filterQueryChangedListener;
} }
@@ -310,7 +306,7 @@ public class RolloutFormLayout extends ValidatableLayout {
* @param distSetChangedListener * @param distSetChangedListener
* Changed listener * Changed listener
*/ */
public void setDistSetChangedListener(final Consumer<Long> distSetChangedListener) { public void setDistSetChangedListener(final Consumer<ProxyDistributionSet> distSetChangedListener) {
this.distSetChangedListener = distSetChangedListener; this.distSetChangedListener = distSetChangedListener;
} }

View File

@@ -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.components.AutoStartOptionGroupLayout.AutoStartOption;
import org.eclipse.hawkbit.ui.rollout.window.layouts.AddRolloutWindowLayout; import org.eclipse.hawkbit.ui.rollout.window.layouts.AddRolloutWindowLayout;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
/** /**
@@ -94,9 +94,9 @@ public class CopyRolloutWindowController extends AddRolloutWindowController {
} }
private void setTargetFilterId(final ProxyRolloutWindow proxyRolloutWindow) { private void setTargetFilterId(final ProxyRolloutWindow proxyRolloutWindow) {
final Page<TargetFilterQuery> filterQueries = targetFilterQueryManagement.findByQuery(PageRequest.of(0, 1), final Slice<TargetFilterQuery> filterQueries = targetFilterQueryManagement.findByQuery(PageRequest.of(0, 1),
proxyRolloutWindow.getTargetFilterQuery()); proxyRolloutWindow.getTargetFilterQuery());
if (filterQueries.getTotalElements() > 0) { if (filterQueries.getNumberOfElements() > 0) {
final TargetFilterQuery tfq = filterQueries.getContent().get(0); final TargetFilterQuery tfq = filterQueries.getContent().get(0);
proxyRolloutWindow proxyRolloutWindow
.setTargetFilterInfo(new ProxyTargetFilterQueryInfo(tfq.getId(), tfq.getName(), tfq.getQuery())); .setTargetFilterInfo(new ProxyTargetFilterQueryInfo(tfq.getId(), tfq.getName(), tfq.getQuery()));

View File

@@ -11,10 +11,15 @@ package org.eclipse.hawkbit.ui.rollout.window.layouts;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; 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.repository.TargetManagement;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyAdvancedRolloutGroup; 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;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyRolloutWindow.GroupDefinitionMode; 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.RolloutWindowDependencies;
import org.eclipse.hawkbit.ui.rollout.window.components.AdvancedGroupsLayout; import org.eclipse.hawkbit.ui.rollout.window.components.AdvancedGroupsLayout;
import org.eclipse.hawkbit.ui.rollout.window.components.RolloutFormLayout; import org.eclipse.hawkbit.ui.rollout.window.components.RolloutFormLayout;
@@ -34,6 +39,7 @@ import com.vaadin.ui.TabSheet;
public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout { public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
private final TargetManagement targetManagement; private final TargetManagement targetManagement;
private final DistributionSetManagement dsManagement;
private final RolloutFormLayout rolloutFormLayout; private final RolloutFormLayout rolloutFormLayout;
private final SimpleGroupsLayout simpleGroupsLayout; private final SimpleGroupsLayout simpleGroupsLayout;
@@ -57,6 +63,7 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
super(dependencies); super(dependencies);
this.targetManagement = dependencies.getTargetManagement(); this.targetManagement = dependencies.getTargetManagement();
this.dsManagement = dependencies.getDistributionSetManagement();
this.rolloutFormLayout = rolloutComponentBuilder.createRolloutFormLayout(); this.rolloutFormLayout = rolloutComponentBuilder.createRolloutFormLayout();
this.simpleGroupsLayout = rolloutComponentBuilder.createSimpleGroupsLayout(); this.simpleGroupsLayout = rolloutComponentBuilder.createSimpleGroupsLayout();
@@ -90,8 +97,8 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
advancedGroupsLayout.setAdvancedGroupDefinitionsChangedListener(this::onAdvancedGroupsChanged); advancedGroupsLayout.setAdvancedGroupDefinitionsChangedListener(this::onAdvancedGroupsChanged);
} }
private void onFilterQueryChange(final String filterQuery) { private void onFilterQueryChange(final ProxyTargetFilterQuery targetFilterQuery) {
this.filterQuery = filterQuery; filterQuery = targetFilterQuery != null ? targetFilterQuery.getQuery() : null;
updateTotalTargets(); updateTotalTargets();
if (isAdvancedGroupsTabSelected()) { if (isAdvancedGroupsTabSelected()) {
@@ -99,8 +106,8 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
} }
} }
private void onDistSetTypeChange(final Long dsTypeId) { private void onDistSetTypeChange(final ProxyDistributionSet ds) {
this.dsTypeId = dsTypeId; dsTypeId = ds != null ? getDsTypeId(ds) : null;
updateTotalTargets(); updateTotalTargets();
if (isAdvancedGroupsTabSelected()) { 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() { private void updateTotalTargets() {
this.totalTargets = getTotalTargets(filterQuery, dsTypeId); totalTargets = getTotalTargets(filterQuery, dsTypeId);
rolloutFormLayout.setTotalTargets(totalTargets); rolloutFormLayout.setTotalTargets(totalTargets);
visualGroupDefinitionLayout.setTotalTargets(totalTargets); visualGroupDefinitionLayout.setTotalTargets(totalTargets);
if (isSimpleGroupsTabSelected()) { if (isSimpleGroupsTabSelected()) {