diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTagFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTagFields.java index b3e744775..a16766021 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTagFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTagFields.java @@ -9,14 +9,10 @@ */ package org.eclipse.hawkbit.repository; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - /** * Describing the fields of the Tag model which can be used in the REST API e.g. * for sorting etc. - * Additionally here were added fields for Target in order + * Additionally, here were added fields for Target in order * filtering over target fields also. */ public enum TargetTagFields implements FieldNameProvider { @@ -36,31 +32,12 @@ public enum TargetTagFields implements FieldNameProvider { /** * The controllerId field. */ - COLOUR(TagFields.COLOUR.getFieldName()), - - /** - * Target fields - */ - TARGET("assignedToTargets", - TargetFields.ID.getFieldName(), TargetFields.NAME.getFieldName()); + COLOUR(TagFields.COLOUR.getFieldName()); private final String fieldName; - private final List subEntityAttributes; - - private TargetTagFields(final String fieldName) { + TargetTagFields(final String fieldName) { this.fieldName = fieldName; - this.subEntityAttributes = Collections.emptyList(); - } - - private TargetTagFields(final String fieldName, final String... subEntityAttributes) { - this.fieldName = fieldName; - this.subEntityAttributes = Arrays.asList(subEntityAttributes); - } - - @Override - public List getSubEntityAttributes() { - return Collections.unmodifiableList(subEntityAttributes); } @Override diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTagManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTagManagement.java index 7307c116a..d715dd401 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTagManagement.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository; import java.util.Collection; import java.util.List; import java.util.Optional; +import java.util.Set; import jakarta.validation.ConstraintViolationException; import jakarta.validation.Valid; @@ -101,22 +102,6 @@ public interface TargetTagManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) Page findAll(@NotNull Pageable pageable); - /** - * Returns all {@link TargetTag}s assigned to {@link Target} with given ID. - * - * @param pageable - * page parameter - * @param controllerId - * of the assigned target - * - * @return {@link TargetTag}s assigned to {@link Target} with given ID - * - * @throws EntityNotFoundException - * if target with given ID does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Page findByTarget(@NotNull Pageable pageable, @NotEmpty String controllerId); - /** * Retrieves all target tags based on the given specification. * diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java index d67011e47..d0d3590f1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java @@ -29,9 +29,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag_; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; -import org.eclipse.hawkbit.repository.jpa.specifications.TagSpecification; -import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; -import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.springframework.dao.ConcurrencyFailureException; @@ -146,14 +143,4 @@ public class JpaTargetTagManagement implements TargetTagManagement { public Page findAll(final Pageable pageable) { return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, null); } - - @Override - public Page findByTarget(final Pageable pageable, final String controllerId) { - if (!targetRepository.exists(TargetSpecifications.hasControllerId(controllerId))) { - throw new EntityNotFoundException(Target.class, controllerId); - } - - return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, - Collections.singletonList(TagSpecification.ofTarget(controllerId))); - } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java index 4f737a093..4863fbcd0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java @@ -96,13 +96,6 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw @Pattern(regexp = "[\\S]*", message = "has whitespaces which are not allowed") private String controllerId; - @CascadeOnDelete - @ManyToMany(targetEntity = JpaTargetTag.class) - @JoinTable(name = "sp_target_target_tag", joinColumns = { - @JoinColumn(name = "target", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_target")) }, inverseJoinColumns = { - @JoinColumn(name = "tag", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_tag")) }) - private Set tags; - @CascadeOnDelete @OneToMany(mappedBy = "target", fetch = FetchType.LAZY, targetEntity = JpaAction.class) private List actions; @@ -111,7 +104,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw * the security token of the target which allows if enabled to authenticate * with this security token. */ - @Column(name = "sec_token", updatable = true, nullable = false, length = Target.SECURITY_TOKEN_MAX_SIZE) + @Column(name = "sec_token", nullable = false, length = Target.SECURITY_TOKEN_MAX_SIZE) @Size(min = 1, max = Target.SECURITY_TOKEN_MAX_SIZE) @NotNull private String securityToken; @@ -149,40 +142,50 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw @JoinColumn(name = "assigned_distribution_set", nullable = true, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_assign_ds")) private JpaDistributionSet assignedDistributionSet; - /** - * Read only on management API. Are committed by controller. - */ - @CascadeOnDelete - @ElementCollection - @Column(name = "attribute_value", length = Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE) - @MapKeyColumn(name = "attribute_key", nullable = false, length = Target.CONTROLLER_ATTRIBUTE_KEY_SIZE) - @CollectionTable(name = "sp_target_attributes", joinColumns = { - @JoinColumn(name = "target_id", nullable = false, updatable = false) }, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_attrib_target")) - private Map controllerAttributes; - - @ManyToOne(fetch = FetchType.LAZY, optional = true, targetEntity = JpaTargetType.class) - @JoinColumn(name = "target_type", nullable = true, updatable = true, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_relation_target_type")) - private TargetType targetType; - - // set default request controller attributes to true, because we want to - // request them the first - // time + // set default request controller attributes to true, because we want to request them the first time @Column(name = "request_controller_attributes", nullable = false) private boolean requestControllerAttributes = true; - @CascadeOnDelete - @OneToMany(mappedBy = "target", fetch = FetchType.LAZY, targetEntity = JpaTargetMetadata.class) - private List metadata; - @OneToOne(fetch = FetchType.LAZY, mappedBy = "target", orphanRemoval = true) @PrimaryKeyJoinColumn private JpaAutoConfirmationStatus autoConfirmationStatus; + @ManyToOne(fetch = FetchType.LAZY, targetEntity = JpaTargetType.class) + @JoinColumn(name = "target_type", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_relation_target_type")) + private TargetType targetType; + + @CascadeOnDelete + @ManyToMany(targetEntity = JpaTargetTag.class) + @JoinTable( + name = "sp_target_target_tag", + joinColumns = { + @JoinColumn(name = "target", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_target")) }, + inverseJoinColumns = { + @JoinColumn(name = "tag", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_tag")) + }) + private Set tags; + + /** + * Supplied / committed by the controller. Read-only via management API. + */ + @CascadeOnDelete + @ElementCollection + @Column(name = "attribute_value", length = Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE) + @MapKeyColumn(name = "attribute_key", nullable = false, length = Target.CONTROLLER_ATTRIBUTE_KEY_SIZE) + @CollectionTable( + name = "sp_target_attributes", + joinColumns = { + @JoinColumn(name = "target_id", nullable = false, updatable = false) }, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_attrib_target")) + private Map controllerAttributes; + + @CascadeOnDelete + @OneToMany(mappedBy = "target", fetch = FetchType.LAZY, targetEntity = JpaTargetMetadata.class) + private List metadata; + /** * Constructor. * - * @param controllerId - * controller ID of the {@link Target} + * @param controllerId controller ID of the {@link Target} */ public JpaTarget(final String controllerId) { this(controllerId, SecurityTokenGeneratorHolder.getInstance().generateToken()); @@ -191,22 +194,16 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw /** * Constructor. * - * @param controllerId - * controller ID of the {@link Target} - * @param securityToken - * for target authentication if enabled + * @param controllerId controller ID of the {@link Target} + * @param securityToken for target authentication if enabled */ public JpaTarget(final String controllerId, final String securityToken) { this.controllerId = controllerId; - setName(truncateControllerIdToMaxNameLength(controllerId)); + // truncate controller ID to max name length (if needed) + setName(controllerId != null && controllerId.length() > NAME_MAX_SIZE ? controllerId.substring(0, NAME_MAX_SIZE) : controllerId); this.securityToken = securityToken; } - private static String truncateControllerIdToMaxNameLength(final String controllerId) { - return controllerId != null && controllerId.length() > NAME_MAX_SIZE ? controllerId.substring(0, NAME_MAX_SIZE) - : controllerId; - } - /** * Constructor */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetTag.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetTag.java index 0a327aa10..bea23d7d6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetTag.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetTag.java @@ -9,72 +9,44 @@ */ package org.eclipse.hawkbit.repository.jpa.model; -import java.util.Collections; -import java.util.List; +import java.io.Serial; import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; import jakarta.persistence.Index; -import jakarta.persistence.ManyToMany; import jakarta.persistence.Table; import jakarta.persistence.UniqueConstraint; +import lombok.NoArgsConstructor; +import lombok.ToString; import org.eclipse.hawkbit.repository.event.remote.TargetTagDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagUpdatedEvent; -import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; -import org.eclipse.persistence.annotations.CascadeOnDelete; import org.eclipse.persistence.descriptors.DescriptorEvent; /** - * A {@link TargetTag} is used to describe Target attributes and use them also - * for filtering the target list. - * + * A {@link TargetTag} is used to describe Target attributes and use them also for filtering the target list. */ +@NoArgsConstructor // Default constructor for JPA. +@ToString(callSuper = true) @Entity @Table(name = "sp_target_tag", indexes = { @Index(name = "sp_idx_target_tag_prim", columnList = "tenant,id"), @Index(name = "sp_idx_target_tag_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_targ_tag")) public class JpaTargetTag extends JpaTag implements TargetTag, EventAwareEntity { + + @Serial private static final long serialVersionUID = 1L; - @CascadeOnDelete - @ManyToMany(mappedBy = "tags", targetEntity = JpaTarget.class, fetch = FetchType.LAZY) - private List assignedToTargets; - - /** - * Constructor. - * - * @param name - * of {@link TargetTag} - * @param description - * of {@link TargetTag} - * @param colour - * of {@link TargetTag} - */ public JpaTargetTag(final String name, final String description, final String colour) { super(name, description, colour); } - public JpaTargetTag() { - // Default constructor for JPA. - } - - public List getAssignedToTargets() { - if (assignedToTargets == null) { - return Collections.emptyList(); - } - - return Collections.unmodifiableList(assignedToTargets); - } - @Override public void fireCreateEvent(final DescriptorEvent descriptorEvent) { EventPublisherHolder.getInstance().getEventPublisher() .publishEvent(new TargetTagCreatedEvent(this, EventPublisherHolder.getInstance().getApplicationId())); - } @Override @@ -87,7 +59,5 @@ public class JpaTargetTag extends JpaTag implements TargetTag, EventAwareEntity public void fireDeleteEvent(final DescriptorEvent descriptorEvent) { EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new TargetTagDeletedEvent(getTenant(), getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId())); - } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TagSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TagSpecification.java index c11f559ec..a95fc2338 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TagSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TagSpecification.java @@ -11,57 +11,28 @@ package org.eclipse.hawkbit.repository.jpa.specifications; import jakarta.persistence.criteria.Join; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; 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.JpaDistributionSet_; -import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; -import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; -import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag_; -import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetTag; -import org.eclipse.hawkbit.repository.model.Target; -import org.eclipse.hawkbit.repository.model.TargetTag; import org.springframework.data.jpa.domain.Specification; /** - * Specifications class for {@link Tag}s. The class provides Spring Data JPQL - * Specifications. - * + * Specifications class for {@link org.eclipse.hawkbit.repository.model.Tag}s. + * The class provides Spring Data JPQL Specifications. */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class TagSpecification { - private TagSpecification() { - // utility class - } - - /** - * {@link Specification} for retrieving {@link TargetTag}s by assigned - * {@link Target}. - * - * @param controllerId - * of the target - * - * @return the {@link JpaTargetTag} {@link Specification} - */ - public static Specification ofTarget(final String controllerId) { - return (targetRoot, query, criteriaBuilder) -> { - final Join tagJoin = targetRoot.join(JpaTargetTag_.assignedToTargets); - - query.distinct(true); - - return criteriaBuilder.equal(tagJoin.get(JpaTarget_.controllerId), controllerId); - }; - - } /** * {@link Specification} for retrieving {@link DistributionSetTag}s by * assigned {@link DistributionSet}. * - * @param dsId - * of the distribution set - * + * @param dsId of the distribution set * @return the {@link JpaDistributionSetTag} {@link Specification} */ public static Specification ofDistributionSet(final Long dsId) { @@ -75,5 +46,4 @@ public final class TagSpecification { }; } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java index 5c7d2657d..d40946c32 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java @@ -18,7 +18,6 @@ import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.ListJoin; -import jakarta.persistence.criteria.MapJoin; import jakarta.persistence.criteria.Order; import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; @@ -27,13 +26,14 @@ import jakarta.persistence.criteria.SetJoin; import jakarta.persistence.criteria.Subquery; import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaAction_; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; 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.JpaRollout; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup_; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; @@ -57,22 +57,15 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.query.QueryUtils; /** - * Specifications class for {@link Target}s. The class provides Spring Data JPQL - * Specifications. - * + * Specifications class for {@link Target}s. The class provides Spring Data JPQL Specifications. */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class TargetSpecifications { - private TargetSpecifications() { - // utility class - } /** - * {@link Specification} for retrieving {@link Target}s including - * {@link TargetTag}s. - * - * @param controllerIDs - * to search for + * {@link Specification} for retrieving {@link Target}s including {@link TargetTag}s. * + * @param controllerIDs to search for * @return the {@link Target} {@link Specification} */ public static Specification byControllerIdWithTagsInJoin(final Collection controllerIDs) { @@ -87,9 +80,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by controllerId * - * @param controllerID - * to search for - * + * @param controllerID to search for * @return the {@link Target} {@link Specification} */ public static Specification hasControllerId(final String controllerID) { @@ -99,9 +90,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by controllerId * - * @param controllerIDs - * to search for - * + * @param controllerIDs to search for * @return the {@link Target} {@link Specification} */ public static Specification hasControllerIdIn(final Collection controllerIDs) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java index 998e963b7..d21270703 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -28,6 +29,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; +import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; @@ -44,6 +46,7 @@ import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.TenantMetaDataRepository; +import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetTag; @@ -203,6 +206,14 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Action.Status.FINISHED)); } + protected Set getTargetTags(final String controllerId) { + return targetRepository + .findOne(TargetSpecifications.hasControllerId(controllerId)) + .map(JpaTarget.class::cast) + .map(JpaTarget::getTags) + .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); + } + private JpaRollout refresh(final Rollout rollout) { return rolloutRepository.findById(rollout.getId()).get(); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java index 6b5196186..23d4c60b1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java @@ -402,7 +402,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { final List assignedTargets = targetManagement.assignTag(assignTarget, targetTag.getId()); assertThat(assignedTargets.size()).as("Assigned targets are wrong").isEqualTo(4); assignedTargets.forEach(target -> assertThat( - targetTagManagement.findByTarget(PAGE, target.getControllerId()).getNumberOfElements()).isEqualTo(1)); + getTargetTags(target.getControllerId()).size()).isEqualTo(1)); final TargetTag findTargetTag = targetTagManagement.getByName("Tag1").orElseThrow(IllegalStateException::new); assertThat(assignedTargets.size()).as("Assigned targets are wrong") @@ -410,7 +410,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { final Target unAssignTarget = targetManagement.unassignTag("targetId123", findTargetTag.getId()); assertThat(unAssignTarget.getControllerId()).as("Controller id is wrong").isEqualTo("targetId123"); - assertThat(targetTagManagement.findByTarget(PAGE, unAssignTarget.getControllerId())).as("Tag size is wrong") + assertThat(getTargetTags(unAssignTarget.getControllerId())).as("Tag size is wrong") .isEmpty(); targetTagManagement.getByName("Tag1").orElseThrow(NoSuchElementException::new); assertThat(targetManagement.findByTag(PAGE, targetTag.getId())).as("Assigned targets are wrong").hasSize(3); @@ -569,7 +569,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { */ private void checkTargetHasTags(final boolean strict, final Iterable targets, final TargetTag... tags) { _target: for (final Target tl : targets) { - for (final Tag tt : targetTagManagement.findByTarget(PAGE, tl.getControllerId())) { + for (final Tag tt : getTargetTags(tl.getControllerId())) { for (final Tag tag : tags) { if (tag.getName().equals(tt.getName())) { continue _target; @@ -588,7 +588,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { targetManagement.getByControllerID(tl.getControllerId()).get(); for (final Tag tag : tags) { - for (final Tag tt : targetTagManagement.findByTarget(PAGE, tl.getControllerId())) { + for (final Tag tt : getTargetTags(tl.getControllerId())) { if (tag.getName().equals(tt.getName())) { fail("Target should have no tags"); } @@ -719,16 +719,16 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { final Target t11 = targetManagement.getByControllerID(t1.getControllerId()) .orElseThrow(IllegalStateException::new); - assertThat(targetTagManagement.findByTarget(PAGE, t11.getControllerId()).getContent()).as("Tag size is wrong") + assertThat(getTargetTags(t11.getControllerId())).as("Tag size is wrong") .hasSize(noT1Tags).containsAll(t1Tags); - assertThat(targetTagManagement.findByTarget(PAGE, t11.getControllerId()).getContent()).as("Tag size is wrong") + assertThat(getTargetTags(t11.getControllerId())).as("Tag size is wrong") .hasSize(noT1Tags).doesNotContain(toArray(t2Tags, TargetTag.class)); final Target t21 = targetManagement.getByControllerID(t2.getControllerId()) .orElseThrow(IllegalStateException::new); - assertThat(targetTagManagement.findByTarget(PAGE, t21.getControllerId()).getContent()).as("Tag size is wrong") + assertThat(getTargetTags(t21.getControllerId())).as("Tag size is wrong") .hasSize(noT2Tags).containsAll(t2Tags); - assertThat(targetTagManagement.findByTarget(PAGE, t21.getControllerId()).getContent()).as("Tag size is wrong") + assertThat(getTargetTags(t21.getControllerId())).as("Tag size is wrong") .hasSize(noT2Tags).doesNotContain(toArray(t1Tags, TargetTag.class)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java index 09f16abc6..041fcad7c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java @@ -69,7 +69,7 @@ class TargetTagManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy(() -> targetTagManagement.update(entityFactory.tag().update(NOT_EXIST_IDL)), "TargetTag"); - verifyThrownExceptionBy(() -> targetTagManagement.findByTarget(PAGE, NOT_EXIST_ID), "Target"); + verifyThrownExceptionBy(() -> getTargetTags(NOT_EXIST_ID), "Target"); } @Test @@ -237,7 +237,7 @@ class TargetTagManagementTest extends AbstractJpaIntegrationTest { final TargetTag toDelete = tags.iterator().next(); for (final Target target : targetRepository.findAll()) { - assertThat(targetTagManagement.findByTarget(PAGE, target.getControllerId()).getContent()) + assertThat(getTargetTags(target.getControllerId())) .contains(toDelete); } @@ -246,7 +246,7 @@ class TargetTagManagementTest extends AbstractJpaIntegrationTest { // check for (final Target target : targetRepository.findAll()) { - assertThat(targetTagManagement.findByTarget(PAGE, target.getControllerId()).getContent()) + assertThat(getTargetTags(target.getControllerId())) .doesNotContain(toDelete); } assertThat(targetTagRepository.findById(toDelete.getId())).as("No tag should be found").isNotPresent(); diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResourceTest.java index e9b275c0e..09f5d43e0 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResourceTest.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResourceTest.java @@ -53,8 +53,7 @@ import io.qameta.allure.Story; @Story("Target Tag Resource") public class MgmtTargetTagResourceTest extends AbstractManagementApiIntegrationTest { - private static final String TARGETTAGS_ROOT = "http://localhost" + MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING - + "/"; + private static final String TARGETTAGS_ROOT = "http://localhost" + MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/"; @Test @Description("Verfies that a paged result list of target tags reflects the content on the repository side.") @@ -86,49 +85,9 @@ public class MgmtTargetTagResourceTest extends AbstractManagementApiIntegrationT .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()); } - @Test - @Description("Verifies that a paged result list of target tags reflects on the content of assigned tags for specific controller/target ID") - public void getTargetTagsByTargetId() throws Exception { - final String controllerId1 = "controllerTestId1"; - final String controllerId2 = "controllerTestId2"; - testdataFactory.createTarget(controllerId1); - testdataFactory.createTarget(controllerId2); - - final List tags = testdataFactory.createTargetTags(2, ""); - final TargetTag tag1 = tags.get(0); - final TargetTag tag2 = tags.get(1); - - targetManagement.toggleTagAssignment(List.of(controllerId1, controllerId2), tag1.getName()); - targetManagement.toggleTagAssignment(List.of(controllerId2), tag2.getName()); - - mvc.perform(get(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING) - .queryParam(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "target.controllerId==" + controllerId2) - .accept(MediaType.APPLICATION_JSON)) - .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(applyTagMatcherOnPagedResult(tag1)) - .andExpect(applyTagMatcherOnPagedResult(tag2)) - .andExpect(applySelfLinkMatcherOnPagedResult(tag1, TARGETTAGS_ROOT + tag1.getId())) - .andExpect(applySelfLinkMatcherOnPagedResult(tag2, TARGETTAGS_ROOT + tag2.getId())) - .andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(2))) - .andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(2))) - .andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(2))); - - mvc.perform(get(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING) - .queryParam(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "target.controllerId==" + controllerId1) - .accept(MediaType.APPLICATION_JSON)) - .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(applyTagMatcherOnPagedResult(tag1)) - .andExpect(applySelfLinkMatcherOnPagedResult(tag1, TARGETTAGS_ROOT + tag1.getId())) - .andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(1))) - .andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(1))) - .andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(1))); - } - @Test @Description("Verifies that a page result when listing tags reflects on the content in the repository when filtered by 2 fields - one tag field and one target field") - public void getTargetTagsFilteredByColorAndTargetId() throws Exception { + public void getTargetTagsFilteredByColor() throws Exception { final String controllerId1 = "controllerTestId1"; final String controllerId2 = "controllerTestId2"; testdataFactory.createTarget(controllerId1); @@ -139,21 +98,22 @@ public class MgmtTargetTagResourceTest extends AbstractManagementApiIntegrationT final TargetTag tag2 = tags.get(1); targetManagement.toggleTagAssignment(List.of(controllerId1, controllerId2), tag1.getName()); - targetManagement.toggleTagAssignment(List.of(controllerId2), tag2.getName()); - + targetManagement.toggleTagAssignment(List.of(controllerId2), tag2.getName()) + ; // pass here q directly as a pure string because .queryParam method delimiters the parameters in q with , // which is logical OR, we want AND here mvc.perform(get(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + - "?" + MgmtRestConstants.REQUEST_PARAMETER_SEARCH + "=target.controllerId==" + controllerId2 + ";colour==" + tag1.getColour()) + "?" + MgmtRestConstants.REQUEST_PARAMETER_SEARCH + "=colour==" + tag2.getColour()) .accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(applyTagMatcherOnPagedResult(tag1)) - .andExpect(applySelfLinkMatcherOnPagedResult(tag1, TARGETTAGS_ROOT + tag1.getId())) + .andExpect(applyTagMatcherOnPagedResult(tag2)) + .andExpect(applySelfLinkMatcherOnPagedResult(tag2, TARGETTAGS_ROOT + tag2.getId())) .andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(1))) .andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(1))) .andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(1))); } + @Test @Description("Verfies that a single result of a target tag reflects the content on the repository side.") @ExpectEvents({ @Expect(type = TargetTagCreatedEvent.class, count = 2) })