Feature target type filter (#1197)
* Added Target type filter with drag and drop support Signed-off-by: Anand kumar <anand.kumar@bosch-si.com> * Removed the unused enums and target type filter button class Signed-off-by: Anand kumar <anand.kumar@bosch-si.com> * Resolved merge conflicts Signed-off-by: Anand kumar <anand.kumar@bosch-si.com> * Fixed java doc issue with the method link in the comment Signed-off-by: Anand kumar <anand.kumar@bosch-si.com> * Fixed the IN query overflow for target Type assignment Signed-off-by: Anand kumar <anand.kumar@bosch-si.com> * Fixed Review comments Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>
This commit is contained in:
@@ -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<TargetUpdateStatus> status, final Boolean overdueState,
|
||||
final String searchText, final Long installedOrAssignedDistributionSetId,
|
||||
final Boolean selectTargetWithNoTag, final String... tagNames) {
|
||||
final List<Specification<JpaTarget>> specList = buildSpecificationList(new FilterParams(status, overdueState,
|
||||
searchText, installedOrAssignedDistributionSetId, selectTargetWithNoTag, tagNames));
|
||||
public long countByFilters(Collection<TargetUpdateStatus> 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<Specification<JpaTarget>> 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<Target> findByCriteriaAPI(final Pageable pageable, final List<Specification<JpaTarget>> 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<String> controllerIds, final Long typeId) {
|
||||
final TargetType type = targetTypeRepository.findById(typeId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetType.class, typeId));
|
||||
|
||||
final List<JpaTarget> targetsWithSameType = findTargetsByInSpecification(controllerIds,
|
||||
TargetSpecifications.hasTargetType(typeId));
|
||||
|
||||
final List<JpaTarget> 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<String> controllerIds) {
|
||||
final List<JpaTarget> 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<JpaTarget> findTargetsByInSpecification(Collection<String> controllerIds,
|
||||
Specification<JpaTarget> 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
|
||||
|
||||
@@ -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}.
|
||||
*
|
||||
|
||||
@@ -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<JpaTarget> 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<JpaTarget> hasTargetType() {
|
||||
return (targetRoot, query, cb) -> cb.isNotNull(targetRoot.get(JpaTarget_.targetType));
|
||||
public static Specification<JpaTarget> 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<JpaTarget> 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<JpaTarget> hasTargetTypeNot(final Long typeId) {
|
||||
return (targetRoot, query, cb) -> cb.or(getTargetTypeIsNullPredicate(targetRoot),
|
||||
cb.notEqual(targetRoot.get(JpaTarget_.targetType).get(JpaTargetType_.id), typeId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user