Implement TargetFilterQueryManagement with AbstractJpaRepositoryManagement (#2587)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-08-05 09:53:24 +03:00
committed by GitHub
parent 1824839a6f
commit 7b24981a1d
36 changed files with 736 additions and 1482 deletions

View File

@@ -14,7 +14,6 @@ import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_UP
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -29,7 +28,6 @@ import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
@@ -146,7 +144,7 @@ public interface DistributionSetManagement<T extends DistributionSet>
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void lock(final long id);
T lock(final long id);
/**
* Unlocks a distribution set.<br/>
@@ -157,7 +155,7 @@ public interface DistributionSetManagement<T extends DistributionSet>
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void unlock(final long id);
T unlock(final long id);
/**
* Find distribution set by id and throw an exception if it is deleted or invalidated.
@@ -310,11 +308,11 @@ public interface DistributionSetManagement<T extends DistributionSet>
List<Statistic> countActionsByStatusForDistributionSet(@NotNull Long id);
/**
* Count all {@link org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate}s
* Count all {@link TargetFilterQueryManagement.AutoAssignDistributionSetUpdate}s
* for Distribution Set.
*
* @param id to look for
* @return number of {@link org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate}s
* @return number of {@link TargetFilterQueryManagement.AutoAssignDistributionSetUpdate}s
*/
@PreAuthorize(HAS_READ_REPOSITORY)
Long countAutoAssignmentsForDistributionSet(@NotNull Long id);

View File

@@ -13,7 +13,6 @@ import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.model.BaseEntity;
/**
@@ -21,6 +20,11 @@ import org.eclipse.hawkbit.repository.model.BaseEntity;
*/
public interface EntityFactory {
/**
* @return {@link TargetBuilder} object
*/
TargetBuilder target();
/**
* @return {@link ActionStatusBuilder} object
*/
@@ -35,14 +39,4 @@ public interface EntityFactory {
* @return {@link RolloutBuilder} object
*/
RolloutBuilder rollout();
/**
* @return {@link TargetBuilder} object
*/
TargetBuilder target();
/**
* @return {@link TargetFilterQueryBuilder} object
*/
TargetFilterQueryBuilder targetFilterQuery();
}

View File

@@ -9,16 +9,20 @@
*/
package org.eclipse.hawkbit.repository;
import java.util.Optional;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
@@ -26,8 +30,10 @@ import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeExcep
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@@ -37,29 +43,13 @@ import org.springframework.security.access.prepost.PreAuthorize;
/**
* Management service for {@link TargetFilterQuery}s.
*/
public interface TargetFilterQueryManagement {
public interface TargetFilterQueryManagement<T extends TargetFilterQuery>
extends RepositoryManagement<T, TargetFilterQueryManagement.Create, TargetFilterQueryManagement.Update> {
/**
* Creates a new {@link TargetFilterQuery}.
*
* @param create to create
* @return the new {@link TargetFilterQuery}
* @throws ConstraintViolationException if fields are not filled as specified. Check
* {@link TargetFilterQueryCreate} for field constraints.
* @throws AssignmentQuotaExceededException if the maximum number of targets that is addressed by the
* given query is exceeded (auto-assignments only)
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
TargetFilterQuery create(@NotNull @Valid TargetFilterQueryCreate create);
/**
* Deletes the {@link TargetFilterQuery} with the given ID.
*
* @param targetFilterQueryId IDs of target filter query to be deleted
* @throws EntityNotFoundException if filter with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_TARGET)
void delete(long targetFilterQueryId);
@Override
default String permissionGroup() {
return "TARGET";
}
/**
* Verifies the provided filter syntax.
@@ -73,23 +63,6 @@ public interface TargetFilterQueryManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
boolean verifyTargetFilterQuerySyntax(@NotNull String query);
/**
* Retrieves all {@link TargetFilterQuery}s.
*
* @param pageable pagination parameter
* @return the found {@link TargetFilterQuery}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<TargetFilterQuery> findAll(@NotNull Pageable pageable);
/**
* Counts all {@link TargetFilterQuery}s.
*
* @return the number of all target filter queries
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
long count();
/**
* Counts all target filters that have a given auto assign distribution set
* assigned.
@@ -102,57 +75,6 @@ public interface TargetFilterQueryManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
long countByAutoAssignDistributionSetId(long autoAssignDistributionSetId);
/**
* Retrieves all {@link TargetFilterQuery}s which match the given name
* filter.
*
* @param name name filter
* @param pageable pagination parameter
* @return the page with the found {@link TargetFilterQuery}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<TargetFilterQuery> findByName(@NotNull String name, @NotNull Pageable pageable);
/**
* 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 filter.
*
* @param rsqlFilter RSQL filter string
* @param pageable pagination parameter
* @return the page with the found {@link TargetFilterQuery}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<TargetFilterQuery> findByRsql(@NotNull String rsqlFilter, @NotNull Pageable pageable);
/**
* Retrieves all {@link TargetFilterQuery}s which match the given query.
*
* @param query the query saved in the target filter query
* @param pageable pagination parameter
* @return the page with the found {@link TargetFilterQuery}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<TargetFilterQuery> findByQuery(@NotNull String query, @NotNull Pageable pageable);
/**
* Retrieves all {@link TargetFilterQuery}s which match the given auto-assign distribution set ID.
*
* @param setId the auto assign distribution set
* @param pageable pagination parameter
* @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(long setId, @NotNull Pageable pageable);
/**
* Retrieves all {@link TargetFilterQuery}s which match the given auto-assign distribution set and RSQL filter.
*
@@ -174,39 +96,6 @@ public interface TargetFilterQueryManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<TargetFilterQuery> findWithAutoAssignDS(@NotNull Pageable pageable);
/**
* Finds the {@link TargetFilterQuery} by id.
*
* @param targetFilterQueryId Target filter query id
* @return the found {@link TargetFilterQuery}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Optional<TargetFilterQuery> get(long targetFilterQueryId);
/**
* Finds the {@link TargetFilterQuery} that matches the given name.
*
* @param targetFilterQueryName Target filter query name
* @return the found {@link TargetFilterQuery}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Optional<TargetFilterQuery> getByName(@NotNull String targetFilterQueryName);
/**
* Updates the {@link TargetFilterQuery}.
*
* @param update to be updated
* @return the updated {@link TargetFilterQuery}
* @throws EntityNotFoundException if either {@link TargetFilterQuery} and/or autoAssignDs are
* provided but not found
* @throws ConstraintViolationException if fields are not filled as specified. Check
* {@link TargetFilterQueryUpdate} for field constraints.
* @throws QuotaExceededException if the update contains a new query which addresses too many
* targets (auto-assignments only)
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetFilterQuery update(@NotNull @Valid TargetFilterQueryUpdate update);
/**
* Updates the auto assign settings of an {@link TargetFilterQuery}.
*
@@ -224,8 +113,7 @@ public interface TargetFilterQueryManagement {
* invalidated
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetFilterQuery updateAutoAssignDS(
@NotNull @Valid AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate);
TargetFilterQuery updateAutoAssignDS(@NotNull @Valid AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate);
/**
* Removes the given {@link DistributionSet} from all auto assignments.
@@ -235,4 +123,118 @@ public interface TargetFilterQueryManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
void cancelAutoAssignmentForDistributionSet(long setId);
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Create extends UpdateCreate {
private DistributionSet autoAssignDistributionSet;
private ActionType autoAssignActionType;
@Setter
@Min(Action.WEIGHT_MIN)
@Max(Action.WEIGHT_MAX)
private Integer autoAssignWeight;
private boolean confirmationRequired;
}
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Update extends UpdateCreate implements Identifiable<Long> {
@NotNull
private Long id;
}
@SuperBuilder
@Getter
class UpdateCreate {
@ValidString
@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE)
@NotNull(groups = DistributionSetTagManagement.Create.class)
private String name;
@ValidString
@Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE)
private String query;
}
/**
* Builder to update the auto assign {@link DistributionSet} of a
* {@link TargetFilterQuery} entry. Defines all fields that can be updated.
*/
@Data
@Accessors(fluent = true)
@EqualsAndHashCode
@ToString
class AutoAssignDistributionSetUpdate {
private final long targetFilterId;
private Long dsId;
private ActionType actionType;
@Min(Action.WEIGHT_MIN)
@Max(Action.WEIGHT_MAX)
private Integer weight;
private Boolean confirmationRequired;
/**
* Constructor
*
* @param targetFilterId ID of {@link TargetFilterQuery} to update
*/
public AutoAssignDistributionSetUpdate(final long targetFilterId) {
this.targetFilterId = targetFilterId;
}
/**
* Specify {@link DistributionSet}
*
* @param dsId ID of the {@link DistributionSet}
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate ds(final Long dsId) {
this.dsId = dsId;
return this;
}
/**
* Specify {@link DistributionSet}
*
* @param actionType {@link ActionType} used for the auto assignment
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate actionType(final ActionType actionType) {
this.actionType = actionType;
return this;
}
/**
* Specify weight of resulting {@link Action}
*
* @param weight weight used for the auto assignment
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate weight(final Integer weight) {
this.weight = weight;
return this;
}
/**
* Specify initial confirmation state of resulting {@link Action}
*
* @param confirmationRequired if confirmation is required for this auto assignment (considered
* with confirmation flow active)
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate confirmationRequired(final boolean confirmationRequired) {
this.confirmationRequired = confirmationRequired;
return this;
}
}
}

View File

@@ -1,95 +0,0 @@
/**
* Copyright (c) 2019 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.builder;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder to update the auto assign {@link DistributionSet} of a
* {@link TargetFilterQuery} entry. Defines all fields that can be updated.
*/
@Getter
@EqualsAndHashCode
@ToString
public class AutoAssignDistributionSetUpdate {
private final long targetFilterId;
private Long dsId;
private ActionType actionType;
@Min(Action.WEIGHT_MIN)
@Max(Action.WEIGHT_MAX)
private Integer weight;
private Boolean confirmationRequired;
/**
* Constructor
*
* @param targetFilterId ID of {@link TargetFilterQuery} to update
*/
public AutoAssignDistributionSetUpdate(final long targetFilterId) {
this.targetFilterId = targetFilterId;
}
/**
* Specify {@link DistributionSet}
*
* @param dsId ID of the {@link DistributionSet}
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate ds(final Long dsId) {
this.dsId = dsId;
return this;
}
/**
* Specify {@link DistributionSet}
*
* @param actionType {@link ActionType} used for the auto assignment
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate actionType(final ActionType actionType) {
this.actionType = actionType;
return this;
}
/**
* Specify weight of resulting {@link Action}
*
* @param weight weight used for the auto assignment
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate weight(final Integer weight) {
this.weight = weight;
return this;
}
/**
* Specify initial confirmation state of resulting {@link Action}
*
* @param confirmationRequired if confirmation is required for this auto assignment (considered
* with confirmation flow active)
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate confirmationRequired(final boolean confirmationRequired) {
this.confirmationRequired = confirmationRequired;
return this;
}
}

View File

@@ -1,39 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.builder;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder for {@link TargetFilterQuery}.
*/
public interface TargetFilterQueryBuilder {
/**
* Used to update a {@link TargetFilterQuery}
*
* @param id of the updatable entity
* @return builder instance
*/
TargetFilterQueryUpdate update(long id);
/**
* Used to update a the auto assignment of a {@link TargetFilterQuery}
*
* @param id of the updatable entity
* @return builder instance
*/
AutoAssignDistributionSetUpdate updateAutoAssign(long id);
/**
* @return builder instance
*/
TargetFilterQueryCreate create();
}

View File

@@ -1,95 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.builder;
import java.util.Optional;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder to create a new {@link TargetFilterQuery} entry. Defines all fields
* that can be set at creation time. Other fields are set by the repository
* automatically, e.g. {@link BaseEntity#getCreatedAt()}.
*/
public interface TargetFilterQueryCreate {
/**
* Set filter name
*
* @param name of {@link TargetFilterQuery#getName()}
* @return updated builder instance
*/
TargetFilterQueryCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
/**
* Set filter query
*
* @param query of {@link TargetFilterQuery#getQuery()}
* @return updated builder instance
*/
TargetFilterQueryCreate query(@Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE) @NotNull String query);
/**
* Set {@link DistributionSet} for auto assignment
*
* @param distributionSet for {@link TargetFilterQuery#getAutoAssignDistributionSet()}
* @return updated builder instance
*/
default TargetFilterQueryCreate autoAssignDistributionSet(final DistributionSet distributionSet) {
return autoAssignDistributionSet(Optional.ofNullable(distributionSet).map(DistributionSet::getId).orElse(null));
}
/**
* Set ID of {@link DistributionSet} for auto assignment
*
* @param dsId for {@link TargetFilterQuery#getAutoAssignDistributionSet()}
* @return updated builder instance
*/
TargetFilterQueryCreate autoAssignDistributionSet(Long dsId);
/**
* Set {@link ActionType} for auto assignment
*
* @param actionType for {@link TargetFilterQuery#getAutoAssignActionType()}
* @return updated builder instance
*/
TargetFilterQueryCreate autoAssignActionType(ActionType actionType);
/**
* Set weight of {@link Action} created during auto assignment
*
* @param weight weight of {@link Action} generated within auto assignment
* @return updated builder instance
*/
TargetFilterQueryCreate autoAssignWeight(Integer weight);
/**
* Specify initial confirmation state of resulting {@link Action} in auto
* assignment
*
* @param confirmationRequired if confirmation is required for configured auto assignment (considered
* with confirmation flow active)
* @return updated builder instance
*/
TargetFilterQueryCreate confirmationRequired(boolean confirmationRequired);
/**
* @return peek on current state of {@link TargetFilterQuery} in the builder
*/
TargetFilterQuery build();
}

View File

@@ -1,34 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.builder;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder to update an existing {@link TargetFilterQuery} entry. Defines all
* fields that can be updated.
*/
public interface TargetFilterQueryUpdate {
/**
* @param name of {@link TargetFilterQuery#getName()}
* @return updated builder instance
*/
TargetFilterQueryUpdate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) String name);
/**
* @param query of {@link TargetFilterQuery#getQuery()}
* @return updated builder instance
*/
TargetFilterQueryUpdate query(@Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE) String query);
}