com.netxforge.netxstudio.screens.f4.Jobs.java Source code

Java tutorial

Introduction

Here is the source code for com.netxforge.netxstudio.screens.f4.Jobs.java

Source

/*******************************************************************************
 * Copyright (c) 21 jan. 2013 NetXForge.
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program 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 General Public License for more
 * details. You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>
 * 
 * Contributors: Christophe Bouhier - initial API and implementation and/or
 * initial documentation
 *******************************************************************************/
package com.netxforge.netxstudio.screens.f4;

import java.util.Collection;
import java.util.List;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.emf.databinding.EMFObservables;
import org.eclipse.emf.databinding.IEMFListProperty;
import org.eclipse.emf.databinding.IEMFValueProperty;
import org.eclipse.emf.databinding.edit.EMFEditProperties;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableValueEditingSupport;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.wb.swt.ResourceManager;
import org.eclipse.wb.swt.SWTResourceManager;

import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.netxforge.netxstudio.common.model.StudioUtils;
import com.netxforge.netxstudio.data.actions.ServerRequest;
import com.netxforge.netxstudio.scheduling.ComponentWorkFlowRun;
import com.netxforge.netxstudio.scheduling.Job;
import com.netxforge.netxstudio.scheduling.JobRunContainer;
import com.netxforge.netxstudio.scheduling.JobState;
import com.netxforge.netxstudio.scheduling.SchedulingPackage;
import com.netxforge.netxstudio.screens.AbstractScreen;
import com.netxforge.netxstudio.screens.editing.filter.CDOSearchFilter;
import com.netxforge.netxstudio.screens.editing.tables.CDOElementComparer;
import com.netxforge.netxstudio.screens.editing.util.CDOMementoUtil;
import com.netxforge.screens.editing.base.IDataServiceInjection;
import com.netxforge.screens.editing.base.ScreenUtil;
import com.netxforge.screens.editing.base.filter.ISearchFilter;
import com.netxforge.screens.editing.base.util.MementoUtil;

/**
 * 
 * @author Christophe Bouhier
 */
public class Jobs extends AbstractScreen implements IDataServiceInjection {

    private static final String MEM_KEY_JOBS_SELECTION_TABLE = "MEM_KEY_JOBS_SELECTION_TABLE";
    private static final String MEM_KEY_JOBS_COLUMNS_TABLE = "MEM_KEY_JOBS_COLUMNS_TABLE";

    private final FormToolkit toolkit = new FormToolkit(Display.getCurrent());
    private Table jobsTable;
    private Text txtFilterText;

    private TableViewer jobsTableViewer;
    private Form frmScheduledJobs;

    private Resource jobsResource;

    private TableViewerColumn tblViewerClmnState;

    @Inject
    private ServerRequest serverActions;

    /**
     * Mirrored scheduler state. It gets updated by init, manual request, or
     * when the scheduler state changes start <==> Stand-by.
     */
    boolean isRunning = false;

    /**
     * List all scheduled actions
     * 
     * @author Christophe
     * 
     */
    public class ListScheduleAction extends Action {

        public ListScheduleAction(String text) {
            super(text);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.action.Action#run()
         */
        @Override
        public void run() {
            try {
                updateScheduleInViewer();
                SWTResourceManager.disposeColors();
                // Update the viewer
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Create the composite.
     * 
     * @param parent
     * @param style
     */
    public Jobs(Composite parent, int style) {
        super(parent, style);
        addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                toolkit.dispose();
                // obm.dispose();
            }
        });
        toolkit.adapt(this);
        toolkit.paintBordersFor(this);

    }

    /**
     * Starts or stops the scheduler. The service side HTTP handler, is
     * synchronous, so roundtrip is awaited.
     * 
     * @author Christophe
     * 
     */
    public class SchedulerStartStopAction extends Action {

        ImageDescriptor playDescriptor = ResourceManager.getPluginImageDescriptor(
                "com.netxforge.netxstudio.screens.editing", "/icons/full/elcl16/play.png");

        ImageDescriptor pauseDescriptor = ResourceManager.getPluginImageDescriptor(
                "com.netxforge.netxstudio.screens.editing", "/icons/full/elcl16/pause.png");

        public SchedulerStartStopAction(String text) {
            super(text, SWT.PUSH);
            // check the initial status of the scheduler.
            try {
                updateSchedulerState();
            } catch (Exception e) {
                // status can't be obtained
                e.printStackTrace();
            }
            updateIcon();
        }

        /**
         * @throws Exception
         */
        public void updateSchedulerState() throws Exception {
            String result = serverActions.callJobAction(ServerRequest.COMMAND_SCHEDULER_STATUS);
            isRunning = ServerRequest.schedulerRunning(ServerRequest.COMMAND_SCHEDULER_STATUS, result);
            // System.out.println("Set action state scheduler is running? " +
            // isRunning + " (result text) " + result);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.action.Action#run()
         */
        @Override
        public void run() {

            if (isRunning) {
                try {
                    serverActions.callJobAction(ServerRequest.COMMAND_SCHEDULER_STOP);
                    updateSchedulerState();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                try {
                    serverActions.callJobAction(ServerRequest.COMMAND_SCHEDULER_START);
                    updateSchedulerState();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            updateIcon();
            updateScheduleInViewer();
        }

        private void updateIcon() {
            if (isRunning) {
                this.setImageDescriptor(pauseDescriptor);
                this.setText("Pause");
            } else {
                this.setImageDescriptor(playDescriptor);
            }
        }
    }

    private void buildUI() {
        setLayout(new FillLayout(SWT.HORIZONTAL));

        frmScheduledJobs = toolkit.createForm(this);

        frmScheduledJobs.getToolBarManager().add(new ListScheduleAction("Update scheduler information"));
        frmScheduledJobs.getToolBarManager().add(new SchedulerStartStopAction("Start"));

        frmScheduledJobs.getToolBarManager().update(true);
        frmScheduledJobs.setToolBarVerticalAlignment(SWT.TOP);

        frmScheduledJobs.setSeparatorVisible(true);
        toolkit.paintBordersFor(frmScheduledJobs);
        frmScheduledJobs.setText("Scheduled Jobs");
        frmScheduledJobs.getBody().setLayout(new GridLayout(3, false));

        Label lblFilterLabel = toolkit.createLabel(frmScheduledJobs.getBody(), "Filter:", SWT.NONE);
        GridData gd_lblFilterLabel = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
        gd_lblFilterLabel.widthHint = 44;
        lblFilterLabel.setLayoutData(gd_lblFilterLabel);

        txtFilterText = toolkit.createText(frmScheduledJobs.getBody(), "New Text",
                SWT.H_SCROLL | SWT.SEARCH | SWT.CANCEL);
        txtFilterText.setText("");
        GridData gd_txtFilterText = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
        gd_txtFilterText.widthHint = 200;
        txtFilterText.setLayoutData(gd_txtFilterText);
        txtFilterText.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent ke) {
                ViewerFilter[] filters = jobsTableViewer.getFilters();
                for (ViewerFilter viewerFilter : filters) {
                    if (viewerFilter instanceof ISearchFilter) {
                        ((ISearchFilter) viewerFilter).setSearchText(txtFilterText.getText());
                    }
                }
                jobsTableViewer.refresh();
            }
        });

        jobsTableViewer = new TableViewer(frmScheduledJobs.getBody(), SWT.BORDER | SWT.FULL_SELECTION);
        jobsTableViewer.setComparer(new CDOElementComparer());
        jobsTableViewer.addFilter(new CDOSearchFilter());

        jobsTable = jobsTableViewer.getTable();
        jobsTable.setLinesVisible(true);
        jobsTable.setHeaderVisible(true);
        jobsTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 4));
        toolkit.paintBordersFor(jobsTable);

        TableViewerColumn tblViewerClmType = new TableViewerColumn(jobsTableViewer, SWT.NONE);
        TableColumn tblclmnJobType = tblViewerClmType.getColumn();
        tblclmnJobType.setWidth(100);
        tblclmnJobType.setText("Job Type");

        TableViewerColumn tableViewerColumn = new TableViewerColumn(jobsTableViewer, SWT.NONE);
        TableColumn tblclmnName = tableViewerColumn.getColumn();
        tblclmnName.setWidth(100);
        tblclmnName.setText("Name");

        tblViewerClmnState = new TableViewerColumn(jobsTableViewer, SWT.NONE);
        TableColumn tblclmnState = tblViewerClmnState.getColumn();
        tblclmnState.setWidth(76);
        tblclmnState.setText("Enabled");

        TableViewerColumn tableViewerColumn_2 = new TableViewerColumn(jobsTableViewer, SWT.NONE);
        TableColumn tblclmnStarttime = tableViewerColumn_2.getColumn();
        tblclmnStarttime.setWidth(130);
        tblclmnStarttime.setText("Scheduled start");

        TableViewerColumn tableViewerColumn_3 = new TableViewerColumn(jobsTableViewer, SWT.NONE);
        TableColumn tblclmnType = tableViewerColumn_3.getColumn();
        tblclmnType.setWidth(130);
        tblclmnType.setText("End");

        TableViewerColumn tableViewerColumn_1 = new TableViewerColumn(jobsTableViewer, SWT.NONE);
        TableColumn tblclmnRepeat = tableViewerColumn_1.getColumn();
        tblclmnRepeat.setWidth(100);
        tblclmnRepeat.setText("Repeats");

        TableViewerColumn tableViewerColumn_6 = new TableViewerColumn(jobsTableViewer, SWT.NONE);
        TableColumn tblclmnInterval = tableViewerColumn_6.getColumn();
        tblclmnInterval.setWidth(100);
        tblclmnInterval.setText("Interval");

        TableViewerColumn tableViewerColumn_7 = new TableViewerColumn(jobsTableViewer, SWT.NONE);
        TableColumn tblclmnUpdate = tableViewerColumn_7.getColumn();
        tblclmnUpdate.setWidth(100);
        tblclmnUpdate.setText("Update");

        jobsTable.setFocus();
    }

    private final List<IAction> actions = Lists.newArrayList();
    private CDOView cdoView;

    /**
     * Set by CDO Invalidation
     */
    private ComponentWorkFlowRun runningWFR;

    @Override
    public IAction[] getActions() {
        // lazy init.
        if (actions.isEmpty()) {
            String actionText = ScreenUtil.isReadOnlyOperation(this.getOperation()) ? "View..." : "Edit...";

            actions.add(new EditJobAction(actionText));
            actions.add(new JobRunsAction("Runs..."));
        }
        return actions.toArray(new IAction[actions.size()]);

    }

    /**
     * An addon {@link Adapter} which provides
     * 
     * @author Christophe Bouhier
     * 
     */
    public class TriggerAddon extends AdapterImpl {
        private final String[] trigger;

        public TriggerAddon(String[] trigger) {
            this.trigger = trigger;
        }

        public String getTriggerTime() {
            return trigger[1];
        }

        @Override
        public boolean isAdapterForType(Object type) {
            return type == TriggerAddon.class;
        }
    }

    class EditJobAction extends Action {

        public EditJobAction(String text) {
            super(text);
        }

        @Override
        public void run() {
            ISelection selection = getViewer().getSelection();
            if (selection instanceof IStructuredSelection) {
                Object o = ((IStructuredSelection) selection).getFirstElement();
                NewEditJob job = new NewEditJob(screenService.getScreenContainer(), SWT.NONE);
                job.setScreenService(screenService);
                job.setOperation(ScreenUtil.OPERATION_EDIT);
                job.injectData(jobsResource, o);
                screenService.setActiveScreen(job);
            }
        }

    }

    class JobRunsAction extends Action {

        public JobRunsAction(String text) {
            super(text);
        }

        @Override
        public void run() {
            ISelection selection = getViewer().getSelection();
            if (selection instanceof IStructuredSelection) {
                Object o = ((IStructuredSelection) selection).getFirstElement();
                JobRuns jobRunsScreen = new JobRuns(screenService.getScreenContainer(), SWT.NONE);
                jobRunsScreen.setScreenService(screenService);
                jobRunsScreen.setOperation(ScreenUtil.OPERATION_READ_ONLY);
                jobRunsScreen.injectData(jobsResource, o);
                screenService.setActiveScreen(jobRunsScreen);
            }

        }

    }

    // Editing support for JFace databinding.
    @SuppressWarnings("unused")
    private class CheckBoxEditingSupport extends ObservableValueEditingSupport {
        private CellEditor cellEditor;

        public CheckBoxEditingSupport(ColumnViewer viewer, DataBindingContext dbc) {
            super(viewer, dbc);
            // cellEditor = new TextCellEditor((Composite) viewer.getControl());

            String[] values = new String[JobState.VALUES.size()];
            int i = 0;
            for (JobState s : JobState.VALUES) {
                values[i] = s.getName();
                i++;
            }
            cellEditor = new ComboBoxCellEditor((Composite) viewer.getControl(), values);
        }

        protected CellEditor getCellEditor(Object element) {
            return cellEditor;
        }

        protected IObservableValue doCreateCellEditorObservable(CellEditor cellEditor) {
            return SWTObservables.observeSelection(cellEditor.getControl());
        }

        protected IObservableValue doCreateElementObservable(Object element, ViewerCell cell) {
            IEMFValueProperty jobStateProperty = EMFEditProperties.value(editingService.getEditingDomain(),
                    SchedulingPackage.Literals.JOB__JOB_STATE);
            return jobStateProperty.observe(element);
        }
    }

    public EMFDataBindingContext initDataBindings_() {
        EMFDataBindingContext bindingContext = new EMFDataBindingContext();

        // tblViewerClmnState.setEditingSupport(new CheckBoxEditingSupport(
        // jobsTableViewer, bindingContext));

        // TODO, Implement content provider, which also can deal with the type
        // of a job which is defined
        // as a job class on it's own.
        ObservableListContentProvider listContentProvider = new ObservableListContentProvider();
        jobsTableViewer.setContentProvider(listContentProvider);

        EAttribute dummyAttribute = EcoreFactory.eINSTANCE.createEAttribute();

        IObservableMap[] observeMaps = EMFObservables.observeMaps(listContentProvider.getKnownElements(),
                new EStructuralFeature[] { dummyAttribute, SchedulingPackage.Literals.JOB__NAME,
                        SchedulingPackage.Literals.JOB__JOB_STATE, SchedulingPackage.Literals.JOB__START_TIME,
                        SchedulingPackage.Literals.JOB__END_TIME, SchedulingPackage.Literals.JOB__REPEAT,
                        SchedulingPackage.Literals.JOB__INTERVAL });
        jobsTableViewer.setLabelProvider(new JobsObervableMapLabelProvider(this, observeMaps));

        IEMFListProperty jobsProperties = EMFEditProperties.resource(editingService.getEditingDomain());

        IObservableList jobsList = jobsProperties.observe(jobsResource);

        jobsTableViewer.setInput(jobsList);

        return bindingContext;
    }

    public void injectData() {

        jobsResource = editingService.getData(SchedulingPackage.Literals.JOB);

        // We also need the transaction to resolve objects communicated by the
        // scheduler.
        if (jobsResource instanceof CDOResource) {
            cdoView = ((CDOResource) jobsResource).cdoView();
        }
        buildUI();
        initDataBindings_();
        updateScheduleInViewer();
    }

    private void updateScheduleInViewer() {
        try {
            String schedule = serverActions.callJobAction(ServerRequest.COMMAND_SCHEDULER_LIST);
            List<String[]> structure = ServerRequest.schedulerTriggers(schedule);
            List<Object> elementsToUpdate = Lists.newArrayList();
            for (final String[] trigger : structure) {
                CDOID triggeredObject = CDOIDUtil.read(trigger[0]); // Read the
                // CDOID;
                CDOObject object = cdoView.getObject(triggeredObject);
                Adapter adapter = EcoreUtil.getAdapter(object.eAdapters(), TriggerAddon.class);
                object.eAdapters().remove(adapter);
                object.eAdapters().add(new TriggerAddon(trigger));
                elementsToUpdate.add(object);
            }

            // Update the viewer.
            jobsTableViewer.refresh(true);
            if (!isRunning) {
                frmScheduledJobs.getHead().setBackground(SWTResourceManager.getColor(255, 102, 102));
                frmScheduledJobs.setText("Scheduled Jobs (NOT Running)");

            } else {
                frmScheduledJobs.getHead().setBackground(SWTResourceManager.getColor(200, 255, 100));
                frmScheduledJobs.setText("Scheduled Jobs (Running)");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public Viewer getViewer() {
        return jobsTableViewer;
    }

    @Override
    public boolean isValid() {
        return false;
    }

    public Form getScreenForm() {
        return frmScheduledJobs;
    }

    @Override
    public String getScreenName() {
        return "Jobs";
    }

    @Override
    public void handleRefresh(Object... objects) {

        for (Object o : objects) {
            if (o instanceof Collection<?>) {
                Collection<?> dirtyObjects = (Collection<?>) o;
                for (Object dirty : dirtyObjects) {
                    handleRefresh(dirty);
                }
            }
            if (o instanceof ComponentWorkFlowRun) {
                // Set a state, current Workflowrun, in the label provider
                // use this to map with the update request on the label
                // provider.
                setRunningWFR((ComponentWorkFlowRun) o);
                Job runningJob = StudioUtils.jobForWorkflowRun(runningWFR);
                if (runningJob != null) {
                    jobsTableViewer.update(runningJob, null);
                }

            }
            if (o instanceof JobRunContainer) {

            }
        }

    }

    /* We handle refresh */
    @Override
    public boolean shouldHandleRefresh() {
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.netxforge.netxstudio.screens.AbstractScreenImpl#saveState(org.eclipse
     * .ui.IMemento)
     */
    @Override
    public void saveState(IMemento memento) {

        // sash state vertical.
        CDOMementoUtil.rememberStructuredViewerSelection(memento, jobsTableViewer, MEM_KEY_JOBS_SELECTION_TABLE);
        MementoUtil.rememberStructuredViewerColumns(memento, jobsTableViewer, MEM_KEY_JOBS_COLUMNS_TABLE);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.netxforge.netxstudio.screens.AbstractScreenImpl#init(org.eclipse.
     * ui.IMemento)
     */
    @Override
    public void restoreState(IMemento memento) {
        if (memento != null) {
            CDOMementoUtil.retrieveStructuredViewerSelection(memento, jobsTableViewer, MEM_KEY_JOBS_SELECTION_TABLE,
                    ((CDOResource) jobsResource).cdoView());
            MementoUtil.retrieveStructuredViewerColumns(memento, jobsTableViewer, MEM_KEY_JOBS_COLUMNS_TABLE);
        }
    }

    public synchronized ComponentWorkFlowRun getRunningWFR() {
        return runningWFR;
    }

    public synchronized void setRunningWFR(ComponentWorkFlowRun runningWFR) {
        this.runningWFR = runningWFR;
    }

}