<MyMathCalcPlugin Project>/src/org/myorg/mymathcalcplugin/AbstractComputationAction.java
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.myorg.mymathcalcplugin;

import com.im.commons.progress.DFFeedback;
import com.im.df.api.ddl.DFField;
import com.im.df.api.dml.DFResultSet;
import com.im.df.api.support.SelectionDescription;
import com.im.df.api.util.DIFUtilities;
import com.im.df.util.UIBackgroundRunnerRO;
import com.im.ijc.core.api.actions.AbstractFieldSelectionAwareAction;
import com.im.ijc.core.api.views.IJCWidget;
import com.im.ijc.core.api.util.IJCCoreUtils;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;

/**
 *
 */
public abstract class AbstractComputationAction extends AbstractFieldSelectionAwareAction {

    private static final int BATCH_MAX_SIZE = 200;
    private static final MessageFormat PROGRESS_MSG = new MessageFormat(NbBundle.getMessage(AbstractComputationAction.class, "MSG_ProgressDetails"));

    private ComputationPerformer computer;

    public AbstractComputationAction(ComputationPerformer computer) {
        this.computer = computer;
    }

    @Override
    protected void performAction(Node[] nodes) {
        IJCWidget widget = findWidget(nodes);
        final List<DFField> fields = IJCCoreUtils.computeFields(widget, false, true);
        final DFResultSet.VertexState vs = IJCCoreUtils.computeCommonVS(widget);

        UIBackgroundRunnerRO runner = new UIBackgroundRunnerRO(getName(), true) {

            @Override
            public void phase1InRequestProcessor() {
                computer.reset();

                SelectionDescription selection = vs.getSelection();
                int total = selection.getSelectedRowsCount();
                getEnvironment().getFeedback().switchToDeterminate(total);
                List ids = new ArrayList();
                for (int i = selection.getMinSelectionIndex(); i <= selection.getMaxSelectionIndex(); i++) {
                    if (getEnvironment().getFeedback().isCancelled()) {
                        return;
                    }

                    if (selection.isSelectedIndex(i)) {
                        ids.add(vs.getIdAt(i));
                    }

                    if ((ids.size() > BATCH_MAX_SIZE) || (i == selection.getMaxSelectionIndex())) {
                        Map<Comparable<?>, Map<String, Object>> data = vs.getData(ids, getEnvironment());

                        int current = i - selection.getMinSelectionIndex();
                        getEnvironment().getFeedback().addMessage(DFFeedback.Type.PROGRESS_MESSAGE, PROGRESS_MSG.format(new Object[] { current, total }), null);
                        getEnvironment().getFeedback().progress(current);

                        for (Map<String, Object> row: data.values()) {
                            for (DFField f: fields) {
                                computer.addValue(row.get(f.getId()));
                            }
                            if (getEnvironment().getFeedback().isCancelled()) {
                                return;
                            }
                        }
                        ids.clear();
                    }
                }

                NotifyDescriptor.Message nd = new NotifyDescriptor.Message(computer.getResultDisplayMessage(), NotifyDescriptor.INFORMATION_MESSAGE);
                DialogDisplayer.getDefault().notifyLater(nd);
            }

        };
        runner.start();
    }

    @Override
    protected boolean enableAccordingToCurrentSelection(IJCWidget widget) {
        if (super.enableAccordingToCurrentSelection(widget)) {
            DFResultSet.VertexState vs = IJCCoreUtils.computeCommonVS(widget);
            if (vs == null) {
                return false;
            }

            List<DFField> fields = IJCCoreUtils.computeFields(widget, false, true);
            for (DFField f: fields) {
                boolean ok = false;
                for (Class c: computer.getSupportedFieldCapabilities()) {
                    if (DIFUtilities.findCapability(f, c) != null) {
                        ok = true;
                        break;
                    }
                }
                if (!ok) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
}