diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFields.java
index ce6b3f391..deca8cd15 100644
--- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFields.java
+++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFields.java
@@ -140,4 +140,4 @@ public enum TargetFields implements FieldNameProvider {
public String getFieldName() {
return fieldName;
}
-}
\ No newline at end of file
+}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/FilterParams.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/FilterParams.java
index 8780cd26f..1bcffebc1 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/FilterParams.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/FilterParams.java
@@ -27,9 +27,11 @@ public class FilterParams {
private final Boolean selectTargetWithNoTag;
private final String[] filterByTagNames;
private final Long filterByDistributionId;
+ private final Boolean selectTargetWithNoTargetType;
+ private final Long filterByTargetType;
/**
- * Constructor.
+ * Constructor for the filter parameters of a Simple Filter.
*
* @param filterByInstalledOrAssignedDistributionSetId
* if set, a filter is added for the given
@@ -56,6 +58,34 @@ public class FilterParams {
this.filterByDistributionId = filterByInstalledOrAssignedDistributionSetId;
this.selectTargetWithNoTag = selectTargetWithNoTag;
this.filterByTagNames = filterByTagNames;
+ this.selectTargetWithNoTargetType = false;
+ this.filterByTargetType = null;
+
+ }
+
+ /**
+ * Constructor for the filter parameters of a Type Filter.
+ *
+ * @param filterBySearchText
+ * if set, a filter is added for the given search text
+ * @param filterByInstalledOrAssignedDistributionSetId
+ * if set, a filter is added for the given
+ * {@link DistributionSet#getId()}
+ * @param selectTargetWithNoType
+ * if true, a filter is added with no type
+ * @param filterByType
+ * if set, a filter is added for the given target type
+ */
+ public FilterParams(final String filterBySearchText, final Long filterByInstalledOrAssignedDistributionSetId,
+ final Boolean selectTargetWithNoType, final Long filterByType) {
+ this.filterBySearchText = filterBySearchText;
+ this.filterByDistributionId = filterByInstalledOrAssignedDistributionSetId;
+ this.filterByStatus = null;
+ this.overdueState = null;
+ this.selectTargetWithNoTag = false;
+ this.filterByTagNames = null;
+ this.selectTargetWithNoTargetType = selectTargetWithNoType;
+ this.filterByTargetType = filterByType;
}
/**
@@ -120,4 +150,23 @@ public class FilterParams {
public String[] getFilterByTagNames() {
return filterByTagNames;
}
+
+ /**
+ * Gets the flag indicating if no target type filter is used.
+ * If set to false this filter is disabled.
+ *
+ * @return the flag indicating if no target type filter is used
+ */
+ public Boolean getSelectTargetWithNoTargetType() {
+ return selectTargetWithNoTargetType;
+ }
+
+ /**
+ * Gets the target type
+ *
+ * @return the target type that are used to filter for
+ */
+ public Long getFilterByTargetType() {
+ return filterByTargetType;
+ }
}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
index 61b942af5..d7bf8348e 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
@@ -8,14 +8,6 @@
*/
package org.eclipse.hawkbit.repository;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import javax.validation.ConstraintViolationException;
-import javax.validation.Valid;
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.TargetCreate;
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
@@ -35,12 +27,22 @@ import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetType;
+import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.security.access.prepost.PreAuthorize;
+import javax.validation.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.
*
@@ -106,11 +108,29 @@ public interface TargetManagement {
*
* @throws EntityNotFoundException
* if distribution set with given ID does not exist
+ *
+ * @deprecated this method {@link TargetManagement#countByFilters(FilterParams)} should be used instead.
*/
+ @Deprecated
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
long countByFilters(Collection status, Boolean overdueState, String searchText,
Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, String... tagNames);
+ /**
+ * Count {@link Target}s for all the given filter parameters.
+ *
+ * @param filterParams
+ * the filters to apply; only filters are enabled that have
+ * non-null value; filters are AND-gated
+ *
+ * @return the found number {@link Target}s
+ *
+ * @throws EntityNotFoundException
+ * if distribution set with given ID does not exist
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ long countByFilters(@NotNull final FilterParams filterParams);
+
/**
* Counts number of targets with given with given distribution set Id
*
@@ -607,6 +627,38 @@ public interface TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetTagAssignmentResult toggleTagAssignment(@NotEmpty Collection controllerIds, @NotEmpty String tagName);
+
+ /**
+ * Initiates {@link TargetType} assignment to given {@link Target}s. If some
+ * targets in the list have the {@link TargetType} not yet assigned, they will
+ * get assigned. If all targets are already of that type, there will be no
+ * un-assignment.
+ *
+ * @param controllerIds
+ * to set the type to
+ * @param typeId
+ * to assign targets to
+ * @return {@link TargetTypeAssignmentResult} with all meta data of the
+ * assignment outcome.
+ *
+ * @throws EntityNotFoundException
+ * if target type with given id does not exist
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
+ TargetTypeAssignmentResult assignType(@NotEmpty Collection controllerIds, @NotNull Long typeId);
+
+ /**
+ * Initiates {@link TargetType} un-assignment to given {@link Target}s. The type
+ * of the targets will be set to {@code null}
+ *
+ * @param controllerIds
+ * to remove the type from
+ * @return {@link TargetTypeAssignmentResult} with all meta data of the
+ * assignment outcome.
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
+ TargetTypeAssignmentResult unAssignType(@NotEmpty Collection controllerIds);
+
/**
* Un-assign a {@link TargetTag} assignment to given {@link Target}.
*
@@ -638,6 +690,8 @@ public interface TargetManagement {
*
* @param controllerID
* to un-assign for
+ * @param targetTypeId
+ * Target type id
* @return the unassigned target
*
* @throws EntityNotFoundException
@@ -854,4 +908,5 @@ public interface TargetManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
TargetMetadata updateMetadata(@NotEmpty String controllerId, @NotNull MetaData metadata);
+
}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetTypeAssignmentResult.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetTypeAssignmentResult.java
new file mode 100644
index 000000000..379f059d3
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetTypeAssignmentResult.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2021 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.model;
+
+import java.util.List;
+
+/**
+ * Result object for {@link TargetType} assignments.
+ *
+ */
+public class TargetTypeAssignmentResult extends AbstractAssignmentResult {
+
+ private final TargetType targetType;
+
+ /**
+ * Constructor.
+ *
+ * @param alreadyAssigned
+ * count of already assigned (ignored) elements
+ * @param assigned
+ * {@link List} of assigned {@link Target}s.
+ * @param unassigned
+ * {@link List} of unassigned {@link Target}s.
+ * @param targetType
+ * the assigned or unassigned tag
+ */
+ public TargetTypeAssignmentResult(final int alreadyAssigned, final List extends Target> assigned,
+ final List extends Target> unassigned, final TargetType targetType) {
+ super(alreadyAssigned, assigned, unassigned);
+ this.targetType = targetType;
+ }
+
+ public TargetType getTargetType() {
+ return targetType;
+ }
+}
diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventType.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventType.java
index fe4b626b7..092d3b129 100644
--- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventType.java
+++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventType.java
@@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetFilterQueryDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetTagDeletedEvent;
+import org.eclipse.hawkbit.repository.event.remote.TargetTypeDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.TenantConfigurationDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
@@ -53,6 +54,8 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetFilterQueryCreat
import org.eclipse.hawkbit.repository.event.remote.entity.TargetFilterQueryUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagUpdatedEvent;
+import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeCreatedEvent;
+import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TenantConfigurationCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TenantConfigurationUpdatedEvent;
@@ -150,6 +153,11 @@ public class EventType {
// rollout stopped due to invalidated distribution set
TYPES.put(43, RolloutStoppedEvent.class);
+
+ // target type
+ TYPES.put(44, TargetTypeCreatedEvent.class);
+ TYPES.put(45, TargetTypeUpdatedEvent.class);
+ TYPES.put(46, TargetTypeDeletedEvent.class);
}
private int value;
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java
index b201da777..9efdb6fab 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java
@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa;
import static org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications.orderedByLinkedDistributionSet;
+import com.google.common.collect.Lists;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
@@ -65,6 +66,7 @@ import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetType;
+import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
@@ -449,11 +451,16 @@ public class JpaTargetManagement implements TargetManagement {
}
@Override
- public long countByFilters(final Collection status, final Boolean overdueState,
- final String searchText, final Long installedOrAssignedDistributionSetId,
- final Boolean selectTargetWithNoTag, final String... tagNames) {
- final List> specList = buildSpecificationList(new FilterParams(status, overdueState,
- searchText, installedOrAssignedDistributionSetId, selectTargetWithNoTag, tagNames));
+ public long countByFilters(Collection status, Boolean overdueState, String searchText,
+ Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag,
+ String... tagNames) {
+ return countByFilters(new FilterParams(status, overdueState, searchText, installedOrAssignedDistributionSetId,
+ selectTargetWithNoTag, tagNames));
+ }
+
+ @Override
+ public long countByFilters(final FilterParams filterParams) {
+ final List> specList = buildSpecificationList(filterParams);
return countByCriteriaAPI(specList);
}
@@ -479,6 +486,13 @@ public class JpaTargetManagement implements TargetManagement {
specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(),
filterParams.getSelectTargetWithNoTag()));
}
+
+ if (hasTypesFilterActive(filterParams)) {
+ specList.add(TargetSpecifications.hasTargetType(filterParams.getFilterByTargetType()));
+ } else if (hasNoTypeFilterActive(filterParams)) {
+ specList.add(TargetSpecifications.hasNoTargetType());
+ }
+
return specList;
}
@@ -490,6 +504,14 @@ public class JpaTargetManagement implements TargetManagement {
return isNoTagActive || isAtLeastOneTagActive;
}
+ private static boolean hasTypesFilterActive(final FilterParams filterParams) {
+ return filterParams.getFilterByTargetType() != null;
+ }
+
+ private static boolean hasNoTypeFilterActive(final FilterParams filterParams) {
+ return Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTargetType());
+ }
+
private Slice findByCriteriaAPI(final Pageable pageable, final List> specList) {
if (CollectionUtils.isEmpty(specList)) {
return convertPage(targetRepository.findAllWithoutCount(pageable), pageable);
@@ -545,6 +567,59 @@ public class JpaTargetManagement implements TargetManagement {
return result;
}
+ @Override
+ @Transactional
+ @Retryable(include = {
+ ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
+ public TargetTypeAssignmentResult assignType(final Collection controllerIds, final Long typeId) {
+ final TargetType type = targetTypeRepository.findById(typeId)
+ .orElseThrow(() -> new EntityNotFoundException(TargetType.class, typeId));
+
+ final List targetsWithSameType = findTargetsByInSpecification(controllerIds,
+ TargetSpecifications.hasTargetType(typeId));
+
+ final List targetsWithoutSameType = findTargetsByInSpecification(controllerIds,
+ TargetSpecifications.hasTargetTypeNot(typeId));
+
+ // set new target type to all targets without that type
+ targetsWithoutSameType.forEach(target -> target.setTargetType(type));
+
+ final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(),
+ Collections
+ .unmodifiableList(targetsWithoutSameType.stream().map(targetRepository::save).collect(Collectors.toList())),
+ Collections.emptyList(), type);
+
+ // no reason to persist the type
+ entityManager.detach(type);
+ return result;
+ }
+
+ @Override
+ @Transactional
+ @Retryable(include = {
+ ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
+ public TargetTypeAssignmentResult unAssignType(final Collection controllerIds) {
+ final List allTargets = findTargetsByInSpecification(controllerIds, null);
+
+ if (allTargets.size() < controllerIds.size()) {
+ throw new EntityNotFoundException(Target.class, controllerIds,
+ allTargets.stream().map(Target::getControllerId).collect(Collectors.toList()));
+ }
+
+ // set new target type to null for all targets
+ allTargets.forEach(target -> target.setTargetType(null));
+
+ return new TargetTypeAssignmentResult(0, Collections.emptyList(), Collections
+ .unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList())), null);
+ }
+
+ private List findTargetsByInSpecification(Collection controllerIds,
+ Specification specification) {
+ return Lists.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream()
+ .map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification)))
+ .flatMap(List::stream).collect(Collectors.toList());
+ }
+
@Override
@Transactional
@Retryable(include = {
@@ -625,7 +700,7 @@ public class JpaTargetManagement implements TargetManagement {
/**
* Applies orderedByLinkedDistributionSet spec for order and adds additional
* specs based on filters
- *
+ *
* @param orderByDistributionId
* distribution set used for order
* @param filterParams
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTypeManagement.java
index 028c9ea83..5f6083a3a 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTypeManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTypeManagement.java
@@ -8,12 +8,6 @@
*/
package org.eclipse.hawkbit.repository.jpa;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.TargetTypeFields;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
@@ -42,9 +36,14 @@ import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.StringUtils;
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}.
*
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 3a30eba3b..de8c79e7b 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
@@ -392,12 +392,16 @@ public final class TargetSpecifications {
return (targetRoot, query, cb) -> {
// Since the targetRoot is changed by joining we need to get the
// isNull predicate first
- final Predicate targetTypeIsNull = targetRoot.get(JpaTarget_.targetType).isNull();
+ final Predicate targetTypeIsNull = getTargetTypeIsNullPredicate(targetRoot);
return cb.or(targetTypeIsNull, cb.equal(getDsTypeIdPath(targetRoot), distributionSetTypeId));
};
}
+ private static Predicate getTargetTypeIsNullPredicate(Root targetRoot) {
+ return targetRoot.get(JpaTarget_.targetType).isNull();
+ }
+
/**
* {@link Specification} for retrieving {@link Target}s that are NOT compatible
* with given {@link DistributionSetType}. Compatibility is evaluated by
@@ -532,13 +536,39 @@ public final class TargetSpecifications {
}
/**
- * {@link Specification} for retrieving {@link Target}s that have a
- * {@link org.eclipse.hawkbit.repository.model.TargetType} assigned
+ * {@link Specification} for retrieving {@link Target}s by target type id
+ *
+ * @param typeId
+ * the id of the target type
*
* @return the {@link Target} {@link Specification}
*/
- public static Specification hasTargetType() {
- return (targetRoot, query, cb) -> cb.isNotNull(targetRoot.get(JpaTarget_.targetType));
+ public static Specification hasTargetType(final long typeId) {
+ return (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.targetType).get(JpaTargetType_.id),
+ typeId);
+ }
+
+ /**
+ * {@link Specification} for retrieving {@link Target}s by target type id is equal to null
+ *
+ * @return the {@link Target} {@link Specification}
+ */
+ public static Specification hasNoTargetType() {
+ return (targetRoot, query, cb) -> cb.isNull(targetRoot.get(JpaTarget_.targetType));
+ }
+
+ /**
+ * {@link Specification} for retrieving {@link Target}s that don't have target
+ * type assigned
+ *
+ * @param typeId
+ * the id of the target type
+ *
+ * @return the {@link Target} {@link Specification}
+ */
+ public static Specification hasTargetTypeNot(final Long typeId) {
+ return (targetRoot, query, cb) -> cb.or(getTargetTypeIsNullPredicate(targetRoot),
+ cb.notEqual(targetRoot.get(JpaTarget_.targetType).get(JpaTargetType_.id), typeId));
}
/**
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 d3c45fa1f..c7957f8e9 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
@@ -26,6 +26,8 @@ import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
+import org.eclipse.hawkbit.repository.model.TargetType;
+import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
import org.eclipse.hawkbit.repository.test.TestConfiguration;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
import org.eclipse.hawkbit.repository.test.util.RolloutTestApprovalStrategy;
@@ -133,4 +135,10 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
return distributionSetManagement.toggleTagAssignment(
sets.stream().map(DistributionSet::getId).collect(Collectors.toList()), tag.getName());
}
+
+ protected TargetTypeAssignmentResult initiateTypeAssignment(final Collection targets, final TargetType type) {
+ return targetManagement.assignType(
+ targets.stream().map(Target::getControllerId).collect(Collectors.toList()), type.getId());
+ }
+
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java
index 667ada5b9..fefe695ae 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java
@@ -58,7 +58,11 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
final TargetTag targTagZ = targetTagManagement.create(entityFactory.tag().create().name("TargTag-Z"));
final TargetTag targTagW = targetTagManagement.create(entityFactory.tag().create().name("TargTag-W"));
- final DistributionSet setA = testdataFactory.createDistributionSet("");
+ final DistributionSet setA = testdataFactory.createDistributionSet("A");
+ final DistributionSet setB = testdataFactory.createDistributionSet("B");
+
+ final TargetType targetTypeX = testdataFactory.createTargetType("TargetTypeX",
+ Collections.singletonList(setB.getType()));
final DistributionSet installedSet = testdataFactory.createDistributionSet("another");
@@ -92,12 +96,17 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
final List targDs = testdataFactory.createTargets(100, targetDsDIdPref,
targetDsDIdPref.concat(" description"), lastTargetNull);
+ final String targetDsEIdPref = "targ-E";
+ final List targEs = testdataFactory.createTargetsWithType(100, targetDsEIdPref, targetTypeX);
+
final String assignedC = targCs.iterator().next().getControllerId();
assignDistributionSet(setA.getId(), assignedC);
final String assignedA = targAs.iterator().next().getControllerId();
assignDistributionSet(setA.getId(), assignedA);
final String assignedB = targBs.iterator().next().getControllerId();
assignDistributionSet(setA.getId(), assignedB);
+ final String assignedE = targEs.iterator().next().getControllerId();
+ assignDistributionSet(setB.getId(), assignedE);
final String installedC = targCs.iterator().next().getControllerId();
final Long actionId = getFirstAssignedActionId(assignDistributionSet(installedSet.getId(), assignedC));
@@ -136,7 +145,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
verifyThat1TargetHasAttributeValue("%c-attribute%", targAttribute.getControllerId());
verifyThat1TargetHasAttributeValue("%" + targAttributeId.getControllerId() + "%",
targAttributeId.getControllerId());
- verifyThatRepositoryContains400Targets();
+ verifyThatRepositoryContains500Targets();
verifyThat200TargetsHaveTagD(targTagW, concat(targBs, targCs));
verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(targTagY, targTagW, targBs);
verifyThat1TargetHasTagHasDescOrNameAndDs(targTagW, setA, targetManagement.getByControllerID(assignedC).get());
@@ -147,19 +156,19 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
verifyThat1TargetWithDescOrNameHasDS(setA, targetManagement.getByControllerID(assignedA).get());
List expected = concat(targAs, targBs, targCs, targDs);
expected.removeAll(targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC)));
- verifyThat397TargetsAreInStatusUnknown(unknown, expected);
+ verifyThat496TargetsAreInStatusUnknown(unknown, expected);
expected = concat(targBs, targCs);
expected.removeAll(targetManagement.getByControllerID(Arrays.asList(assignedB, assignedC)));
verifyThat198TargetsAreInStatusUnknownAndHaveGivenTags(targTagY, targTagW, unknown, expected);
- verfyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(setA, unknown);
+ verifyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(setA, unknown);
expected = concat(targAs);
expected.remove(targetManagement.getByControllerID(assignedA).get());
verifyThat99TargetsWithNameOrDescriptionAreInGivenStatus(unknown, expected);
expected = concat(targBs);
expected.remove(targetManagement.getByControllerID(assignedB).get());
verifyThat99TargetsWithGivenNameOrDescAndTagAreInStatusUnknown(targTagW, unknown, expected);
- verifyThat3TargetsAreInStatusPending(pending,
- targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC)));
+ verifyThat4TargetsAreInStatusPending(pending,
+ targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC, assignedE)));
verifyThat3TargetsWithGivenDSAreInPending(setA, pending,
targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC)));
verifyThat1TargetWithGivenNameOrDescAndDSIsInPending(setA, pending,
@@ -171,8 +180,13 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
verifyThat2TargetsWithGivenTagAreInPending(targTagW, pending,
targetManagement.getByControllerID(Arrays.asList(assignedB, assignedC)));
verifyThat200targetsWithGivenTagAreInStatusPendingorUnknown(targTagW, both, concat(targBs, targCs));
- verfiyThat1TargetAIsInStatusPendingAndHasDSInstalled(installedSet, pending,
+ verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(installedSet, pending,
targetManagement.getByControllerID(installedC).get());
+ verifyThat1TargetHasTypeAndDSAssigned(targetTypeX, setB, targetManagement.getByControllerID(assignedE).get());
+ verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(setA, targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC)));
+ verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(installedSet, targetManagement.getByControllerID(Collections.singletonList(installedC)));
+ verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(targetTypeX, targEs);
+ verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(concat(targAs, targBs, targCs, targDs));
expected = concat(targBs, targCs);
expected.removeAll(targetManagement.getByControllerID(Arrays.asList(assignedB, assignedC)));
@@ -180,354 +194,314 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
}
@Step
- private void verfiyThat1TargetAIsInStatusPendingAndHasDSInstalled(final DistributionSet installedSet,
+ private void verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(final DistributionSet installedSet,
final List pending, final Target expected) {
+ final FilterParams filterParams = new FilterParams(pending, null, null, installedSet.getId(), Boolean.FALSE);
final String query = "updatestatus==pending and installedds.name==" + installedSet.getName();
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(pending, null, null, installedSet.getId(), Boolean.FALSE))
- .getContent())
- .as("has number of elements").hasSize(1).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null,
- installedSet.getId(), Boolean.FALSE)))
- .as("and contains the following elements").containsExactly(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
-
+ 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)))
+ .as("and contains the following elements").containsExactly(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat200targetsWithGivenTagAreInStatusPendingorUnknown(final TargetTag targTagW,
final List both, final List expected) {
+ final FilterParams filterParams = new FilterParams(both, null, null, null, Boolean.FALSE, targTagW.getName());
final String query = "(updatestatus==pending or updatestatus==unknown) and tag==" + targTagW.getName();
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(both, null, null, null, Boolean.FALSE, targTagW.getName()))
- .getContent()).as("has number of elements").hasSize(200)
- .as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(both, null, null, null,
- Boolean.FALSE, targTagW.getName())))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(200).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat2TargetsWithGivenTagAreInPending(final TargetTag targTagW,
final List pending, final List expected) {
+ final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE,
+ targTagW.getName());
final String query = "updatestatus==pending and tag==" + targTagW.getName();
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(pending, null, null, null, Boolean.FALSE, targTagW.getName()))
- .getContent())
- .as("has number of elements").hasSize(2).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, null,
- Boolean.FALSE, targTagW.getName())))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(2).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat2TargetsWithGivenTagAndDSIsInPending(final TargetTag targTagW, final DistributionSet setA,
final List pending, final List expected) {
+ final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE,
+ targTagW.getName());
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ") and tag==" + targTagW.getName();
- assertThat(targetManagement
- .findByFilters(PAGE,
- new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE, targTagW.getName()))
- .getContent())
- .as("has number of elements").hasSize(2).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, setA.getId(),
- Boolean.FALSE, targTagW.getName())))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(2).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat1TargetWithGivenNameOrDescAndTagAndDSIsInPending(final TargetTag targTagW,
final DistributionSet setA, final List pending, final Target expected) {
+ final FilterParams filterParams = new FilterParams(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE,
+ targTagW.getName());
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ") and (name==*targ-B* or description==*targ-B*) and tag==" + targTagW.getName();
- assertThat(targetManagement
- .findByFilters(PAGE,
- new FilterParams(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE, targTagW.getName()))
- .getContent())
- .as("has number of elements").hasSize(1).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, "%targ-B%",
- setA.getId(), Boolean.FALSE, targTagW.getName())))
- .as("and contains the following elements").containsExactly(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ 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)))
+ .as("and contains the following elements").containsExactly(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat1TargetWithGivenNameOrDescAndDSIsInPending(final DistributionSet setA,
final List pending, final Target expected) {
+ final FilterParams filterParams = new FilterParams(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE);
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ") and (name==*targ-A* or description==*targ-A*)";
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE))
- .getContent())
- .as("has number of elements").hasSize(1).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, "%targ-A%",
- setA.getId(), Boolean.FALSE)))
- .as("and contains the following elements").containsExactly(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ 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)))
+ .as("and contains the following elements").containsExactly(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat3TargetsWithGivenDSAreInPending(final DistributionSet setA,
final List pending, final List expected) {
+ final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE);
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ")";
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE)).getContent())
- .as("has number of elements").hasSize(3).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(
- targetManagement.countByFilters(pending, null, null, setA.getId(), Boolean.FALSE)))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(3).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
- private void verifyThat3TargetsAreInStatusPending(final List pending,
+ private void verifyThat4TargetsAreInStatusPending(final List pending,
final List expected) {
+ final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE);
final String query = "updatestatus==pending";
- assertThat(targetManagement.findByFilters(PAGE, new FilterParams(pending, null, null, null, Boolean.FALSE))
- .getContent())
- .as("has number of elements").hasSize(3).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, null,
- Boolean.FALSE, new String[0])))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(4).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat99TargetsWithGivenNameOrDescAndTagAreInStatusUnknown(final TargetTag targTagW,
final List unknown, final List expected) {
+ final FilterParams filterParams = new FilterParams(unknown, null, "%targ-B%", null, Boolean.FALSE,
+ targTagW.getName());
final String query = "updatestatus==unknown and (name==*targ-B* or description==*targ-B*) and tag=="
+ targTagW.getName();
- assertThat(targetManagement
- .findByFilters(PAGE,
- new FilterParams(unknown, null, "%targ-B%", null, Boolean.FALSE, targTagW.getName()))
- .getContent()).as("has number of elements").hasSize(99)
- .as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(unknown, null, "%targ-B%", null,
- Boolean.FALSE, targTagW.getName())))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(99).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat99TargetsWithNameOrDescriptionAreInGivenStatus(final List unknown,
final List expected) {
+ final FilterParams filterParams = new FilterParams(unknown, null, "%targ-A%", null, Boolean.FALSE);
final String query = "updatestatus==unknown and (name==*targ-A* or description==*targ-A*)";
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(unknown, null, "%targ-A%", null, Boolean.FALSE, new String[0]))
- .getContent()).as("has number of elements").hasSize(99)
- .as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(
- targetManagement.countByFilters(unknown, null, "%targ-A%", null, Boolean.FALSE)))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
-
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(99).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
- private void verfyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(final DistributionSet setA,
+ private void verifyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(final DistributionSet setA,
final List unknown) {
+ final FilterParams filterParams = new FilterParams(unknown, null, null, setA.getId(), Boolean.FALSE);
final String query = "updatestatus==unknown and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ")";
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(unknown, null, null, setA.getId(), Boolean.FALSE)).getContent())
- .as("has number of elements").hasSize(0).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(
- targetManagement.countByFilters(unknown, null, null, setA.getId(), Boolean.FALSE)))
- .as("and filter query returns the same result")
- .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(0).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and filter query returns the same result")
+ .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
}
@Step
private void verifyThat198TargetsAreInStatusUnknownAndHaveGivenTags(final TargetTag targTagY,
final TargetTag targTagW, final List unknown, final List expected) {
+ final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE, targTagY.getName(),
+ targTagW.getName());
final String query = "updatestatus==unknown and (tag==" + targTagY.getName() + " or tag==" + targTagW.getName()
+ ")";
- assertThat(targetManagement.findByFilters(PAGE,
- new FilterParams(unknown, null, null, null, Boolean.FALSE, targTagY.getName(), targTagW.getName()))
- .getContent()).as("has number of elements").hasSize(198)
- .as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(unknown, null, null, null,
- Boolean.FALSE, targTagY.getName(), targTagW.getName())))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(198).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
- private void verifyThat397TargetsAreInStatusUnknown(final List unknown,
+ private void verifyThat496TargetsAreInStatusUnknown(final List unknown,
final List expected) {
+ final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE);
final String query = "updatestatus==unknown";
- assertThat(targetManagement.findByFilters(PAGE, new FilterParams(unknown, null, null, null, Boolean.FALSE))
- .getContent()).as("has number of elements").hasSize(397)
- .as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(
- targetManagement.countByFilters(unknown, null, null, null, Boolean.FALSE)))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
-
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(496).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat198TargetsAreInStatusUnknownAndOverdue(final List unknown,
final List expected) {
+ final FilterParams filterParams = new FilterParams(unknown, Boolean.TRUE, null, null, Boolean.FALSE);
// be careful: simple filters are concatenated using AND-gating
final String query = "lastcontrollerrequestat=le=${overdue_ts};updatestatus==UNKNOWN";
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(unknown, Boolean.TRUE, null, null, Boolean.FALSE)).getContent())
- .as("has number of elements").hasSize(198).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(
- targetManagement.countByFilters(unknown, Boolean.TRUE, null, null, Boolean.FALSE)))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(198).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat1TargetWithDescOrNameHasDS(final DistributionSet setA, final Target expected) {
+ final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE);
final String query = "(name==*targ-A* or description==*targ-A*) and (assignedds.name==" + setA.getName()
+ " or installedds.name==" + setA.getName() + ")";
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE))
- .getContent())
- .as("has number of elements").hasSize(1).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(
- targetManagement.countByFilters(null, null, "%targ-A%", setA.getId(), Boolean.FALSE)))
- .as("and contains the following elements").containsExactly(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
-
+ 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)))
+ .as("and contains the following elements").containsExactly(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat3TargetsHaveDSAssigned(final DistributionSet setA, final List expected) {
+ final FilterParams filterParams = new FilterParams(null, null, null, setA.getId(), Boolean.FALSE);
final String query = "assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName();
- assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, null, setA.getId(), Boolean.FALSE))
- .getContent())
- .as("has number of elements").hasSize(3).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(
- targetManagement.countByFilters(null, null, null, setA.getId(), Boolean.FALSE)))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
-
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(3).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat0TargetsWithNameOrdescAndDSHaveTag(final TargetTag targTagX, final DistributionSet setA) {
+ final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE,
+ targTagX.getName());
final String query = "(name==*targ-C* or description==*targ-C*) and tag==" + targTagX.getName()
+ " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")";
- assertThat(targetManagement
- .findByFilters(PAGE,
- new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagX.getName()))
- .getContent())
- .as("has number of elements").hasSize(0).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-C%",
- setA.getId(), Boolean.FALSE, targTagX.getName())))
- .as("and filter query returns the same result")
- .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
-
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(0).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and filter query returns the same result")
+ .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
}
@Step
private void verifyThat0TargetsWithTagAndDescOrNameHasDS(final TargetTag targTagW, final DistributionSet setA) {
+ final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE,
+ targTagW.getName());
final String query = "(name==*targ-A* or description==*targ-A*) and tag==" + targTagW.getName()
+ " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")";
- assertThat(targetManagement
- .findByFilters(PAGE,
- new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, targTagW.getName()))
- .getContent())
- .as("has number of elements").hasSize(0).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-A%",
- setA.getId(), Boolean.FALSE, targTagW.getName())))
- .as("and filter query returns the same result")
- .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
-
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(0).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and filter query returns the same result")
+ .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
}
@Step
private void verifyThat1TargetHasTagHasDescOrNameAndDs(final TargetTag targTagW, final DistributionSet setA,
final Target expected) {
+ final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE,
+ targTagW.getName());
final String query = "(name==*targ-c* or description==*targ-C*) and tag==" + targTagW.getName()
+ " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")";
- assertThat(targetManagement
- .findByFilters(PAGE,
- new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagW.getName()))
- .getContent())
- .as("has number of elements").hasSize(1).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-C%",
- setA.getId(), Boolean.FALSE, targTagW.getName())))
- .as("and contains the following elements").containsExactly(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
-
+ 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)))
+ .as("and contains the following elements").containsExactly(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat1TargetHasNameAndId(final String name, final String controllerId) {
- assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, name, null, Boolean.FALSE))
- .getContent()).as("has number of elements").hasSize(1).as("that number is also returned by count query")
- .hasSize(Ints
- .saturatedCast(targetManagement.countByFilters(null, null, name, null, Boolean.FALSE)));
+ final FilterParams filterParamsByName = new FilterParams(null, null, name, null, Boolean.FALSE);
+ assertThat(targetManagement.findByFilters(PAGE, filterParamsByName).getContent()).as("has number of elements")
+ .hasSize(1).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParamsByName)));
- assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, controllerId, null, Boolean.FALSE))
- .getContent()).as("has number of elements").hasSize(1).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(
- targetManagement.countByFilters(null, null, controllerId, null, Boolean.FALSE)));
+ final FilterParams filterParamsByControllerId = new FilterParams(null, null, controllerId, null, Boolean.FALSE);
+ assertThat(targetManagement.findByFilters(PAGE, filterParamsByControllerId).getContent())
+ .as("has number of elements").hasSize(1).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParamsByControllerId)));
}
@Step
private void verifyThat1TargetHasAttributeValue(final String value, final String controllerId) {
- assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, value, null, Boolean.FALSE))
- .getContent()).as("has number of elements").hasSize(1).as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(
- targetManagement.countByFilters(null, null, value, null, Boolean.FALSE)));
+ final FilterParams filterParams = new FilterParams(null, null, value, null, Boolean.FALSE);
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(1).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)));
}
@Step
private void verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(final TargetTag targTagY,
final TargetTag targTagW, final List expected) {
+ final FilterParams filterParams = new FilterParams(null, null, "%targ-B%", null, Boolean.FALSE,
+ targTagY.getName(), targTagW.getName());
final String query = "(name==*targ-B* or description==*targ-B*) and (tag==" + targTagY.getName() + " or tag=="
+ targTagW.getName() + ")";
- assertThat(targetManagement.findByFilters(PAGE,
- new FilterParams(null, null, "%targ-B%", null, Boolean.FALSE, targTagY.getName(), targTagW.getName()))
- .getContent()).as("has number of elements").hasSize(100)
- .as("that number is also returned by count query")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-B%", null,
- Boolean.FALSE, targTagY.getName(), targTagW.getName())))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
-
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(100).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@SafeVarargs
@@ -539,27 +513,66 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
@Step
private void verifyThat200TargetsHaveTagD(final TargetTag targTagD, final List expected) {
+ final FilterParams filterParams = new FilterParams(null, null, null, null, Boolean.FALSE, targTagD.getName());
final String query = "tag==" + targTagD.getName();
- assertThat(targetManagement
- .findByFilters(PAGE, new FilterParams(null, null, null, null, Boolean.FALSE, targTagD.getName()))
- .getContent()).as("Expected number of results is").hasSize(200)
- .as("and is expected number of results is equal to ")
- .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, null, null,
- Boolean.FALSE, targTagD.getName())))
- .as("and contains the following elements").containsAll(expected)
- .as("and filter query returns the same result")
- .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
-
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("Expected number of results is")
+ .hasSize(200).as("and is expected number of results is equal to ")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected)
+ .as("and filter query returns the same result")
+ .containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
- private void verifyThatRepositoryContains400Targets() {
- assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, null, null, null)).getContent())
- .as("Overall we expect that many targets in the repository").hasSize(400)
+ private void verifyThatRepositoryContains500Targets() {
+ final FilterParams filterParams = new FilterParams(null, null, null, null, null);
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent())
+ .as("Overall we expect that many targets in the repository").hasSize(500)
.as("which is also reflected by repository count").hasSize(Ints.saturatedCast(targetManagement.count()))
.as("which is also reflected by call without specification")
.containsAll(targetManagement.findAll(PAGE).getContent());
+ }
+ @Step
+ private void verifyThat1TargetHasTypeAndDSAssigned(final TargetType type, final DistributionSet set,
+ final Target expected) {
+ final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.FALSE, type.getId());
+ 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)))
+ .as("and contains the following elements").containsExactly(expected);
+ }
+
+ @Step
+ private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set, final List expected) {
+ final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.TRUE, null);
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(expected.size()).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected);
+ }
+
+ @Step
+ private void verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(final TargetType targetType,
+ final List expected) {
+ final FilterParams filterParams = new FilterParams("%targ-E%", null, Boolean.FALSE, targetType.getId());
+ List filteredTargets = targetManagement.findByFilters(PAGE, filterParams).getContent();
+ assertThat(filteredTargets).as("has number of elements").hasSize(100)
+ .as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)));
+ // Comparing the controller ids, as one of the targets was modified, so a 1:1
+ // comparison of the objects is not possible
+ assertThat(filteredTargets.stream().map(Target::getControllerId).collect(Collectors.toList()))
+ .containsAll(expected.stream().map(Target::getControllerId).collect(Collectors.toList()));
+ }
+
+ @Step
+ private void verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(final List expected) {
+ final FilterParams filterParams = new FilterParams("%targ-%", null, Boolean.TRUE, null);
+ assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
+ .hasSize(400).as("that number is also returned by count query")
+ .hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
+ .as("and contains the following elements").containsAll(expected);
}
@Test
@@ -770,4 +783,28 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
.type(type);
return distributionSetManagement.create(dsCreate);
}
+
+ @Test
+ @Description("Verifies that targets with given target type are returned from repository.")
+ public void findTargetByTargetType() {
+ TargetType testType = testdataFactory.createTargetType("testType", Collections.singletonList(standardDsType));
+ List unassigned = testdataFactory.createTargets(9, "unassigned");
+ List assigned = testdataFactory.createTargetsWithType(11, "assigned", testType);
+
+ assertThat(targetManagement.findByFilters(PAGE,
+ new FilterParams(null,null, false, testType.getId())))
+ .as("Contains the targets with set type").containsAll(assigned)
+ .as("and that means the following expected amount").hasSize(11);
+ assertThat(targetManagement.countByFilters(new FilterParams(null,null, false, testType.getId())))
+ .as("Count the targets with set type").isEqualTo(11);
+
+ assertThat(targetManagement.findByFilters(PAGE,
+ new FilterParams(null, null, true, null)))
+ .as("Contains the targets without a type").containsAll(unassigned)
+ .as("and that means the following expected amount").hasSize(9);
+ assertThat(targetManagement.countByFilters(new FilterParams(null, null, true, null)))
+ .as("Counts the targets without a type").isEqualTo(9);
+
+ }
+
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java
index 08a972ba1..bf6323960 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java
@@ -28,6 +28,7 @@ import javax.validation.ConstraintViolationException;
import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.FilterParams;
+import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
@@ -39,6 +40,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreated
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagCreatedEvent;
+import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
@@ -57,6 +59,7 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetType;
+import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
import org.eclipse.hawkbit.repository.test.matcher.Expect;
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
@@ -752,7 +755,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
toggleTagAssignment(tagABCTargets, tagB);
toggleTagAssignment(tagABCTargets, tagC);
- assertThat(targetManagement.countByFilters(null, null, null, null, Boolean.FALSE, "X"))
+ assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "X")))
.as("Target count is wrong").isEqualTo(0);
// search for targets with tag tagA
@@ -782,11 +785,11 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
checkTargetHasNotTags(tagCTargets, tagA, tagB);
// check again target lists refreshed from DB
- assertThat(targetManagement.countByFilters(null, null, null, null, Boolean.FALSE, "A"))
+ assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "A")))
.as("Target count is wrong").isEqualTo(targetWithTagA.size());
- assertThat(targetManagement.countByFilters(null, null, null, null, Boolean.FALSE, "B"))
+ assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "B")))
.as("Target count is wrong").isEqualTo(targetWithTagB.size());
- assertThat(targetManagement.countByFilters(null, null, null, null, Boolean.FALSE, "C"))
+ assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "C")))
.as("Target count is wrong").isEqualTo(targetWithTagC.size());
}
@@ -1107,7 +1110,57 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
assertThat(targetFound1.get().getOptLockRevision()).isEqualTo(2);
assertThat(targetFound1.get().getTargetType().getId()).isEqualTo(targetType.getId());
}
+
+ @Test
+ @WithUser(allSpPermissions = true)
+ @Description("Tests the assignment of types to multiple targets.")
+ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 20),
+ @Expect(type = TargetTypeCreatedEvent.class, count = 2),
+ @Expect(type = TargetUpdatedEvent.class, count = 29), @Expect(type = TargetDeletedEvent.class, count = 1) })
+ public void targetTypeBulkAssignments() {
+ final List typeATargets = testdataFactory.createTargets(10, "typeATargets", "first description");
+ final List typeBTargets = testdataFactory.createTargets(10, "typeBTargets", "first description");
+ // create a target type
+ final TargetType typeA = testdataFactory.createTargetType("A", Collections.singletonList(standardDsType));
+ final TargetType typeB = testdataFactory.createTargetType("B", Collections.singletonList(standardDsType));
+
+ // assign target type to target
+ TargetTypeAssignmentResult resultA = initiateTypeAssignment(typeATargets, typeA);
+ TargetTypeAssignmentResult resultB = initiateTypeAssignment(typeBTargets, typeB);
+ assertThat(resultA.getAssigned()).isEqualTo(10);
+ assertThat(resultB.getAssigned()).isEqualTo(10);
+ checkTargetsHaveType(typeATargets, typeA);
+ checkTargetsHaveType(typeBTargets, typeB);
+
+ // double assignment does not unassign
+ resultA = initiateTypeAssignment(typeATargets, typeA);
+ resultB = initiateTypeAssignment(typeBTargets, typeB);
+ assertThat(resultA.getAssigned()).isZero();
+ assertThat(resultB.getAssigned()).isZero();
+ assertThat(resultA.getAlreadyAssigned()).isEqualTo(10);
+ assertThat(resultB.getAlreadyAssigned()).isEqualTo(10);
+ checkTargetsHaveType(typeATargets, typeA);
+ checkTargetsHaveType(typeBTargets, typeB);
+
+ // verify that type assignment does not throw an error if target list includes an unknown id
+ targetManagement.deleteByControllerID(typeATargets.get(0).getControllerId());
+ final TargetTypeAssignmentResult resultC = initiateTypeAssignment(typeATargets, typeB);
+ assertThat(resultC.getAssigned()).isEqualTo(9);
+ assertThat(resultC.getAlreadyAssigned()).isZero();
+ checkTargetsHaveType(typeATargets, typeB);
+ }
+
+ private void checkTargetsHaveType(final List targets, final TargetType type) {
+ List foundTargets = targetRepository
+ .findAllById(targets.stream().map(Identifiable::getId).collect(Collectors.toList()));
+ for (final Target target : foundTargets) {
+ if (!type.getName().equals(type.getName())) {
+ fail(String.format("Target %s is not of type %s.", target, type));
+ }
+ }
+ }
+
@Test
@Description("Queries and loads the metadata related to a given target.")
public void findAllTargetMetadataByControllerId() {
diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java
index 9ac187b89..42eef3a9c 100644
--- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java
+++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java
@@ -110,7 +110,7 @@ import org.springframework.test.context.TestPropertySource;
public abstract class AbstractIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(AbstractIntegrationTest.class);
- protected static final Pageable PAGE = PageRequest.of(0, 400, Sort.by(Direction.ASC, "id"));
+ protected static final Pageable PAGE = PageRequest.of(0, 500, Sort.by(Direction.ASC, "id"));
protected static final URI LOCALHOST = URI.create("http://127.0.0.1");
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/FormComponentBuilder.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/FormComponentBuilder.java
index 98e3e18bb..93e5e6358 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/FormComponentBuilder.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/FormComponentBuilder.java
@@ -8,9 +8,18 @@
*/
package org.eclipse.hawkbit.ui.common.builder;
+import com.vaadin.data.Binder;
+import com.vaadin.data.Binder.Binding;
+import com.vaadin.data.Binder.BindingBuilder;
+import com.vaadin.data.Validator;
+import com.vaadin.data.ValueProvider;
+import com.vaadin.server.Setter;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.TextArea;
+import com.vaadin.ui.TextField;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
-import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.Type;
import org.eclipse.hawkbit.ui.common.data.aware.ActionTypeAware;
import org.eclipse.hawkbit.ui.common.data.aware.DescriptionAware;
@@ -23,7 +32,6 @@ import org.eclipse.hawkbit.ui.common.data.aware.VersionAware;
import org.eclipse.hawkbit.ui.common.data.providers.AbstractProxyDataProvider;
import org.eclipse.hawkbit.ui.common.data.providers.DistributionSetStatelessDataProvider;
import org.eclipse.hawkbit.ui.common.data.providers.TargetFilterQueryDataProvider;
-import org.eclipse.hawkbit.ui.common.data.providers.TargetTypeDataProvider;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSet;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSetInfo;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetFilterQuery;
@@ -39,17 +47,6 @@ import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.util.StringUtils;
-import com.vaadin.data.Binder;
-import com.vaadin.data.Binder.Binding;
-import com.vaadin.data.Binder.BindingBuilder;
-import com.vaadin.data.Validator;
-import com.vaadin.data.ValueProvider;
-import com.vaadin.server.Setter;
-import com.vaadin.ui.CheckBox;
-import com.vaadin.ui.ComboBox;
-import com.vaadin.ui.TextArea;
-import com.vaadin.ui.TextField;
-
/**
* Builder class for from components
*/
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/TargetManagementFilterParams.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/TargetManagementFilterParams.java
index f95619a58..0c0885b41 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/TargetManagementFilterParams.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/filters/TargetManagementFilterParams.java
@@ -8,18 +8,17 @@
*/
package org.eclipse.hawkbit.ui.common.data.filters;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Objects;
-
+import com.google.common.base.MoreObjects;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.ui.common.data.providers.TargetManagementStateDataProvider;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
-import com.google.common.base.MoreObjects;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
/**
* Filter params for {@link TargetManagementStateDataProvider}.
@@ -35,12 +34,14 @@ public class TargetManagementFilterParams implements Serializable {
private boolean noTagClicked;
private Collection targetTags;
private Long targetFilterQueryId;
+ private boolean noTargetTypeClicked;
+ private Long targetTypeId;
/**
* Constructor for TargetManagementFilterParams to initialize
*/
public TargetManagementFilterParams() {
- this(null, null, Collections.emptyList(), false, null, false, Collections.emptyList(), null);
+ this(null, null, Collections.emptyList(), false, null, false, Collections.emptyList(), null, false, null);
}
/**
@@ -66,7 +67,7 @@ public class TargetManagementFilterParams implements Serializable {
public TargetManagementFilterParams(final Long pinnedDistId, final String searchText,
final Collection targetUpdateStatusList, final boolean overdueState,
final Long distributionId, final boolean noTagClicked, final Collection targetTags,
- final Long targetFilterQueryId) {
+ final Long targetFilterQueryId, final boolean noTargetTypeClicked, final Long targetTypeId) {
this.pinnedDistId = pinnedDistId;
this.searchText = searchText;
this.targetUpdateStatusList = targetUpdateStatusList;
@@ -75,6 +76,8 @@ public class TargetManagementFilterParams implements Serializable {
this.noTagClicked = noTagClicked;
this.targetTags = targetTags;
this.targetFilterQueryId = targetFilterQueryId;
+ this.noTargetTypeClicked = noTargetTypeClicked;
+ this.targetTypeId = targetTypeId;
}
/**
@@ -93,6 +96,8 @@ public class TargetManagementFilterParams implements Serializable {
this.distributionId = filter.getDistributionId();
this.noTagClicked = filter.isNoTagClicked();
this.targetTags = filter.getTargetTags() != null ? new ArrayList<>(filter.getTargetTags()) : null;
+ this.noTargetTypeClicked = filter.isNoTargetTypeClicked();
+ this.targetTypeId = filter.getTargetTypeId();
this.targetFilterQueryId = filter.getTargetFilterQueryId();
}
@@ -119,7 +124,11 @@ public class TargetManagementFilterParams implements Serializable {
}
private boolean isAnyComplexFilterSelected() {
- return distributionId != null || targetFilterQueryId != null;
+ return distributionId != null || targetFilterQueryId != null || isAnyTypeSelected();
+ }
+
+ private boolean isAnyTypeSelected(){
+ return targetTypeId != null || isNoTargetTypeClicked();
}
/**
@@ -278,6 +287,46 @@ public class TargetManagementFilterParams implements Serializable {
this.noTagClicked = noTagClicked;
}
+ /**
+ * Gets the status of no target Type clicked
+ *
+ * @return noTargetTypeClicked true if it is clicked, otherwise
+ * false
+ */
+ public boolean isNoTargetTypeClicked() {
+ return noTargetTypeClicked;
+ }
+
+ /**
+ * Sets the state of no target type filter
+ *
+ * @param noTargetTypeClicked
+ * true if the tag is clicked, otherwise
+ * false
+ */
+ public void setNoTargetTypeClicked(boolean noTargetTypeClicked) {
+ this.noTargetTypeClicked = noTargetTypeClicked;
+ }
+
+ /**
+ * Gets the targetTypeId
+ *
+ * @return targetTypeId for target type filter
+ */
+ public Long getTargetTypeId() {
+ return targetTypeId;
+ }
+
+ /**
+ * Sets the targetType
+ *
+ * @param targetTypeId
+ * Id of targetType
+ */
+ public void setTargetTypeId(Long targetTypeId) {
+ this.targetTypeId = targetTypeId;
+ }
+
// equals requires all fields in condition
@SuppressWarnings("squid:S1067")
@Override
@@ -296,13 +345,15 @@ public class TargetManagementFilterParams implements Serializable {
&& Objects.equals(this.getDistributionId(), other.getDistributionId())
&& Objects.equals(this.isNoTagClicked(), other.isNoTagClicked())
&& Objects.equals(this.getTargetTags(), other.getTargetTags())
- && Objects.equals(this.getTargetFilterQueryId(), other.getTargetFilterQueryId());
+ && Objects.equals(this.getTargetFilterQueryId(), other.getTargetFilterQueryId())
+ && Objects.equals(this.isNoTargetTypeClicked(), other.isNoTargetTypeClicked())
+ && Objects.equals(this.getTargetTypeId(), other.getTargetTypeId());
}
@Override
public int hashCode() {
return Objects.hash(getPinnedDistId(), getSearchText(), getTargetUpdateStatusList(), isOverdueState(),
- getDistributionId(), isNoTagClicked(), getTargetTags(), getTargetFilterQueryId());
+ getDistributionId(), isNoTagClicked(), getTargetTags(), getTargetFilterQueryId(), isNoTargetTypeClicked(), getTargetTypeId());
}
@Override
@@ -311,6 +362,7 @@ public class TargetManagementFilterParams implements Serializable {
.add("searchText", getSearchText()).add("targetUpdateStatusList", getTargetUpdateStatusList())
.add("overdueState", isOverdueState()).add("distributionId", getDistributionId())
.add("noTagClicked", isNoTagClicked()).add("targetTags", getTargetTags())
- .add("targetFilterQueryId", getTargetFilterQueryId()).toString();
+ .add("targetFilterQueryId", getTargetFilterQueryId())
+ .add("noTargetTypeClicked", isNoTargetTypeClicked()).add("targetTypeId", getTargetTypeId()).toString();
}
}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetManagementStateDataProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetManagementStateDataProvider.java
index 945aac3d9..ba85b8604 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetManagementStateDataProvider.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetManagementStateDataProvider.java
@@ -64,6 +64,8 @@ public class TargetManagementStateDataProvider
final boolean noTagClicked = filter.isNoTagClicked();
final String[] targetTags = filter.getTargetTags().toArray(new String[0]);
final Long targetFilterQueryId = filter.getTargetFilterQueryId();
+ final boolean noTargetTypeClicked = filter.isNoTargetTypeClicked();
+ final Long targetTypeId = filter.getTargetTypeId();
if (pinnedDistId != null) {
return targetManagement.findByFilterOrderByLinkedDistributionSet(pageRequest, pinnedDistId,
@@ -76,6 +78,12 @@ public class TargetManagementStateDataProvider
return targetManagement.findByTargetFilterQuery(pageRequest, targetFilterQueryId);
}
+ // Type Filter of Deployment Management view
+ if (targetTypeId != null || noTargetTypeClicked) {
+ return targetManagement.findByFilters(pageRequest, new FilterParams(searchText, distributionId, noTargetTypeClicked, targetTypeId));
+ }
+
+ // Simple Filter of Deployment Management view
return targetManagement.findByFilters(pageRequest, new FilterParams(targetUpdateStatusList, overdueState,
searchText, distributionId, noTagClicked, targetTags));
}
@@ -95,6 +103,8 @@ public class TargetManagementStateDataProvider
final Long distributionId = filter.getDistributionId();
final boolean noTagClicked = filter.isNoTagClicked();
final String[] targetTags = filter.getTargetTags().toArray(new String[0]);
+ final boolean noTargetTypeClicked = filter.isNoTargetTypeClicked();
+ final Long targetTypeId = filter.getTargetTypeId();
final Long targetFilterQueryId = filter.getTargetFilterQueryId();
if (filter.isAnyFilterSelected()) {
@@ -102,8 +112,14 @@ public class TargetManagementStateDataProvider
return targetManagement.countByTargetFilterQuery(targetFilterQueryId);
}
- return targetManagement.countByFilters(targetUpdateStatusList, overdueState, searchText, distributionId,
- noTagClicked, targetTags);
+ // Type Filter of Deployment Management view
+ if (targetTypeId != null || noTargetTypeClicked) {
+ return targetManagement.countByFilters(new FilterParams(searchText, distributionId, noTargetTypeClicked, targetTypeId));
+ }
+
+ // Simple Filter of Deployment Management view
+ return targetManagement.countByFilters(new FilterParams(targetUpdateStatusList, overdueState, searchText, distributionId,
+ noTagClicked, targetTags));
}
return targetManagement.count();
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetTypeDataProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetTypeDataProvider.java
index ae0b230bf..97eae1327 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetTypeDataProvider.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/data/providers/TargetTypeDataProvider.java
@@ -31,6 +31,14 @@ public class TargetTypeDataProvider
private static final long serialVersionUID = 1L;
private final transient TargetTypeManagement targetTypeManagement;
+ /**
+ * Constructor
+ *
+ * @param targetTypeManagement
+ * TargetTypeManagement
+ * @param mapper
+ * Mapper
+ */
public TargetTypeDataProvider(final TargetTypeManagement targetTypeManagement, IdentifiableEntityToProxyIdentifiableEntityMapper mapper) {
super(mapper, Sort.by(Direction.ASC, "name"));
this.targetTypeManagement = targetTypeManagement;
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/event/FilterType.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/event/FilterType.java
index ff64c5f4a..b075dc4f4 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/event/FilterType.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/event/FilterType.java
@@ -12,5 +12,5 @@ package org.eclipse.hawkbit.ui.common.event;
* Enum constants for filter type
*/
public enum FilterType {
- SEARCH, TYPE, TARGET_TYPE, TAG, NO_TAG, STATUS, OVERDUE, QUERY, DISTRIBUTION, MASTER;
+ SEARCH, TYPE, TAG, NO_TAG, TARGET_TYPE, NO_TARGET_TYPE, STATUS, OVERDUE, QUERY, DISTRIBUTION, MASTER;
}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractTargetTypeFilterButtons.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractTargetTypeFilterButtons.java
index 8663b075f..436b4f735 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractTargetTypeFilterButtons.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractTargetTypeFilterButtons.java
@@ -9,8 +9,7 @@
package org.eclipse.hawkbit.ui.common.filterlayout;
import com.vaadin.ui.Button;
-import java.util.Collection;
-import java.util.Map;
+import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
@@ -20,47 +19,57 @@ import org.eclipse.hawkbit.ui.common.event.EventView;
import org.eclipse.hawkbit.ui.common.event.FilterChangedEventPayload;
import org.eclipse.hawkbit.ui.common.event.FilterType;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterButtonClickBehaviour.ClickBehaviourType;
-import org.eclipse.hawkbit.ui.common.state.TagFilterLayoutUiState;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUITagButtonStyle;
+import org.eclipse.hawkbit.ui.management.targettag.filter.TargetTagFilterLayoutUiState;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
-import org.springframework.util.CollectionUtils;
+
+import java.util.Collection;
/**
- * Class for defining the type filter buttons.
+ * Class for defining the target type filter buttons.
*/
public abstract class AbstractTargetTypeFilterButtons extends AbstractFilterButtons {
private static final long serialVersionUID = 1L;
- private final TagFilterLayoutUiState tagFilterLayoutUiState;
-
+ private final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState;
protected final UINotification uiNotification;
- private final Button noTargetTypeButton;
-
private final TargetTypeFilterButtonClick targetTypeFilterButtonClick;
+ private final transient TargetTypeManagement targetTypeManagement;
+ private final Button noTargetTypeButton;
+ private boolean preNoTargetTypeBtnState;
/**
* Constructor for AbstractTargetTypeFilterButtons
- *
* @param uiDependencies
* {@link CommonUiDependencies}
- * @param tagFilterLayoutUiState
- * TagFilterLayoutUiState
+ * @param targetTagFilterLayoutUiState
+ * {@link TargetTagFilterLayoutUiState}
+ * @param targetTypeManagement
+ * TargetTypeManagement
*/
protected AbstractTargetTypeFilterButtons(final CommonUiDependencies uiDependencies,
- final TagFilterLayoutUiState tagFilterLayoutUiState) {
+ final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState,
+ final TargetTypeManagement targetTypeManagement) {
super(uiDependencies.getEventBus(), uiDependencies.getI18n(), uiDependencies.getUiNotification(),
uiDependencies.getPermChecker());
+ this.preNoTargetTypeBtnState = false;
this.uiNotification = uiDependencies.getUiNotification();
- this.tagFilterLayoutUiState = tagFilterLayoutUiState;
+ this.targetTagFilterLayoutUiState = targetTagFilterLayoutUiState;
+ this.targetTypeManagement = targetTypeManagement;
this.noTargetTypeButton = buildNoTargetTypeButton();
this.targetTypeFilterButtonClick = new TargetTypeFilterButtonClick(this::onFilterChangedEvent);
}
+ @Override
+ protected TargetTypeFilterButtonClick getFilterButtonClickBehaviour() {
+ return targetTypeFilterButtonClick;
+ }
+
private Button buildNoTargetTypeButton() {
final Button noTargetType = SPUIComponentProvider.getButton(
getFilterButtonIdPrefix() + "." + SPUIDefinitions.NO_TARGET_TYPE_BUTTON_ID,
@@ -71,24 +80,51 @@ public abstract class AbstractTargetTypeFilterButtons extends AbstractFilterButt
final ProxyTargetType proxyTargetType = new ProxyTargetType();
proxyTargetType.setNoTargetType(true);
+ noTargetType.addClickListener(event -> getFilterButtonClickBehaviour().processFilterClick(proxyTargetType));
+
+ noTargetType.addStyleName("filter-drop-hint-layout");
return noTargetType;
}
- @Override
- protected TargetTypeFilterButtonClick getFilterButtonClickBehaviour(){
- return targetTypeFilterButtonClick;
+ /**
+ * @return the noTargetType Button component
+ */
+ public Button getNoTargetTypeButton() {
+ return noTargetTypeButton;
}
- private void onFilterChangedEvent(final ProxyTargetType targetType,
- final ClickBehaviourType clickType) {
- final Long targetTypeId = ClickBehaviourType.CLICKED == clickType ? targetType.getId()
+ private void onFilterChangedEvent(ProxyTargetType proxyTargetType, ClickBehaviourType clickType) {
+ getDataCommunicator().reset();
+
+ final boolean isNoTargetTypeActive = proxyTargetType.isNoTargetType() && clickType == ClickBehaviourType.CLICKED;
+
+ if (isNoTargetTypeActive) {
+ getNoTargetTypeButton().addStyleName(SPUIStyleDefinitions.SP_NO_TAG_BTN_CLICKED_STYLE);
+ } else {
+ getNoTargetTypeButton().removeStyleName(SPUIStyleDefinitions.SP_NO_TAG_BTN_CLICKED_STYLE);
+ }
+
+ if (preNoTargetTypeBtnState != isNoTargetTypeActive){
+ publishNoTargetTypeChangedEvent(isNoTargetTypeActive);
+ }
+
+ final Long targetTypeId = ClickBehaviourType.CLICKED == clickType ? proxyTargetType.getId()
: null;
publishFilterChangedEvent(targetTypeId);
+ preNoTargetTypeBtnState = isNoTargetTypeActive;
+ }
+
+ private void publishNoTargetTypeChangedEvent(final boolean isNoTargetTypeActivated) {
+ eventBus.publish(EventTopics.FILTER_CHANGED, this, new FilterChangedEventPayload<>(ProxyTarget.class,
+ FilterType.NO_TARGET_TYPE, isNoTargetTypeActivated, EventView.DEPLOYMENT));
+ targetTagFilterLayoutUiState.setNoTargetTypeClicked(isNoTargetTypeActivated);
}
private void publishFilterChangedEvent(final Long targetTypeId) {
eventBus.publish(EventTopics.FILTER_CHANGED, this, new FilterChangedEventPayload<>(ProxyTarget.class,
FilterType.TARGET_TYPE, targetTypeId, EventView.DEPLOYMENT));
+
+ targetTagFilterLayoutUiState.setClickedTargetTypeFilterId(targetTypeId);
}
/**
@@ -105,52 +141,92 @@ public abstract class AbstractTargetTypeFilterButtons extends AbstractFilterButt
*/
protected abstract EventView getView();
- /**
- * Target type deletion operation.
- *
- * @param targetTypeToDelete
- * target type to delete
- *
- * @return true if target type is deleted, in error case false.
- */
- protected abstract boolean deleteTargetType(final ProxyTargetType targetTypeToDelete);
/**
- * @return Button component of no target type
+ * Type deletion operation.
+ *
+ * @param typeToDelete
+ * target type to delete
+ * @return true if delete target type has no exception
*/
- public Button getNoTargetTypeButton() {
- return noTargetTypeButton;
- }
+ protected abstract boolean deleteTargetType(final ProxyTargetType typeToDelete);
@Override
public void restoreState() {
- final Map targetTypesToRestore = tagFilterLayoutUiState.getClickedTagIdsWithName();
+ final Long targetFilterTypeIdToRestore = targetTagFilterLayoutUiState.getClickedTargetTypeFilterId();
- if (!CollectionUtils.isEmpty(targetTypesToRestore)) {
- removeNonExistingTargetTypes(targetTypesToRestore);
+ if (targetFilterTypeIdToRestore != null) {
+ if (targetTypeExists(targetFilterTypeIdToRestore)) {
+ targetTypeFilterButtonClick
+ .setPreviouslyClickedFilterId(targetTagFilterLayoutUiState.getClickedTargetTypeFilterId());
+ } else {
+ targetTagFilterLayoutUiState.setClickedTargetTypeFilterId(null);
+ }
}
- if (tagFilterLayoutUiState.isNoTagClicked()) {
+ if (targetTagFilterLayoutUiState.isNoTargetTypeClicked()) {
getNoTargetTypeButton().addStyleName(SPUIStyleDefinitions.SP_NO_TAG_BTN_CLICKED_STYLE);
}
}
- private void removeNonExistingTargetTypes(final Map targetTypeIdsWithName) {
- final Collection targetTypeIds = targetTypeIdsWithName.keySet();
- final Collection existingTargetTypeIds = filterExistingTargetTypeIds(targetTypeIds);
- if (targetTypeIds.size() != existingTargetTypeIds.size()) {
- targetTypeIds.retainAll(existingTargetTypeIds);
+ /**
+ * Reset filter on target type updated
+ *
+ * @param updatedTargetTypeIds
+ * Collections of updated target type Ids
+ */
+ public void resetFilterOnTargetTypeUpdated(Collection updatedTargetTypeIds) {
+ if (isClickedTargetTypeInIds(updatedTargetTypeIds)) {
+ publishFilterChangedEvent(targetTypeFilterButtonClick.getPreviouslyClickedFilterId());
}
-
}
/**
- * Filters out non-existant target type by ids.
+ * Reset filter on target type deleted
*
- * @param targetTypeIds
- * provided target type ids
- * @return filtered list of existing target type ids
+ * @param deletedTargetTargetTypeIds
+ * Collections of updated target type Ids
*/
- protected abstract Collection filterExistingTargetTypeIds(final Collection targetTypeIds);
+ public void resetFilterOnTargetTypeDeleted(final Collection deletedTargetTargetTypeIds) {
+ if (isClickedTargetTypeInIds(deletedTargetTargetTypeIds)) {
+ targetTypeFilterButtonClick.setPreviouslyClickedFilterId(null);
+ publishFilterChangedEvent(null);
+ }
+ }
+ private boolean isClickedTargetTypeInIds(final Collection targetTypeIds) {
+ final Long clickedTargetTypeId = targetTypeFilterButtonClick.getPreviouslyClickedFilterId();
+ return clickedTargetTypeId != null && targetTypeIds.contains(clickedTargetTypeId);
+ }
+
+ /**
+ * Reevaluate filter
+ */
+ public void reevaluateFilter() {
+ final Long clickedTargetTypeId = targetTypeFilterButtonClick.getPreviouslyClickedFilterId();
+
+ if (clickedTargetTypeId != null && !targetTypeExists(clickedTargetTypeId)) {
+ targetTypeFilterButtonClick.setPreviouslyClickedFilterId(null);
+ publishFilterChangedEvent(null);
+ }
+ }
+
+ private boolean targetTypeExists(Long targetTypeId) {
+ return targetTypeManagement.get(targetTypeId).isPresent();
+ }
+
+ /**
+ * Remove applied target type filter
+ */
+ public void clearAppliedTargetTypeFilter() {
+ if (targetTagFilterLayoutUiState.isNoTargetTypeClicked()) {
+ targetTagFilterLayoutUiState.setNoTargetTypeClicked(false);
+ getNoTargetTypeButton().removeStyleName(SPUIStyleDefinitions.SP_NO_TAG_BTN_CLICKED_STYLE);
+ }
+
+ if (targetTypeFilterButtonClick.getPreviouslyClickedFilterId() != null) {
+ targetTypeFilterButtonClick.setPreviouslyClickedFilterId(null);
+ targetTagFilterLayoutUiState.setClickedTargetTypeFilterId(null);
+ }
+ }
}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/TargetTypeFilterButtonClick.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/TargetTypeFilterButtonClick.java
index b2e82cbbe..be009b584 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/TargetTypeFilterButtonClick.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/TargetTypeFilterButtonClick.java
@@ -17,24 +17,61 @@ import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
public class TargetTypeFilterButtonClick extends AbstractFilterSingleButtonClick {
private static final long serialVersionUID = 1L;
+ private boolean noTargetTypeBtnClicked;
+
private final transient BiConsumer filterChangedCallback;
- TargetTypeFilterButtonClick(final BiConsumer filterChangedCallback) {
+ /**
+ * Constructor
+ *
+ * @param filterChangedCallback
+ * filterChangedCallback
+ */
+ public TargetTypeFilterButtonClick(
+ final BiConsumer filterChangedCallback) {
this.filterChangedCallback = filterChangedCallback;
+ this.noTargetTypeBtnClicked = false;
+ }
+
+ @Override
+ public void processFilterClick(final ProxyTargetType clickedFilter) {
+ if (isFilterPreviouslyClicked(clickedFilter) || isNoTargetTypePreviouslyClicked(clickedFilter)) {
+ previouslyClickedFilterId = null;
+ filterUnClicked(clickedFilter);
+ } else {
+ previouslyClickedFilterId = clickedFilter.getId();
+ filterClicked(clickedFilter);
+ }
}
@Override
protected void filterUnClicked(ProxyTargetType clickedFilter) {
+ if (clickedFilter.isNoTargetType()){
+ noTargetTypeBtnClicked = false;
+ }
filterChangedCallback.accept(clickedFilter, ClickBehaviourType.UNCLICKED);
}
@Override
protected void filterClicked(ProxyTargetType clickedFilter) {
+ noTargetTypeBtnClicked = clickedFilter.isNoTargetType();
filterChangedCallback.accept(clickedFilter, ClickBehaviourType.CLICKED);
}
@Override
public boolean isFilterPreviouslyClicked(final ProxyTargetType clickedFilter) {
- return false;
+ return (previouslyClickedFilterId != null && previouslyClickedFilterId.equals(clickedFilter.getId()));
}
+
+ private boolean isNoTargetTypePreviouslyClicked(ProxyTargetType clickedFilter) {
+ return clickedFilter.isNoTargetType() && isNoTargetTypeBtnClicked();
+ }
+
+ /**
+ * @return true if no target type button clicked
+ */
+ public boolean isNoTargetTypeBtnClicked() {
+ return noTargetTypeBtnClicked;
+ }
+
}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/AbstractTargetsToTargetTypeAssignmentSupport.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/AbstractTargetsToTargetTypeAssignmentSupport.java
new file mode 100644
index 000000000..8cb6f8c90
--- /dev/null
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/AbstractTargetsToTargetTypeAssignmentSupport.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2021 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.ui.common.grid.support.assignment;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.hawkbit.im.authentication.SpPermission;
+import org.eclipse.hawkbit.ui.SpPermissionChecker;
+import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
+import org.eclipse.hawkbit.ui.common.event.EntityModifiedEventPayload;
+import org.eclipse.hawkbit.ui.common.event.EventTopics;
+import org.vaadin.spring.events.EventBus;
+
+/**
+ * Support for assigning/un-assigning targets to target type.
+ *
+ */
+public abstract class AbstractTargetsToTargetTypeAssignmentSupport extends AssignmentSupport {
+ private final SpPermissionChecker permChecker;
+ private final EventBus.UIEventBus eventBus;
+
+ protected AbstractTargetsToTargetTypeAssignmentSupport(final CommonUiDependencies uiDependencies) {
+ super(uiDependencies.getUiNotification(), uiDependencies.getI18n());
+ this.permChecker = uiDependencies.getPermChecker();
+ this.eventBus = uiDependencies.getEventBus();
+ }
+
+ @Override
+ public List getMissingPermissionsForDrop() {
+ return permChecker.hasUpdateTargetPermission() ? Collections.emptyList()
+ : Collections.singletonList(SpPermission.UPDATE_TARGET);
+ }
+
+ protected void publishTypeAssignmentEvent(final List sourceItemsToAssign) {
+ final List assignedTargetIds = sourceItemsToAssign.stream().map(ProxyIdentifiableEntity::getId)
+ .collect(Collectors.toList());
+ eventBus.publish(EventTopics.ENTITY_MODIFIED, this,
+ new EntityModifiedEventPayload(EntityModifiedEventPayload.EntityModifiedEventType.ENTITY_UPDATED,
+ ProxyTarget.class, assignedTargetIds));
+ }
+}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/TargetsToNoTargetTypeAssignmentSupport.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/TargetsToNoTargetTypeAssignmentSupport.java
new file mode 100644
index 000000000..eee84202d
--- /dev/null
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/TargetsToNoTargetTypeAssignmentSupport.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) 2021 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.ui.common.grid.support.assignment;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.hawkbit.repository.TargetManagement;
+import org.eclipse.hawkbit.repository.model.AbstractAssignmentResult;
+import org.eclipse.hawkbit.repository.model.Target;
+import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
+import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * Support for un-assigning the {@link ProxyTarget} items from a {@link ProxyTargetType}.
+ *
+ */
+public class TargetsToNoTargetTypeAssignmentSupport extends AbstractTargetsToTargetTypeAssignmentSupport {
+ private final TargetManagement targetManagement;
+
+ private static final String CAPTION_TYPE = "caption.type";
+ private static final String CAPTION_TARGET = "caption.target";
+
+ /**
+ * Constructor for TargetsToTargetTypeAssignmentSupport
+ *
+ * @param uiDependencies
+ * {@link CommonUiDependencies}
+ * @param targetManagement
+ * TargetManagement
+ */
+ public TargetsToNoTargetTypeAssignmentSupport(final CommonUiDependencies uiDependencies,
+ final TargetManagement targetManagement) {
+ super(uiDependencies);
+ this.targetManagement = targetManagement;
+ }
+
+ @Override
+ protected void performAssignment(List sourceItemsToAssign, ProxyTargetType targetItem) {
+ if (hasRequiredPermissions()) {
+ final AbstractAssignmentResult typesAssignmentResult = initiateTargetTypeUnAssignment(
+ sourceItemsToAssign);
+
+ final String assignmentMsg = createAssignmentMessage(typesAssignmentResult, i18n.getMessage(CAPTION_TARGET),
+ i18n.getMessage(CAPTION_TYPE), "");
+ notification.displaySuccess(assignmentMsg);
+
+ publishTypeAssignmentEvent(sourceItemsToAssign);
+ }
+ }
+
+ /**
+ *
+ * @return false if required permissions are missing
+ */
+ private boolean hasRequiredPermissions() {
+ final List requiredPermissions = getMissingPermissionsForDrop();
+ if (!CollectionUtils.isEmpty(requiredPermissions)) {
+ notification
+ .displayValidationError(i18n.getMessage(UIMessageIdProvider.MESSAGE_ERROR_PERMISSION_INSUFFICIENT, requiredPermissions));
+ return false;
+ }
+ return true;
+ }
+
+ protected AbstractAssignmentResult initiateTargetTypeUnAssignment(final List sourceItems) {
+ final Collection controllerIdsToAssign = sourceItems.stream().map(ProxyTarget::getControllerId)
+ .collect(Collectors.toList());
+
+ return targetManagement.unAssignType(controllerIdsToAssign);
+ }
+
+}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/TargetsToTargetTypeAssignmentSupport.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/TargetsToTargetTypeAssignmentSupport.java
new file mode 100644
index 000000000..73e49f6f4
--- /dev/null
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/TargetsToTargetTypeAssignmentSupport.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2021 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.ui.common.grid.support.assignment;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.eclipse.hawkbit.repository.TargetManagement;
+import org.eclipse.hawkbit.repository.model.AbstractAssignmentResult;
+import org.eclipse.hawkbit.repository.model.Target;
+import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
+import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
+
+/**
+ * Support for assigning the {@link ProxyTarget} items to {@link ProxyTargetType}.
+ *
+ */
+public class TargetsToTargetTypeAssignmentSupport extends AbstractTargetsToTargetTypeAssignmentSupport {
+ private final TargetManagement targetManagement;
+
+ private static final String CAPTION_TYPE = "caption.type";
+ private static final String CAPTION_TARGET = "caption.target";
+
+ /**
+ * Constructor for TargetsToTargetTypeAssignmentSupport
+ *
+ * @param uiDependencies
+ * {@link CommonUiDependencies}
+ * @param targetManagement
+ * TargetManagement
+ */
+ public TargetsToTargetTypeAssignmentSupport(final CommonUiDependencies uiDependencies, final TargetManagement targetManagement) {
+ super(uiDependencies);
+ this.targetManagement = targetManagement;
+ }
+
+ @Override
+ protected List getFilteredSourceItems(List sourceItemsToAssign, ProxyTargetType targetItem) {
+ if (!isAssignmentValid(sourceItemsToAssign, targetItem)) {
+ return Collections.emptyList();
+ }
+
+ return sourceItemsToAssign;
+ }
+
+ /**
+ *
+ * @param sourceItemsToAssign
+ * @param targetItem
+ * @return false if some targets already have a type assigned
+ */
+ private boolean isAssignmentValid(List sourceItemsToAssign, ProxyTargetType targetItem) {
+ if(sourceItemsToAssign.size() > 1) {
+ List targetsWithDifferentType = sourceItemsToAssign.stream().filter(
+ target -> target.getTypeInfo() != null && !target.getTypeInfo().getId().equals(targetItem.getId()))
+ .collect(Collectors.toList());
+
+ if (!targetsWithDifferentType.isEmpty()) {
+ notification.displayValidationError(i18n.getMessage(UIMessageIdProvider.MESSAGE_TARGET_TARGETTYPE_ASSIGNED));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ protected void performAssignment(final List sourceItemsToAssign, final ProxyTargetType targetItem) {
+ final Long typeId = targetItem.getId();
+
+ final AbstractAssignmentResult typesAssignmentResult = initiateTargetTypeAssignment(sourceItemsToAssign,
+ typeId);
+
+ final String assignmentMsg = createAssignmentMessage(typesAssignmentResult,
+ i18n.getMessage(CAPTION_TARGET),
+ i18n.getMessage(CAPTION_TYPE), targetItem.getName());
+ notification.displaySuccess(assignmentMsg);
+
+ publishTypeAssignmentEvent(sourceItemsToAssign);
+ }
+
+ private AbstractAssignmentResult initiateTargetTypeAssignment(final List sourceItems,
+ final Long typeId) {
+ final Collection controllerIdsToAssign = sourceItems.stream().map(ProxyTarget::getControllerId)
+ .collect(Collectors.toList());
+
+ return targetManagement.assignType(controllerIdsToAssign, typeId);
+ }
+
+}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/TypeToTargetAssignmentSupport.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/TypeToTargetAssignmentSupport.java
new file mode 100644
index 000000000..995468a3d
--- /dev/null
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/support/assignment/TypeToTargetAssignmentSupport.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2021 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.ui.common.grid.support.assignment;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.hawkbit.im.authentication.SpPermission;
+import org.eclipse.hawkbit.repository.TargetManagement;
+import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
+import org.eclipse.hawkbit.ui.SpPermissionChecker;
+import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
+import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
+import org.eclipse.hawkbit.ui.common.event.EntityModifiedEventPayload;
+import org.eclipse.hawkbit.ui.common.event.EventTopics;
+import org.vaadin.spring.events.EventBus;
+
+/**
+ * Support for assigning the {@link ProxyTargetType} items to {@link ProxyTarget}.
+ *
+ */
+public class TypeToTargetAssignmentSupport extends AssignmentSupport {
+
+ private final TargetManagement targetManagement;
+ private final EventBus.UIEventBus eventBus;
+ private final SpPermissionChecker permChecker;
+
+ private static final String CAPTION_TYPE = "caption.type";
+ private static final String CAPTION_TARGET = "caption.target";
+
+ /**
+ * Constructor for TypeToTargetAssignmentSupport
+ *
+ * @param uiDependencies
+ * {@link CommonUiDependencies}
+ * @param targetManagement
+ * TargetManagement
+ */
+ public TypeToTargetAssignmentSupport(final CommonUiDependencies uiDependencies, final TargetManagement targetManagement) {
+ super(uiDependencies.getUiNotification(), uiDependencies.getI18n());
+ this.eventBus = uiDependencies.getEventBus();
+ this.permChecker = uiDependencies.getPermChecker();
+ this.targetManagement = targetManagement;
+ }
+
+ @Override
+ public List getMissingPermissionsForDrop() {
+ return permChecker.hasUpdateTargetPermission() ? Collections.emptyList()
+ : Collections.singletonList(SpPermission.UPDATE_TARGET);
+ }
+
+ @Override
+ protected void performAssignment(List sourceItemsToAssign, ProxyTarget targetItem) {
+ final String controllerId = targetItem.getControllerId();
+ // multi-type assignment is not supported
+ final Long typeId = sourceItemsToAssign.get(0).getId();
+ TargetTypeAssignmentResult targetTypeAssignmentResult = initiateTargetTypeAssignment(typeId, controllerId);
+
+ final String assignmentMsg = createAssignmentMessage(targetTypeAssignmentResult, i18n.getMessage(CAPTION_TARGET),
+ i18n.getMessage(CAPTION_TYPE), sourceItemsToAssign.get(0).getName());
+ notification.displaySuccess(assignmentMsg);
+
+ publishTypeAssignmentEvent(sourceItemsToAssign);
+ }
+
+ protected TargetTypeAssignmentResult initiateTargetTypeAssignment(final Long targetType, final String controllerId) {
+ return targetManagement.assignType(Collections.singletonList(controllerId), targetType);
+ }
+
+ protected void publishTypeAssignmentEvent(final List sourceItemsToAssign) {
+ final List assignedTargetIds = sourceItemsToAssign.stream().map(ProxyIdentifiableEntity::getId)
+ .collect(Collectors.toList());
+ eventBus.publish(EventTopics.ENTITY_MODIFIED, this, new EntityModifiedEventPayload(
+ EntityModifiedEventPayload.EntityModifiedEventType.ENTITY_UPDATED, ProxyTarget.class, assignedTargetIds));
+ }
+}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/state/TagFilterLayoutUiState.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/state/TagFilterLayoutUiState.java
index 22d79ae4b..9ecba6f92 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/state/TagFilterLayoutUiState.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/state/TagFilterLayoutUiState.java
@@ -18,8 +18,26 @@ public class TagFilterLayoutUiState extends HidableLayoutUiState {
private static final long serialVersionUID = 1L;
private boolean noTagClicked;
+ private boolean noTargetTypeClicked;
private final Map clickedTagIdsWithName = new HashMap<>();
+ /**
+ * @return True if no targetType is clicked or selected
+ */
+ public boolean isNoTargetTypeClicked() {
+ return noTargetTypeClicked;
+ }
+
+ /**
+ * Sets the status of no targetType clicked
+ *
+ * @param noTargetTypeClicked
+ * boolean
+ */
+ public void setNoTargetTypeClicked(boolean noTargetTypeClicked) {
+ this.noTargetTypeClicked = noTargetTypeClicked;
+ }
+
/**
* @return True if not tag is clicked or selected
*/
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetCountMessageLabel.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetCountMessageLabel.java
index e23b8f7d6..d8bc33586 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetCountMessageLabel.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetCountMessageLabel.java
@@ -134,6 +134,7 @@ public class TargetCountMessageLabel extends AbstractFooterSupport implements Co
appendSearchMsg(filterMessageBuilder, targetFilterParams.getSearchText());
appendDsMsg(filterMessageBuilder, targetFilterParams.getDistributionId());
appendCustomFilterQueryMsg(filterMessageBuilder, targetFilterParams.getTargetFilterQueryId());
+ appendTargetTypeFilterMsg(filterMessageBuilder, targetFilterParams.isNoTargetTypeClicked(), targetFilterParams.getTargetTypeId());
String filterMessage = filterMessageBuilder.toString().trim();
if (filterMessage.endsWith(",")) {
@@ -186,6 +187,12 @@ public class TargetCountMessageLabel extends AbstractFooterSupport implements Co
}
}
+ private void appendTargetTypeFilterMsg(final StringBuilder filterMessageBuilder, boolean noTargetTypeClicked, final Long targetTypeId) {
+ if (targetTypeId != null || noTargetTypeClicked) {
+ appendFilterMsg(filterMessageBuilder, i18n.getMessage("label.filter.target.type"));
+ }
+ }
+
/**
* Update pinning details
*
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGrid.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGrid.java
index fab8d540a..268748a97 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGrid.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGrid.java
@@ -50,6 +50,7 @@ import org.eclipse.hawkbit.ui.common.grid.support.SelectionSupport;
import org.eclipse.hawkbit.ui.common.grid.support.assignment.AssignmentSupport;
import org.eclipse.hawkbit.ui.common.grid.support.assignment.DistributionSetsToTargetAssignmentSupport;
import org.eclipse.hawkbit.ui.common.grid.support.assignment.TargetTagsToTargetAssignmentSupport;
+import org.eclipse.hawkbit.ui.common.grid.support.assignment.TypeToTargetAssignmentSupport;
import org.eclipse.hawkbit.ui.management.dstable.DistributionGridLayoutUiState;
import org.eclipse.hawkbit.ui.management.miscs.DeploymentAssignmentWindowController;
import org.eclipse.hawkbit.ui.management.targettag.filter.TargetTagFilterLayoutUiState;
@@ -157,9 +158,12 @@ public class TargetGrid extends AbstractGrid(this, i18n, uiDependencies.getUiNotification(),
sourceTargetAssignmentStrategies, eventBus));
@@ -263,6 +267,10 @@ public class TargetGrid extends AbstractGrid {
filter.setDistributionId(null);
filter.setNoTagClicked(false);
+ filter.setNoTargetTypeClicked(false);
filter.setOverdueState(false);
filter.setSearchText(null);
filter.setTargetTags(Collections.emptyList());
filter.setTargetUpdateStatusList(Collections.emptyList());
-
+ filter.setTargetTypeId(null);
+ filter.setTargetFilterQueryId(null);
getFilterSupport().refreshFilter();
});
}
- /**
- * Update filter on simple tab selection
- */
- public void onSimpleTabSelected() {
- getFilterSupport().updateFilter(TargetManagementFilterParams::setTargetFilterQueryId, null);
- }
-
@Override
public void addColumns() {
addNameColumn();
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGridHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGridHeader.java
index c55f1dc13..4e85ddf61 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGridHeader.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGridHeader.java
@@ -140,7 +140,8 @@ public class TargetGridHeader extends AbstractEntityGridHeader {
super.restoreState();
if (targetTagFilterLayoutUiState.isCustomFilterTabSelected()) {
- onSimpleFilterReset();
+ onFilterReset();
+ disabledSearchIcon();
}
if (isBulkUploadInProgress()) {
@@ -153,12 +154,10 @@ public class TargetGridHeader extends AbstractEntityGridHeader {
}
/**
- * Reset the distribution set filer drop area support
+ * Reset the distribution set filer drop area support and the search
*/
- public void onSimpleFilterReset() {
+ public void onFilterReset() {
getSearchHeaderSupport().resetSearch();
- getSearchHeaderSupport().disableSearch();
-
distributionSetFilterDropAreaSupport.reset();
}
@@ -248,4 +247,10 @@ public class TargetGridHeader extends AbstractEntityGridHeader {
public void enableSearchIcon() {
getSearchHeaderSupport().enableSearch();
}
+ /**
+ * Disable search icon in the search header
+ */
+ public void disabledSearchIcon() {
+ getSearchHeaderSupport().disableSearch();
+ }
}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGridLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGridLayout.java
index f5cecc62e..6a08e5b95 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGridLayout.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetGridLayout.java
@@ -204,15 +204,21 @@ public class TargetGridLayout extends AbstractGridComponentLayout {
*/
public void onTargetFilterTabChanged(final TargetFilterTabChangedEventPayload eventPayload) {
final boolean isCustomFilterTabSelected = TargetFilterTabChangedEventPayload.CUSTOM == eventPayload;
+ final boolean isTargetTypeFilterTabSelected = TargetFilterTabChangedEventPayload.TARGET_TYPE == eventPayload;
+ final boolean isSimpleTypeFilterTabSelected = TargetFilterTabChangedEventPayload.SIMPLE == eventPayload;
+ targetGridHeader.onFilterReset();
if (isCustomFilterTabSelected) {
- targetGridHeader.onSimpleFilterReset();
- targetGrid.onCustomTabSelected();
- } else {
+ targetGridHeader.disabledSearchIcon();
+ }
+ if(isTargetTypeFilterTabSelected){
+ targetGridHeader.enableSearchIcon();
+ }
+ if (isSimpleTypeFilterTabSelected){
targetGridHeader.enableSearchIcon();
- targetGrid.onSimpleTabSelected();
}
+ targetGrid.resetAllFilters();
countMessageLabel.updateFilteredCount();
}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetWindowLayout.java
index 477522749..76d474730 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetWindowLayout.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetWindowLayout.java
@@ -38,6 +38,8 @@ public class TargetWindowLayout extends AbstractEntityWindowLayout
*
* @param i18n
* I18N
+ * @param targetTypeManagement
+ * TargetTypeManagement
*/
public TargetWindowLayout(final VaadinMessageSource i18n, final TargetTypeManagement targetTypeManagement) {
super();
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/MultipleTargetFilter.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/MultipleTargetFilter.java
index d1d2a5834..c7a122cc4 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/MultipleTargetFilter.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/MultipleTargetFilter.java
@@ -8,12 +8,9 @@
*/
package org.eclipse.hawkbit.ui.management.targettag.filter;
-import com.vaadin.ui.Accordion;
-import com.vaadin.ui.Alignment;
-import com.vaadin.ui.VerticalLayout;
-import com.vaadin.ui.themes.ValoTheme;
import java.util.Arrays;
import java.util.List;
+
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TargetTagManagement;
@@ -40,6 +37,11 @@ import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
+import com.vaadin.ui.Accordion;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.themes.ValoTheme;
+
/**
* Target filter tabsheet with 'simple' and 'complex' filter options.
*/
@@ -77,7 +79,8 @@ public class MultipleTargetFilter extends Accordion {
this.filterByButtons = new TargetTagFilterButtons(uiDependencies, targetTagManagement, targetManagement,
targetTagFilterLayoutUiState, targetTagWindowBuilder);
- this.targetTypeFilterButtons = new TargetTypeFilterButtons(uiDependencies, targetTypeManagement, targetTagFilterLayoutUiState, targetTypeWindowBuilder);
+ this.targetTypeFilterButtons = new TargetTypeFilterButtons(uiDependencies, targetTypeManagement, targetManagement,
+ targetTagFilterLayoutUiState, targetTypeWindowBuilder);
this.filterByStatusFooter = new FilterByStatusLayout(i18n, eventBus, targetTagFilterLayoutUiState);
this.simpleFilterTab = buildSimpleFilterTab();
this.targetTypeFilterTab = buildTargetTypeFilterTab();
@@ -98,8 +101,7 @@ public class MultipleTargetFilter extends Accordion {
this.targetTypeGridActionsVisibilityListener = new GridActionsVisibilityListener(eventBus, layoutViewAware,
targetTypeFilterButtons::hideActionColumns, targetTypeFilterButtons::showEditColumn, targetTypeFilterButtons::showDeleteColumn);
this.entityTargetTypeModifiedListener = new EntityModifiedListener.Builder<>(eventBus, ProxyTargetType.class)
- .parentEntityType(ProxyTarget.class).viewAware(layoutViewAware)
- .entityModifiedAwareSupports(getTargetTypeModifiedAwareSupports()).build();
+ .viewAware(layoutViewAware).entityModifiedAwareSupports(getTargetTypeModifiedAwareSupports()).build();
init();
addTabs();
@@ -165,7 +167,8 @@ public class MultipleTargetFilter extends Accordion {
private List getTargetTypeModifiedAwareSupports() {
return Arrays.asList(EntityModifiedGridRefreshAwareSupport.of(targetTypeFilterButtons::refreshAll),
- EntityModifiedGenericSupport.of(null, null, null));
+ EntityModifiedGenericSupport.of(null, targetTypeFilterButtons::resetFilterOnTargetTypeUpdated,
+ targetTypeFilterButtons::resetFilterOnTargetTypeDeleted));
}
private List getFilterQueryModifiedAwareSupports() {
@@ -191,9 +194,9 @@ public class MultipleTargetFilter extends Accordion {
public void selectedTabChanged() {
final String selectedTabId = getTab(getSelectedTab()).getId();
-
if (UIComponentIdProvider.SIMPLE_FILTER_ACCORDION_TAB.equals(selectedTabId)) {
customFilterTab.clearAppliedTargetFilterQuery();
+ targetTypeFilterButtons.clearAppliedTargetTypeFilter();
targetTagFilterLayoutUiState.setCustomFilterTabSelected(false);
targetTagFilterLayoutUiState.setTargetTypeFilterTabSelected(false);
@@ -201,13 +204,19 @@ public class MultipleTargetFilter extends Accordion {
eventBus.publish(EventTopics.TARGET_FILTER_TAB_CHANGED, this, TargetFilterTabChangedEventPayload.SIMPLE);
}
if (UIComponentIdProvider.TARGET_TYPE_FILTER_ACCORDION_TAB.equals(selectedTabId)){
+ customFilterTab.clearAppliedTargetFilterQuery();
+ filterByButtons.clearTargetTagFilters();
+ filterByStatusFooter.clearStatusAndOverdueFilters();
+
targetTagFilterLayoutUiState.setTargetTypeFilterTabSelected(true);
targetTagFilterLayoutUiState.setCustomFilterTabSelected(false);
+
eventBus.publish(EventTopics.TARGET_FILTER_TAB_CHANGED, this, TargetFilterTabChangedEventPayload.TARGET_TYPE);
}
if (UIComponentIdProvider.CUSTOM_FILTER_ACCORDION_TAB.equals(selectedTabId)){
filterByButtons.clearTargetTagFilters();
filterByStatusFooter.clearStatusAndOverdueFilters();
+ targetTypeFilterButtons.clearAppliedTargetTypeFilter();
targetTagFilterLayoutUiState.setCustomFilterTabSelected(true);
targetTagFilterLayoutUiState.setTargetTypeFilterTabSelected(false);
@@ -223,20 +232,14 @@ public class MultipleTargetFilter extends Accordion {
public void restoreState() {
if (targetTagFilterLayoutUiState.isCustomFilterTabSelected()) {
customFilterTab.restoreState();
-
setSelectedTab(customFilterTab);
- }
- if (targetTagFilterLayoutUiState.isCustomFilterTabSelected()) {
- filterByButtons.restoreState();
- filterByStatusFooter.restoreState();
-
- setSelectedTab(simpleFilterTab);
- }
- if (targetTagFilterLayoutUiState.isTargetTypeFilterTabSelected()) {
- filterByButtons.restoreState();
- filterByStatusFooter.restoreState();
-
+ } else if (targetTagFilterLayoutUiState.isTargetTypeFilterTabSelected()){
+ targetTypeFilterButtons.restoreState();
setSelectedTab(targetTypeFilterTab);
+ } else {
+ filterByButtons.restoreState();
+ filterByStatusFooter.restoreState();
+ setSelectedTab(simpleFilterTab);
}
}
@@ -246,6 +249,7 @@ public class MultipleTargetFilter extends Accordion {
public void onViewEnter() {
filterByButtons.reevaluateFilter();
customFilterTab.reevaluateFilter();
+ targetTypeFilterButtons.reevaluateFilter();
}
/**
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/TargetTagFilterLayoutUiState.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/TargetTagFilterLayoutUiState.java
index 8b80cedab..4c606a694 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/TargetTagFilterLayoutUiState.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/TargetTagFilterLayoutUiState.java
@@ -21,11 +21,19 @@ public class TargetTagFilterLayoutUiState extends TagFilterLayoutUiState {
private static final long serialVersionUID = 1L;
private Long clickedTargetFilterQueryId;
+ private Long clickedTargetTypeFilterId;
private final Collection clickedTargetUpdateStatusFilters = new ArrayList<>();
private boolean isOverdueFilterClicked;
private boolean isCustomFilterTabSelected;
private boolean isTargetTypeFilterTabSelected;
+ public Long getClickedTargetTypeFilterId() {
+ return clickedTargetTypeFilterId;
+ }
+
+ public void setClickedTargetTypeFilterId(Long clickedTargetTypeFilterId) {
+ this.clickedTargetTypeFilterId = clickedTargetTypeFilterId;
+ }
/**
* @return Id of clicked target filter query
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/TargetTypeFilterButtons.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/TargetTypeFilterButtons.java
index 5775d01dd..4f84e5730 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/TargetTypeFilterButtons.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/filter/TargetTypeFilterButtons.java
@@ -8,11 +8,12 @@
*/
package org.eclipse.hawkbit.ui.management.targettag.filter;
+import com.vaadin.ui.Button;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
-import java.util.Collection;
-import java.util.stream.Collectors;
-import org.eclipse.hawkbit.repository.Identifiable;
+import com.vaadin.ui.dnd.DropTargetExtension;
+import com.vaadin.ui.dnd.event.DropEvent;
+import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.exception.TargetTypeInUseException;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
@@ -25,31 +26,59 @@ import org.eclipse.hawkbit.ui.common.event.EntityModifiedEventPayload;
import org.eclipse.hawkbit.ui.common.event.EventTopics;
import org.eclipse.hawkbit.ui.common.event.EventView;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractTargetTypeFilterButtons;
-import org.eclipse.hawkbit.ui.common.state.TagFilterLayoutUiState;
+import org.eclipse.hawkbit.ui.common.grid.support.DragAndDropSupport;
+import org.eclipse.hawkbit.ui.common.grid.support.assignment.AssignmentSupport;
+import org.eclipse.hawkbit.ui.common.grid.support.assignment.TargetsToNoTargetTypeAssignmentSupport;
+import org.eclipse.hawkbit.ui.common.grid.support.assignment.TargetsToTargetTypeAssignmentSupport;
+import org.eclipse.hawkbit.ui.common.layout.listener.EntityDraggingListener;
import org.eclipse.hawkbit.ui.management.targettag.targettype.TargetTypeWindowBuilder;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
/**
* Target Type filter buttons table.
*/
@SuppressWarnings("squid:S2160")
public class TargetTypeFilterButtons extends AbstractTargetTypeFilterButtons {
private static final long serialVersionUID = 1L;
-
- private final transient TargetTypeManagement targetTypeManagement;
- private final transient TargetTypeWindowBuilder targetTypeWindowBuilder;
-
private static final Logger LOG = LoggerFactory.getLogger(TargetTypeFilterButtons.class);
- TargetTypeFilterButtons(final CommonUiDependencies uiDependencies,
- final TargetTypeManagement targetTypeManagement, final TagFilterLayoutUiState tagFilterLayoutUiState,
- final TargetTypeWindowBuilder targetTypeWindowBuilder) {
- super(uiDependencies, tagFilterLayoutUiState);
+ private final transient TargetManagement targetManagement;
+ private final transient TargetTypeManagement targetTypeManagement;
+ private final transient TargetTypeWindowBuilder targetTypeWindowBuilder;
+ private final transient CommonUiDependencies uiDependencies;
+ private transient EntityDraggingListener draggingListener;
+ TargetTypeFilterButtons(final CommonUiDependencies uiDependencies,
+ final TargetTypeManagement targetTypeManagement, final TargetManagement targetManagement, final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState,
+ final TargetTypeWindowBuilder targetTypeWindowBuilder) {
+ super(uiDependencies, targetTagFilterLayoutUiState, targetTypeManagement);
+
+ this.targetManagement = targetManagement;
this.targetTypeManagement = targetTypeManagement;
this.targetTypeWindowBuilder = targetTypeWindowBuilder;
+ this.uiDependencies = uiDependencies;
+
+ final Map> sourceTargetAssignmentStrategies = new HashMap<>();
+ final TargetsToTargetTypeAssignmentSupport targetsToTargetTypeAssignment = new TargetsToTargetTypeAssignmentSupport(uiDependencies,
+ targetManagement);
+
+ sourceTargetAssignmentStrategies.put(UIComponentIdProvider.TARGET_TABLE_ID, targetsToTargetTypeAssignment);
+
+ setDropSupportToNoType();
+ setDragAndDropSupportSupport(new DragAndDropSupport<>(this, i18n, uiNotification,
+ sourceTargetAssignmentStrategies, eventBus));
+ getDragAndDropSupportSupport().ignoreSelection(true);
+ getDragAndDropSupportSupport().addDragAndDrop();
init();
setDataProvider(
@@ -74,7 +103,17 @@ public class TargetTypeFilterButtons extends AbstractTargetTypeFilterButtons {
@Override
protected boolean deleteFilterButtons(Collection filterButtonsToDelete) {
final ProxyTargetType targetTypeToDelete = filterButtonsToDelete.iterator().next();
- return deleteTargetType(targetTypeToDelete);
+ final String targetTypeToDeleteName = targetTypeToDelete.getName();
+ final Long targetTypeToDeleteId = targetTypeToDelete.getId();
+
+ final Long clickedTargetTypeId = getFilterButtonClickBehaviour().getPreviouslyClickedFilterId();
+
+ if (clickedTargetTypeId != null && clickedTargetTypeId.equals(targetTypeToDeleteId)) {
+ uiNotification.displayValidationError(i18n.getMessage("message.targettype.delete", targetTypeToDeleteName));
+ } else {
+ return deleteTargetType(targetTypeToDelete);
+ }
+ return false;
}
@Override
@@ -113,12 +152,8 @@ public class TargetTypeFilterButtons extends AbstractTargetTypeFilterButtons {
LOG.trace("Target type already in use exception: {}", exception.getMessage());
uiNotification.displayValidationError(i18n.getMessage(exception.getMessage()));
}
- return false;
- }
- @Override
- protected Collection filterExistingTargetTypeIds(Collection targetTypeIds) {
- return targetTypeManagement.get(targetTypeIds).stream().map(Identifiable::getId).collect(Collectors.toSet());
+ return false;
}
@Override
@@ -131,4 +166,43 @@ public class TargetTypeFilterButtons extends AbstractTargetTypeFilterButtons {
return permissionChecker.hasUpdateRepositoryPermission();
}
+ private void setDropSupportToNoType() {
+ final TargetsToNoTargetTypeAssignmentSupport targetsToNoTargetTypeAssignmentSupport = new TargetsToNoTargetTypeAssignmentSupport(
+ uiDependencies, targetManagement);
+
+ final DropTargetExtension