org.jboss.bpm.console.client.process.InstanceListView.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.bpm.console.client.process.InstanceListView.java

Source

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2006, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.bpm.console.client.process;

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

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.mvc4g.client.Controller;
import com.mvc4g.client.Event;
import com.mvc4g.client.ViewInterface;
import org.jboss.bpm.console.client.ApplicationContext;
import org.jboss.bpm.console.client.BpmConsoleClientFactory;
import org.jboss.bpm.console.client.common.CustomizableListBox;
import org.jboss.bpm.console.client.common.DataDriven;
import org.jboss.bpm.console.client.common.IFrameWindowCallback;
import org.jboss.bpm.console.client.common.IFrameWindowPanel;
import org.jboss.bpm.console.client.common.LoadingOverlay;
import org.jboss.bpm.console.client.common.WidgetWindowPanel;
import org.jboss.bpm.console.client.icons.ConsoleIconBundle;
import org.jboss.bpm.console.client.model.ProcessDefinitionRef;
import org.jboss.bpm.console.client.model.ProcessInstanceRef;
import org.jboss.bpm.console.client.model.TokenReference;
import org.jboss.bpm.console.client.process.events.InstanceEvent;
import org.jboss.bpm.console.client.process.events.SignalInstanceEvent;
import org.jboss.bpm.console.client.util.SimpleDateFormat;

/**
 * @author Heiko.Braun <heiko.braun@jboss.com>
 */
public class InstanceListView implements IsWidget, ViewInterface, DataDriven {

    public final static String ID = InstanceListView.class.getName();

    private Controller controller;

    private VerticalPanel instanceList = null;

    private CustomizableListBox<ProcessInstanceRef> listBox;

    private ProcessDefinitionRef currentDefinition;

    private boolean isInitialized;

    private List<ProcessInstanceRef> cachedInstances = null;

    private SimpleDateFormat dateFormat = new SimpleDateFormat();

    private ApplicationContext appContext;

    private IFrameWindowPanel iframeWindow = null;

    private boolean isRiftsawInstance;

    //private PagingPanel pagingPanel;

    SimplePanel panel;

    private MenuItem startBtn, terminateBtn, deleteBtn, signalBtn, refreshBtn;

    // elements needed to signal waiting execution
    private List<TokenReference> tokensToSignal = null;

    private WidgetWindowPanel signalWindowPanel;

    private CustomizableListBox<TokenReference> listBoxTokens = null;

    private List<TextBox> signalTextBoxes = null;

    private CustomizableListBox<String> listBoxTokenSignals;

    private ImageResource greenIcon;
    private final BpmConsoleClientFactory clientFactory;

    public InstanceListView(BpmConsoleClientFactory clientFactory) {
        this.appContext = clientFactory.getApplicationContext();
        this.clientFactory = clientFactory;
        this.isRiftsawInstance = clientFactory.getApplicationContext().getConfig().getProfileName()
                .equals("BPEL Console");
        this.controller = clientFactory.getController();
    }

    public Widget asWidget() {

        panel = new SimplePanel();

        controller.addView(ID, this);
        initialize();

        ConsoleIconBundle imageBundle = (ConsoleIconBundle) GWT.create(ConsoleIconBundle.class);
        greenIcon = imageBundle.greenIcon();

        return panel;
    }

    public boolean isInitialized() {
        return isInitialized;
    }

    public void initialize() {
        if (!isInitialized) {
            instanceList = new VerticalPanel();

            listBox = new CustomizableListBox<ProcessInstanceRef>(
                    new CustomizableListBox.ItemFormatter<ProcessInstanceRef>() {
                        public String format(ProcessInstanceRef processInstanceRef) {

                            String result = "";

                            result += processInstanceRef.getId();
                            result += " ";
                            result += processInstanceRef.getState().toString();
                            result += " ";
                            result += processInstanceRef.getStartDate() != null
                                    ? dateFormat.format(processInstanceRef.getStartDate())
                                    : "";

                            return result;
                        }
                    });

            listBox.setFirstLine("<b>Instance</b>, State, Start Date");

            listBox.addChangeHandler(new ChangeHandler() {
                public void onChange(ChangeEvent event) {
                    int index = listBox.getSelectedIndex();
                    if (index != -1) {
                        ProcessInstanceRef item = listBox.getItem(index);

                        // enable or disable signal button depending on current activity
                        if (isSignalable(item)) {
                            signalBtn.setEnabled(true);
                        } else {
                            signalBtn.setEnabled(false);
                        }

                        terminateBtn.setEnabled(true);

                        // update details
                        controller.handleEvent(new Event(UpdateInstanceDetailAction.ID,
                                new InstanceEvent(currentDefinition, item)));
                    }
                }
            });

            // toolbar
            final VerticalPanel toolBox = new VerticalPanel();

            toolBox.setSpacing(5);

            final MenuBar toolBar = new MenuBar();
            refreshBtn = new MenuItem("Refresh", new Command() {

                public void execute() {
                    controller.handleEvent(new Event(UpdateInstancesAction.ID, getCurrentDefinition()));
                }
            });
            toolBar.addItem(refreshBtn);
            refreshBtn.setEnabled(false);
            toolBar.addSeparator();

            startBtn = new MenuItem("Start", new Command() {
                public void execute() {
                    if (Window.confirm(
                            "Start new execution. Do you want to start a new execution of this process?")) {
                        String url = getCurrentDefinition().getFormUrl();
                        boolean hasForm = (url != null && !url.equals(""));
                        if (hasForm) {
                            ProcessDefinitionRef definition = getCurrentDefinition();
                            iframeWindow = new IFrameWindowPanel(definition.getFormUrl(),
                                    "New Process Instance: " + definition.getId());

                            iframeWindow.setCallback(new IFrameWindowCallback() {
                                public void onWindowClosed() {
                                    controller.handleEvent(
                                            new Event(UpdateInstancesAction.ID, getCurrentDefinition()));
                                }
                            });

                            iframeWindow.show();
                        } else {
                            controller.handleEvent(new Event(StartNewInstanceAction.ID, getCurrentDefinition()));
                        }
                    }

                }
            });

            terminateBtn = new MenuItem("Terminate", new Command() {
                public void execute() {
                    if (getSelection() != null) {

                        if (Window.confirm(
                                "Terminate instance. Terminating this instance will stop further execution.")) {
                            ProcessInstanceRef selection = getSelection();
                            selection.setState(ProcessInstanceRef.STATE.ENDED);
                            selection.setEndResult(ProcessInstanceRef.RESULT.OBSOLETE);
                            controller.handleEvent(new Event(StateChangeAction.ID, selection));
                        }
                    } else {
                        Window.alert("Missing selection. Please select an instance");
                    }
                }
            }

            );

            deleteBtn = new MenuItem("Delete", new Command() {
                public void execute() {
                    if (getSelection() != null) {
                        if (Window.confirm(
                                "Delete instance. Deleting this instance will remove any history information and associated tasks as well.")) {
                            ProcessInstanceRef selection = getSelection();
                            selection.setState(ProcessInstanceRef.STATE.ENDED);

                            controller.handleEvent(new Event(DeleteInstanceAction.ID, selection));

                        } else {
                            Window.alert("Missing selection. Please select an instance");
                        }
                    }
                }
            }

            );

            signalBtn = new MenuItem("Signal", new Command() {
                public void execute() {
                    createSignalWindow();
                }
            });

            if (!isRiftsawInstance) // riftsaw doesn't support instance operations
            {
                toolBar.addItem(startBtn);
                toolBar.addItem(signalBtn);
                toolBar.addItem(deleteBtn);

                startBtn.setEnabled(false);
                deleteBtn.setEnabled(false);
                signalBtn.setEnabled(false);
            }

            // terminate works on any BPM Engine
            toolBar.addItem(terminateBtn);
            terminateBtn.setEnabled(false);

            toolBox.add(toolBar);

            instanceList.add(toolBox);
            instanceList.add(listBox);

            // cached data?
            if (this.cachedInstances != null)

            {
                bindData(this.cachedInstances);
            }

            // layout
            HorizontalPanel layout = new HorizontalPanel();
            layout.add(instanceList);

            // details
            InstanceDetailView detailsView = new InstanceDetailView(clientFactory);
            controller.addView(InstanceDetailView.ID, detailsView);
            controller.addAction(UpdateInstanceDetailAction.ID, new UpdateInstanceDetailAction());
            controller.addAction(ClearInstancesAction.ID, new ClearInstancesAction());
            controller.addAction(SignalExecutionAction.ID,
                    new SignalExecutionAction(clientFactory.getApplicationContext()));
            layout.add(detailsView);

            panel.add(layout);

            isInitialized = true;

        }
    }

    public ProcessInstanceRef getSelection() {
        ProcessInstanceRef selection = null;
        if (listBox.getSelectedIndex() != -1) {
            selection = listBox.getItem(listBox.getSelectedIndex());
        }
        return selection;
    }

    public ProcessDefinitionRef getCurrentDefinition() {
        return this.currentDefinition;
    }

    public void setController(Controller controller) {
        this.controller = controller;
    }

    public void reset() {
        this.currentDefinition = null;
        this.cachedInstances = new ArrayList<ProcessInstanceRef>();
        renderUpdate();

        startBtn.setEnabled(false);
        terminateBtn.setEnabled(false);
        deleteBtn.setEnabled(false);
        signalBtn.setEnabled(false);
        refreshBtn.setEnabled(false);
    }

    public void update(Object... data) {
        this.currentDefinition = (ProcessDefinitionRef) data[0];
        this.cachedInstances = (List<ProcessInstanceRef>) data[1];

        renderUpdate();
    }

    public void setLoading(boolean isLoading) {
        LoadingOverlay.on(instanceList, isLoading);
    }

    private void renderUpdate() {
        if (isInitialized()) {
            bindData(this.cachedInstances);

            // clear details
            controller.handleEvent(
                    new Event(UpdateInstanceDetailAction.ID, new InstanceEvent(this.currentDefinition, null)));

            startBtn.setEnabled(true);
            deleteBtn.setEnabled(true);
            refreshBtn.setEnabled(true);
        }
    }

    private void bindData(List<ProcessInstanceRef> instances) {
        listBox.clear();

        List<ProcessInstanceRef> list = instances;//pagingPanel.trim(instances);
        for (ProcessInstanceRef inst : list) {
            listBox.addItem(inst);
        }

        // layout again
        //TODO: -Rikkola-
        //        panel.invalidate();
    }

    private boolean isSignalable(ProcessInstanceRef processInstance) {

        tokensToSignal = new ArrayList<TokenReference>();

        // first check if the parent execution is signalable
        if (processInstance.getRootToken() != null && processInstance.getRootToken().canBeSignaled()) {
            tokensToSignal.add(processInstance.getRootToken());

        } else if (processInstance.getRootToken() != null && processInstance.getRootToken().getChildren() != null) {
            // next verify children
            collectSignalableTokens(processInstance.getRootToken(), tokensToSignal);
        }

        if (tokensToSignal.size() > 0) {
            return true;
        } else {
            return false;
        }
    }

    private void collectSignalableTokens(TokenReference tokenParent, List<TokenReference> tokensToSignal) {
        if (tokenParent.getChildren() != null) {
            for (TokenReference token : tokenParent.getChildren()) {
                if (token.canBeSignaled()) {
                    tokensToSignal.add(token);
                }

                collectSignalableTokens(token, tokensToSignal);
            }
        }
    }

    private void createSignalWindow() {
        signalTextBoxes = new ArrayList<TextBox>();

        VerticalPanel layout = new VerticalPanel();
        layout.setStyleName("bpm-window-layout");

        // toolbar
        final HorizontalPanel toolBox = new HorizontalPanel();

        toolBox.setSpacing(5);

        final MenuBar toolBar = new MenuBar();
        toolBar.addItem("Signal", new Command() {

            public void execute() {
                int selectedToken = listBoxTokens.getSelectedIndex();
                int selectedSignal = listBoxTokenSignals.getSelectedIndex();
                if (selectedToken != -1 && selectedSignal != -1) {

                    controller.handleEvent(new Event(SignalExecutionAction.ID,
                            new SignalInstanceEvent(getCurrentDefinition(), getSelection(),
                                    listBoxTokens.getItem(selectedToken),
                                    listBoxTokenSignals.getItem(selectedSignal), selectedToken)));

                } else {
                    Window.alert("Incomplete selection. Please select both token and signal name");
                }

            }
        });

        toolBar.addItem("Cancel", new Command() {
            public void execute() {

                signalWindowPanel.close();
            }
        });

        Label header = new Label("Available tokens to signal: ");
        header.setStyleName("bpm-label-header");
        layout.add(header);

        toolBox.add(toolBar);

        layout.add(toolBox);

        listBoxTokens = new CustomizableListBox<TokenReference>(
                new CustomizableListBox.ItemFormatter<TokenReference>() {
                    public String format(TokenReference tokenReference) {
                        String result = "";

                        result += tokenReference.getId();

                        result += " ";

                        result += tokenReference.getName() == null ? tokenReference.getCurrentNodeName()
                                : tokenReference.getName();

                        return result;
                    }
                });

        listBoxTokens.setFirstLine("Id, Name");

        listBoxTokens.addChangeHandler(new ChangeHandler() {
            public void onChange(ChangeEvent event) {
                int index = listBoxTokens.getSelectedIndex();
                if (index != -1) {
                    TokenReference item = listBoxTokens.getItem(index);
                    renderAvailableSignals(item);
                }
            }
        });

        renderSignalListBox(-1);
        layout.add(listBoxTokens);

        Label headerSignals = new Label("Available signal names");
        headerSignals.setStyleName("bpm-label-header");
        layout.add(headerSignals);

        listBoxTokenSignals = new CustomizableListBox<String>(new CustomizableListBox.ItemFormatter<String>() {
            public String format(String item) {
                return item;
            }
        });

        listBoxTokenSignals.setFirstLine("Signal name");

        layout.add(listBoxTokenSignals);

        signalWindowPanel = new WidgetWindowPanel("Signal process from wait state", layout, true);

    }

    public void renderSignalListBox(int i) {
        // remove currently signaled token
        if (i > -1) {
            tokensToSignal.remove(i);
        }

        // if available token list is empty close window
        if (tokensToSignal.isEmpty()) {
            signalWindowPanel.close();
        }

        // display all remaining token possible to signal
        listBoxTokens.clear();
        for (TokenReference token : tokensToSignal) {
            listBoxTokens.addItem(token);
        }

        // clear available signal list box
        if (listBoxTokenSignals != null) {
            listBoxTokenSignals.clear();
        }
    }

    private void renderAvailableSignals(TokenReference item) {
        listBoxTokenSignals.clear();
        for (String signal : item.getAvailableSignals()) {
            listBoxTokenSignals.addItem(signal);
        }
    }

}