package org.ovirt.engine.core.bll.storage.disk.image;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.ovirt.engine.core.common.businessentities.storage.CinderDisk;
import org.ovirt.engine.core.common.businessentities.storage.Disk;
import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
import org.ovirt.engine.core.common.businessentities.storage.DiskStorageType;
import org.ovirt.engine.core.common.businessentities.storage.LunDisk;
public class DisksFilter {
/**
* A generic {@link Predicate} for filtering {@link Disk}s by their storage type and then casting them
* to the appropriate concrete implementation.
*/
private static class DiskStorageTypePredicate<T extends Disk> implements Predicate<Disk> {
private Class<T> implementingDiskType;
private DiskStorageTypePredicate(Class<T> implementingDiskType) {
this.implementingDiskType = implementingDiskType;
}
@Override
public boolean test(Disk disk) {
return DiskStorageType.forClass(implementingDiskType) == disk.getDiskStorageType();
}
public Class<T> getImplementingDiskType() {
return implementingDiskType;
}
}
/**
* Filters out all disks that are not images.
*/
public static final DiskStorageTypePredicate<DiskImage> ONLY_IMAGES =
new DiskStorageTypePredicate<>(DiskImage.class);
/**
* Filters out all disks that are not Luns.
*/
public static final DiskStorageTypePredicate<LunDisk> ONLY_LUNS = new DiskStorageTypePredicate<>(LunDisk.class);
/**
* Filters out all disks that are not Cinder disks.
*/
public static final DiskStorageTypePredicate<CinderDisk> ONLY_CINDER =
new DiskStorageTypePredicate<>(CinderDisk.class);
/**
* Filters out all disks that are not snapable (retains only disks that we can take a snapshot of).
*/
public static final Predicate<Disk> ONLY_SNAPABLE = Disk::isAllowSnapshot;
/**
* Filters out all disks that are shareable.
*/
public static final Predicate<Disk> ONLY_NOT_SHAREABLE = d -> !d.isShareable();
/**
* Filters out all disks that are not active.
*/
public static final Predicate<Disk> ONLY_ACTIVE = d -> Boolean.TRUE.equals(((DiskImage) d).getActive());
/**
* Filters out all disks that are not plugged.
*/
public static final Predicate<Disk> ONLY_PLUGGED = Disk::getPlugged;
/**
* This method filters a list of disks retaining only disk images and continues to filter the list by the
* specified predicates.
*
* @param disks The collection of disks to filter
* @param predicates The predicates to filter by
* @return A filtered list of disks
*/
public static List<DiskImage> filterImageDisks(Collection<? extends Disk> disks, Predicate<Disk>... predicates) {
return filterDisksByStorageType(disks, ONLY_IMAGES, predicates);
}
/**
* This method filters a list of disks retaining only lun disks and continues to filter the list by the
* specified predicates.
*
* @param disks The collection of disks to filter
* @param predicates The predicates to filter by
* @return A filtered list of disks
*/
public static List<LunDisk> filterLunDisks(Collection<? extends Disk> disks, Predicate<Disk>... predicates) {
return filterDisksByStorageType(disks, ONLY_LUNS, predicates);
}
/**
* This method filters a list of disks retaining only cinder disks and continues to filter the list by the
* specified predicates.
*
* @param disks The collection of disks to filter
* @param predicates The predicates to filter by
* @return A filtered list of disks
*/
public static List<CinderDisk> filterCinderDisks(Collection<? extends Disk> disks, Predicate<Disk>... predicates) {
return filterDisksByStorageType(disks, ONLY_CINDER, predicates);
}
/**
* This method filters a list of disks retaining only disks of a certain storage type and continues to filter the list by
* the specified predicates.
*
* @param disks The collection of disks to filter
* @param storageTypePredicate The predicate that defines the storage type to filter by
* @param predicates The predicates to filter by
* @return A filtered list of disks
*/
private static <T extends Disk> List<T> filterDisksByStorageType
(Collection<? extends Disk> disks, DiskStorageTypePredicate<T> storageTypePredicate, Predicate<Disk>... predicates) {
Predicate<Disk> chain = Stream.concat(Stream.of(storageTypePredicate), Arrays.stream(predicates)).reduce(Predicate::and).orElse(p -> true);
return disks.stream().filter(chain)
.map(storageTypePredicate.getImplementingDiskType()::cast)
.collect(Collectors.toList());
}
}