package org.ovirt.engine.core.bll;

import java.util.ArrayList;
import java.util.List;

import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;

import org.ovirt.engine.core.common.businessentities.ClusterEditWarnings;
import org.ovirt.engine.core.common.businessentities.Nameable;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VDSGroup;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.interfaces.BackendLocal;
import org.ovirt.engine.core.common.queries.ClusterEditParameters;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.dao.VdsDao;
import org.ovirt.engine.core.dao.VmDao;

public class GetClusterEditWarningsQuery<P extends ClusterEditParameters> extends QueriesCommandBase<P> {

    @Inject
    private VdsDao vdsDao;

    @Inject
    private VmDao vmDao;

    @Inject
    @Any
    private Instance<ClusterEditChecker<VDS>> hostCheckers;

    @Inject
    @Any
    private Instance<ClusterEditChecker<VM>> vmCheckers;

    @Inject
    private BackendLocal backend;

    public GetClusterEditWarningsQuery(P parameters) {
        super(parameters);
    }

    @Override
    protected void executeQueryCommand() {
        final VDSGroup oldCluster = backend.runQuery(VdcQueryType.GetVdsGroupById, getParameters()).getReturnValue();
        VDSGroup newCluster = getParameters().getNewCluster();

        List<ClusterEditWarnings.Warning> hostWarnings = getProblematicEntities(oldCluster, newCluster, hostCheckers, new ClusterEntityResolver<VDS>() {
            @Override
            public List<VDS> getClusterEntities(VDSGroup cluster) {
                return vdsDao.getAllForVdsGroup(cluster.getId());
            }
        });

        List<ClusterEditWarnings.Warning> vmWarnings = getProblematicEntities(oldCluster, newCluster, vmCheckers, new ClusterEntityResolver<VM>() {
            @Override
            public List<VM> getClusterEntities(VDSGroup cluster) {
                return vmDao.getAllForVdsGroup(cluster.getId());
            }
        });

        setReturnValue(new ClusterEditWarnings(hostWarnings, vmWarnings));
    }

    private static <T extends Nameable> List<ClusterEditWarnings.Warning> getProblematicEntities(
            VDSGroup oldCluster,
            VDSGroup newCluster,
            Iterable<ClusterEditChecker<T>> checkers,
            ClusterEntityResolver<T> entityResolver) {

        List<ClusterEditWarnings.Warning> warnings = new ArrayList<>();

        List<ClusterEditChecker<T>> checks = getApplicableChecks(oldCluster, newCluster, checkers);
        if (!checks.isEmpty()) {
            List<T> entities = entityResolver.getClusterEntities(oldCluster);
            for (ClusterEditChecker<T> checker : checks) {
                ClusterEditWarnings.Warning warning = new ClusterEditWarnings.Warning(checker.getMainMessage());
                for (T entity : entities) {
                    if (!checker.check(entity)) {
                        warning.getDetailsByName().put(entity.getName(), checker.getDetailMessage(entity));
                    }
                }
                if (!warning.isEmpty()) {
                    warnings.add(warning);
                }
            }
        }

        return warnings;
    }

    private static <T> List<ClusterEditChecker<T>> getApplicableChecks(
            VDSGroup oldCluster,
            VDSGroup newCluster,
            Iterable<ClusterEditChecker<T>> checkers) {

        List<ClusterEditChecker<T>> result = new ArrayList<>();
        for (ClusterEditChecker<T> checker : checkers) {
            if (checker.isApplicable(oldCluster, newCluster)) {
                result.add(checker);
            }
        }

        return result;
    }

    private interface ClusterEntityResolver<T> {
        List<T> getClusterEntities(VDSGroup cluster);
    }
}

@@ -29,16 +29,120 @@
 e.bll;%0A%0A
+import static java.util.stream.Collectors.toList;%0Aimport static java.util.stream.StreamSupport.stream;%0A%0A
 import j
@@ -1716,156 +1716,35 @@
 ers,
- new ClusterEntityResolver%3CVDS%3E() %7B%0A            @Override%0A            public List%3CVDS%3E getClusterEntities(VDSGroup cluster) %7B%0A                return
+%0A                cluster -%3E
  vds
@@ -1785,33 +1785,8 @@
 d())
-;%0A            %7D%0A        %7D
 );%0A%0A
@@ -1902,154 +1902,35 @@
 ers,
- new ClusterEntityResolver%3CVM%3E() %7B%0A            @Override%0A            public List%3CVM%3E getClusterEntities(VDSGroup cluster) %7B%0A                return
+%0A                cluster -%3E
  vmD
@@ -1970,33 +1970,8 @@
 d())
-;%0A            %7D%0A        %7D
 );%0A%0A
@@ -2439,20 +2439,110 @@
 T%3E%3E 
-checks = get
+applicableChecks = stream(checkers.spliterator(), false)%0A                .filter(checker -%3E checker.is
 Appl
@@ -2547,22 +2547,16 @@
 plicable
-Checks
 (oldClus
@@ -2574,21 +2574,48 @@
 ster
-, checkers
+))%0A                .collect(toList()
 );%0A
+%0A
     
@@ -2619,25 +2619,35 @@
        if (!
-c
+applicableC
 hecks.isEmpt
@@ -2776,25 +2776,35 @@
 %3E checker : 
-c
+applicableC
 hecks) %7B%0A   
@@ -2933,60 +2933,43 @@
     
-for (T entity : entities) %7B%0A                    if (
+entities.stream().filter(entity -%3E 
 !che
@@ -2987,18 +2987,34 @@
 entity))
- %7B
+.forEach(entity -%3E
 %0A       
@@ -3116,50 +3116,11 @@
 ty))
+)
 ;%0A
-                    %7D%0A                %7D%0A
     
@@ -3283,475 +3283,28 @@
     
-private static %3CT%3E List%3CClusterEditChecker%3CT%3E%3E getApplicableChecks(%0A            VDSGroup oldCluster,%0A            VDSGroup newCluster,%0A            Iterable%3CClusterEditChecker%3CT%3E%3E checkers) %7B%0A%0A        List%3CClusterEditChecker%3CT%3E%3E result = new ArrayList%3C%3E();%0A        for (ClusterEditChecker%3CT%3E checker : checkers) %7B%0A            if (checker.isApplicable(oldCluster, newCluster)) %7B%0A                result.add(checker);%0A            %7D%0A        %7D%0A%0A        return result;%0A    %7D%0A
+@FunctionalInterface
 %0A   

Use Java 8 Lambdas in GetClusterEditWarningsQuery