org.libreplan.web.common.JobSchedulerController.java Source code

Java tutorial

Introduction

Here is the source code for org.libreplan.web.common.JobSchedulerController.java

Source

/*
 * This file is part of LibrePlan
 *
 * Copyright (C) 2013 St. Antoniusziekenhuis
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.libreplan.web.common;

import static org.libreplan.web.I18nHelper._;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.libreplan.business.common.entities.Connector;
import org.libreplan.business.common.entities.ConnectorException;
import org.libreplan.business.common.entities.JobClassNameEnum;
import org.libreplan.business.common.entities.JobSchedulerConfiguration;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.importers.SynchronizationInfo;
import org.quartz.CronExpression;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.SuspendNotAllowedException;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zkplus.spring.SpringUtil;
import org.zkoss.zul.Button;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Groupbox;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Popup;
import org.zkoss.zul.RowRenderer;
import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.Caption;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

/**
 * Controller for job scheduler manager.
 *
 * @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
 */
public class JobSchedulerController extends BaseCRUDController<JobSchedulerConfiguration> {

    private static final Log LOG = LogFactory.getLog(JobSchedulerController.class);

    private Popup cronExpressionInputPopup;

    private Label jobGroup;

    private Label jobName;

    private Textbox cronExpressionTextBox;

    private Textbox cronExpressionSeconds;

    private Textbox cronExpressionMinutes;

    private Textbox cronExpressionHours;

    private Textbox cronExpressionDayOfMonth;

    private Textbox cronExpressionMonth;

    private Textbox cronExpressionDayOfWeek;

    private Textbox cronExpressionYear;

    private IJobSchedulerModel jobSchedulerModel;

    public JobSchedulerController() {
        jobSchedulerModel = (IJobSchedulerModel) SpringUtil.getBean("jobSchedulerModel");
    }

    @Override
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        Grid listJobSchedulings = (Grid) listWindow.getFellowIfAny("listJobSchedulings");
        listJobSchedulings.getModel();
        initCronExpressionPopup();
    }

    /**
     * Initializes cron expressions for popup.
     */
    private void initCronExpressionPopup() {
        cronExpressionTextBox = (Textbox) editWindow.getFellow("cronExpressionTextBox");

        cronExpressionInputPopup = (Popup) editWindow.getFellow("cronExpressionInputPopup");

        jobGroup = (Label) cronExpressionInputPopup.getFellow("jobGroup");

        jobName = (Label) cronExpressionInputPopup.getFellow("jobName");

        Grid cronExpressionGrid = (Grid) cronExpressionInputPopup.getFellow("cronExpressionGrid");

        cronExpressionSeconds = (Textbox) cronExpressionGrid.getFellow("cronExpressionSeconds");

        cronExpressionMinutes = (Textbox) cronExpressionGrid.getFellow("cronExpressionMinutes");

        cronExpressionHours = (Textbox) cronExpressionGrid.getFellow("cronExpressionHours");

        cronExpressionDayOfMonth = (Textbox) cronExpressionGrid.getFellow("cronExpressionDayOfMonth");

        cronExpressionMonth = (Textbox) cronExpressionGrid.getFellow("cronExpressionMonth");

        cronExpressionDayOfWeek = (Textbox) cronExpressionGrid.getFellow("cronExpressionDayOfWeek");

        cronExpressionYear = (Textbox) cronExpressionGrid.getFellow("cronExpressionYear");
    }

    /**
     * Returns a list of {@link JobSchedulerConfiguration}.
     */
    public List<JobSchedulerConfiguration> getJobSchedulerConfigurations() {
        return jobSchedulerModel.getJobSchedulerConfigurations();
    }

    /**
     * Returns {@link JobSchedulerConfiguration}.
     */
    public JobSchedulerConfiguration getJobSchedulerConfiguration() {
        return jobSchedulerModel.getJobSchedulerConfiguration();
    }

    /**
     * Returns all predefined jobs.
     */
    public JobClassNameEnum[] getJobNames() {
        return JobClassNameEnum.values();
    }

    /**
     * Returns list of connectorNames.
     */
    public List<String> getConnectorNames() {
        List<Connector> connectors = jobSchedulerModel.getConnectors();
        List<String> connectorNames = new ArrayList<>();

        for (Connector connector : connectors) {
            connectorNames.add(connector.getName());
        }

        return connectorNames;
    }

    /**
     * Renders job scheduling and returns {@link RowRenderer}.
     */
    public RowRenderer getJobSchedulingRenderer() {
        return (row, o, i) -> {
            final JobSchedulerConfiguration jobSchedulerConfiguration = (JobSchedulerConfiguration) o;
            row.setValue(o);

            Util.appendLabel(row, jobSchedulerConfiguration.getJobGroup());
            Util.appendLabel(row, jobSchedulerConfiguration.getJobName());
            Util.appendLabel(row, jobSchedulerConfiguration.getCronExpression());
            Util.appendLabel(row, getNextFireTime(jobSchedulerConfiguration));
            Hbox hbox = new Hbox();

            hbox.appendChild(createManualButton(event -> {
                try {
                    jobSchedulerModel.doManual(jobSchedulerConfiguration);
                    showSynchronizationInfo();
                } catch (ConnectorException e) {
                    messagesForUser.showMessage(Level.ERROR, e.getMessage());
                }
            }));

            hbox.appendChild(Util.createEditButton(event -> goToEditForm(jobSchedulerConfiguration)));

            hbox.appendChild(Util.createRemoveButton(event -> confirmDelete(jobSchedulerConfiguration)));

            row.appendChild(hbox);
        };
    }

    private RowRenderer getSynchronizationInfoRenderer() {
        return (row, o, i) -> {
            final SynchronizationInfo synchronizationInfo = (SynchronizationInfo) o;
            row.setValue(o);

            Groupbox groupbox = new Groupbox();
            groupbox.setClosable(true);
            Caption caption = new Caption();
            caption.setLabel(synchronizationInfo.getAction());
            groupbox.appendChild(caption);
            row.appendChild(groupbox);

            if (synchronizationInfo.isSuccessful()) {
                groupbox.appendChild(new Label(_("Completed")));
            } else {

                Listbox listbox = new Listbox();

                listbox.setModel(new SimpleListModel<>(synchronizationInfo.getFailedReasons()));
                groupbox.appendChild(listbox);
            }
        };
    }

    private List<SynchronizationInfo> getSynchronizationInfos() {
        return jobSchedulerModel.getSynchronizationInfos();
    }

    private void showSynchronizationInfo() {
        Map<String, Object> args = new HashMap<>();

        Window win = (Window) Executions.createComponents("/orders/_synchronizationInfo.zul", null, args);

        Window syncInfoWin = (Window) win.getFellowIfAny("syncInfoWin");

        Grid syncInfoGrid = (Grid) syncInfoWin.getFellowIfAny("syncInfoGrid");

        syncInfoGrid.setModel(new SimpleListModel<>(getSynchronizationInfos()));

        syncInfoGrid.setRowRenderer(getSynchronizationInfoRenderer());

        try {
            win.doModal();
        } catch (SuspendNotAllowedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns the next fire time for the specified job in {@link JobSchedulerConfiguration}.
     *
     * @param jobSchedulerConfiguration
     *            the job scheduler configuration
     */
    private String getNextFireTime(JobSchedulerConfiguration jobSchedulerConfiguration) {
        return jobSchedulerModel.getNextFireTime(jobSchedulerConfiguration);
    }

    /**
     * Creates and returns a button.
     *
     * @param eventListener
     *            Event listener for this button
     */
    private static Button createManualButton(EventListener eventListener) {
        Button button = new Button(_("Manual"));
        button.setTooltiptext(_("Manual"));
        button.setSclass("add-button");
        button.addEventListener(Events.ON_CLICK, eventListener);

        return button;
    }

    /**
     * Opens the <code>cronExpressionInputPopup</code>.
     */
    public void openPopup() {
        setupCronExpressionPopup(getJobSchedulerConfiguration());
        cronExpressionInputPopup.open(cronExpressionTextBox, "after_start");
    }

    /**
     * Sets the cronExpression values for <code>cronExpressionInputPopup</code>.
     *
     * @param jobSchedulerConfiguration
     *            where to read the values
     */
    private void setupCronExpressionPopup(final JobSchedulerConfiguration jobSchedulerConfiguration) {
        if (jobSchedulerConfiguration != null) {
            jobGroup.setValue(jobSchedulerConfiguration.getJobGroup());
            jobName.setValue(jobSchedulerConfiguration.getJobName());

            String cronExpression = jobSchedulerConfiguration.getCronExpression();

            if (cronExpression == null || cronExpression.isEmpty()) {
                return;
            }

            String[] cronExpressionArray = StringUtils.split(cronExpression);

            cronExpressionSeconds.setValue(cronExpressionArray[0]);
            cronExpressionMinutes.setValue(cronExpressionArray[1]);
            cronExpressionHours.setValue(cronExpressionArray[2]);
            cronExpressionDayOfMonth.setValue(cronExpressionArray[3]);
            cronExpressionMonth.setValue(cronExpressionArray[4]);
            cronExpressionDayOfWeek.setValue(cronExpressionArray[5]);

            if (cronExpressionArray.length == 7) {
                cronExpressionYear.setValue(cronExpressionArray[6]);
            }
        }
    }

    /**
     * Sets the <code>cronExpressionTextBox</code> value from the <code>cronExpressionInputPopup</code>.
     */
    public void updateCronExpression() {
        String cronExpression = getCronExpressionString();
        try {
            // Check cron expression format
            new CronExpression(cronExpression);
        } catch (ParseException e) {
            LOG.info("Unable to parse cron expression", e);

            throw new WrongValueException(cronExpressionInputPopup,
                    _("Unable to parse cron expression") + ":\n" + e.getMessage());
        }
        cronExpressionTextBox.setValue(cronExpression);
        cronExpressionInputPopup.close();
        Util.saveBindings(cronExpressionTextBox);
    }

    /**
     * Concatenating the cronExpression values.
     *
     * @return cronExpression string
     */
    private String getCronExpressionString() {
        String cronExpression = "";
        cronExpression += StringUtils.trimToEmpty(cronExpressionSeconds.getValue()) + " ";
        cronExpression += StringUtils.trimToEmpty(cronExpressionMinutes.getValue()) + " ";
        cronExpression += StringUtils.trimToEmpty(cronExpressionHours.getValue()) + " ";
        cronExpression += StringUtils.trimToEmpty(cronExpressionDayOfMonth.getValue()) + " ";
        cronExpression += StringUtils.trimToEmpty(cronExpressionMonth.getValue()) + " ";
        cronExpression += StringUtils.trimToEmpty(cronExpressionDayOfWeek.getValue());

        String year = StringUtils.trimToEmpty(cronExpressionYear.getValue());

        return !year.isEmpty() ? cronExpression + " " + year : cronExpression;
    }

    /**
     * Closes the popup.
     */
    public void cancelPopup() {
        cronExpressionInputPopup.close();
    }

    @Override
    protected String getEntityType() {
        return _("Job scheduling");
    }

    @Override
    protected String getPluralEntityType() {
        return _("Job scheduling");
    }

    @Override
    protected void initCreate() {
        jobSchedulerModel.initCreate();
    }

    @Override
    protected void initEdit(JobSchedulerConfiguration entity) {
        jobSchedulerModel.initEdit(entity);
    }

    @Override
    protected void save() {
        jobSchedulerModel.confirmSave();
        if (jobSchedulerModel.scheduleOrUnscheduleJob()) {
            messagesForUser.showMessage(Level.INFO, _("Job is scheduled/unscheduled"));
        }
    }

    @Override
    protected void cancel() {
        jobSchedulerModel.cancel();
    }

    @Override
    protected JobSchedulerConfiguration getEntityBeingEdited() {
        return jobSchedulerModel.getJobSchedulerConfiguration();
    }

    @Override
    protected void delete(JobSchedulerConfiguration entity) throws InstanceNotFoundException {
        jobSchedulerModel.remove(entity);
        if (jobSchedulerModel.deleteScheduledJob(entity)) {
            messagesForUser.showMessage(Level.INFO, _("Job is deleted from scheduler"));
        }
    }

}