/* * Copyright 2005-2008 Pentaho Corporation. All rights reserved. * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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 Lesser General Public License for more details. * * Copyright 2008 - 2009 Pentaho Corporation. All rights reserved. * * Created * @author Steven Barkdull */ package org.pentaho.pac.client.scheduler.ctlr; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.pentaho.gwt.widgets.client.controls.ProgressPopupPanel; import org.pentaho.gwt.widgets.client.controls.schededitor.ScheduleEditor; import org.pentaho.gwt.widgets.client.dialogs.MessageDialogBox; import org.pentaho.gwt.widgets.client.ui.ICallback; import org.pentaho.gwt.widgets.client.utils.CronParseException; import org.pentaho.gwt.widgets.client.utils.TimeUtil; import org.pentaho.pac.client.ISchedulerServiceAsync; import org.pentaho.pac.client.PacServiceFactory; import org.pentaho.pac.client.common.ui.IResponseCallback; import org.pentaho.pac.client.common.ui.dialog.ConfirmDialog; import org.pentaho.pac.client.common.ui.dialog.MessageDialog; import org.pentaho.pac.client.i18n.Messages; import org.pentaho.pac.client.scheduler.model.Schedule; import org.pentaho.pac.client.scheduler.model.SchedulesModel; import org.pentaho.pac.client.scheduler.view.DualModeScheduleEditor; import org.pentaho.pac.client.scheduler.view.ScheduleCreatorDialog; import org.pentaho.pac.client.scheduler.view.SchedulerToolbar; import org.pentaho.pac.client.scheduler.view.SchedulesListCtrl; import org.pentaho.pac.client.scheduler.view.SolutionRepositoryActionSequenceListEditor; import org.pentaho.pac.client.scheduler.view.ScheduleCreatorDialog.TabIndex; import org.pentaho.pac.client.utils.ExceptionParser; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.ButtonBase; import com.google.gwt.user.client.ui.Widget; public class SchedulerToolbarController { private SchedulerToolbar schedulerToolbar; private SchedulesListCtrl schedulesListCtrl; private ScheduleCreatorDialog scheduleCreatorDialog = null; private SchedulesListController schedulesListController = null; private SolutionRepositoryActionSequenceListEditorController solRepActionSequenceEditorController = null; private SchedulesModel schedulesModel = null; private static final int INVALID_SCROLL_POS = -1; private static final String DISABLED = "disabled"; //$NON-NLS-1$ private boolean isInitialized = false; private boolean loadingInitialized = false; private static String SUSPENDED_SCHEDULER_STATE = "suspended"; //$NON-NLS-1$ private static String NORMAL_SCHEDULER_STATE = "normal"; //$NON-NLS-1$ public SchedulerToolbarController( ScheduleCreatorDialog pScheduleCreatorDialog, SchedulerToolbar schedulerToolbar, SchedulesListCtrl schedulesListCtrl ) { this.scheduleCreatorDialog = pScheduleCreatorDialog; this.schedulerToolbar = schedulerToolbar; this.schedulesListCtrl = schedulesListCtrl; } public void init( SchedulesListController pSchedulesListController, SolutionRepositoryActionSequenceListEditorController solRepActionSequenceEditorController ) { if ( !isInitialized ) { this.schedulesListController = pSchedulesListController; this.solRepActionSequenceEditorController = solRepActionSequenceEditorController; final SchedulerToolbarController localThis = this; schedulerToolbar.setOnCreateListener( new ICallback<Widget>() { public void onHandle(Widget w) { localThis.handleCreateSchedule(); } }); schedulerToolbar.setOnUpdateListener( new ICallback<Widget>() { public void onHandle(Widget w) { localThis.handleUpdateSchedule(); } }); schedulerToolbar.setOnDeleteListener( new ICallback<Widget>() { public void onHandle(Widget w) { localThis.handleDeleteSchedules(); } }); schedulerToolbar.setOnResumeListener( new ICallback<Widget>() { public void onHandle(Widget w) { localThis.handleResumeSchedules(); } }); schedulerToolbar.setOnSuspendListener( new ICallback<Widget>() { public void onHandle(Widget w) { localThis.handlePauseSchedules(); } }); schedulerToolbar.setOnRunNowListener( new ICallback<Widget>() { public void onHandle(Widget w) { localThis.handleRunNowSchedules(); } }); schedulerToolbar.setOnRefreshListener( new ICallback<Widget>() { public void onHandle(Widget w) { loadJobsTable(); // TODO sbarkdull reload sol rep model/view } }); schedulerToolbar.setOnFilterListChangeListener( new ICallback<String>() { public void onHandle(String s) { updateSchedulesTable(); } }); ICallback<SolutionRepositoryActionSequenceListEditor> loadingCompleteHandler = new ICallback<SolutionRepositoryActionSequenceListEditor>() { public void onHandle(SolutionRepositoryActionSequenceListEditor o) { localThis.handleLoadingComplete(); } }; scheduleCreatorDialog.getSolutionRepositoryActionSequenceEditor().setOnLoadingCompleteHandler( loadingCompleteHandler ); loadJobsTable(); // TODO sbarkdull belongs in SchedulesListController enableTools(); isInitialized = true; } } private List<Schedule> getSortedSchedulesList( List<Schedule> scheduleList ) { assert null != scheduleList : "getSortedSchedulesList(): Schedule list cannot be null."; //$NON-NLS-1$ Collections.sort( scheduleList, new Comparator<Schedule>() { public int compare(Schedule s1, Schedule s2) { return s1.getJobName().compareToIgnoreCase( s2.getJobName() ); } }); return scheduleList; } private void updateSchedulesTable() { List<Schedule> scheduleList = schedulesModel.getScheduleList(); schedulesListController.updateSchedulesTable( getSortedSchedulesList( getFilteredSchedulesList( scheduleList ) ) ); } private List<Schedule> getFilteredSchedulesList( List<Schedule> scheduleList ) { List<Schedule> filteredList = null; String filterVal = schedulerToolbar.getFilterValue(); if ( !SchedulerToolbar.ALL_GROUPS_FILTER.equals( filterVal ) ) { filteredList = new ArrayList<Schedule>(); for ( int ii=0; ii<scheduleList.size(); ++ii ) { Schedule s = scheduleList.get( ii ); if ( s.getJobGroup().equals( filterVal ) ) { filteredList.add( s ); } } } else { filteredList = scheduleList; } return filteredList; } private void updateSchedule() { AsyncCallback<Object> updateScheduleResponseCallback = new AsyncCallback<Object>() { public void onSuccess( Object o ) { scheduleCreatorDialog.hide(); loadJobsTable(); } public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(),caught.getMessage()), false, false, true); messageDialog.center(); } }; final List<Schedule> scheduleList = schedulesListCtrl.getSelectedSchedules(); Schedule oldSchedule = scheduleList.get( 0 ); DualModeScheduleEditor scheduleEditor = scheduleCreatorDialog.getScheduleEditor(); ISchedulerServiceAsync schedSvc = scheduleEditor.isSubscriptionSchedule() ? PacServiceFactory.getSubscriptionService() : PacServiceFactory.getSchedulerService(); String cronStr = scheduleEditor.getCronString(); Date startDate = scheduleEditor.getStartDate(); Date endDate = scheduleEditor.getEndDate(); if ( null == cronStr ) { // must be a repeating schedule String startTime = scheduleEditor.getStartTime(); // format of string should be: HH:MM:SS AM/PM, e.g. 7:12:28 PM startDate = TimeUtil.getDateTime( startTime, startDate ); endDate = (null != endDate) ? TimeUtil.getDateTime( startTime, endDate ) : null; } ScheduleEditor.ScheduleType rt = scheduleEditor.getScheduleType(); switch ( rt ) { case RUN_ONCE: schedSvc.updateRepeatSchedule( oldSchedule.getJobName(), oldSchedule.getJobGroup(), oldSchedule.getSchedId(), scheduleEditor.getName().trim(), scheduleEditor.getGroupName().trim(), scheduleEditor.getDescription().trim(), startDate, endDate, "0" /*repeat count*/, //$NON-NLS-1$ "0" /*repeat time*/, //$NON-NLS-1$ scheduleCreatorDialog.getSolutionRepositoryActionSequenceEditor().getActionsAsString().trim(), updateScheduleResponseCallback ); break; case SECONDS: // fall through case MINUTES: // fall through case HOURS: // fall through case DAILY: // fall through case WEEKLY: // fall through case MONTHLY: // fall through case YEARLY: if ( null == cronStr ) { String repeatInterval = Long.toString( TimeUtil.secsToMillisecs( scheduleEditor.getRepeatInSecs() ) ); schedSvc.updateRepeatSchedule( oldSchedule.getJobName(), oldSchedule.getJobGroup(), oldSchedule.getSchedId(), scheduleEditor.getName().trim(), scheduleEditor.getGroupName().trim(), scheduleEditor.getDescription().trim(), startDate, endDate, null /*repeat count*/, repeatInterval.trim(), scheduleCreatorDialog.getSolutionRepositoryActionSequenceEditor().getActionsAsString().trim(), updateScheduleResponseCallback ); break; } else { // fall through to case CRON } case CRON: schedSvc.updateCronSchedule( oldSchedule.getJobName(), oldSchedule.getJobGroup(), oldSchedule.getSchedId(), scheduleEditor.getName().trim(), scheduleEditor.getGroupName().trim(), scheduleEditor.getDescription().trim(), startDate, endDate, cronStr.trim(), scheduleCreatorDialog.getSolutionRepositoryActionSequenceEditor().getActionsAsString().trim(), updateScheduleResponseCallback ); break; default: throw new RuntimeException( Messages.getString("invalidRunType", rt.toString() ) ); //$NON-NLS-1$ } } /** * */ @SuppressWarnings("fallthrough") private void updateScheduleWithNewScheduleType() { final List<Schedule> scheduleList = schedulesListCtrl.getSelectedSchedules(); Schedule oldSchedule = scheduleList.get( 0 ); AsyncCallback<Object> deleteScheduleCallback = new AsyncCallback<Object>() { public void onSuccess( Object o ) { createSchedule(); } public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // TODO sbarkdull scheduleCreatorDialog -> scheduleEditorDialog DualModeScheduleEditor scheduleEditor = scheduleCreatorDialog.getScheduleEditor(); ISchedulerServiceAsync schedSvc = null; if ( oldSchedule.isSubscriptionSchedule() != scheduleEditor.isSubscriptionSchedule() ) { // they are changing the schedule type, so delete it, and add a new one schedSvc = oldSchedule.isSubscriptionSchedule() ? PacServiceFactory.getSubscriptionService() : PacServiceFactory.getSchedulerService(); List<Schedule> deleteList = new ArrayList<Schedule>(); deleteList.add( oldSchedule ); schedSvc.deleteJobs(deleteList, deleteScheduleCallback ); } else { // they are NOT changing the schedule type, so just update the existing schedule. updateSchedule(); } } /** * Merge the two maps into one map. Add all key-values in the schedulerMap to * the mergedMap, unless the key is in both the schedulerMap and subscriptionMap. * If it is in both maps, add the one from the subscriptionMap. * NOTE: all elements in subscriptionMap should be in the schedulerMap, but not the * inverse. * * @param schedulerMap * @param subscriptionMap * @return */ private static List<Schedule> mergeSchedules( Map<String,Schedule> schedulerMap, Map<String,Schedule> subscriptionMap ) { Schedule currentSched = null; List<Schedule> mergedList = new ArrayList<Schedule>(); for ( Map.Entry<String,Schedule> me : schedulerMap.entrySet() ) { Schedule subscriptionSchedule = subscriptionMap.get( me.getKey() ); if ( null != subscriptionSchedule ) { currentSched = subscriptionSchedule; } else { currentSched = me.getValue(); } mergedList.add( currentSched ); } return mergedList; } private void initFilterList() { String currentFilter = schedulerToolbar.getFilterValue(); currentFilter = ( null == currentFilter ) ? SchedulerToolbar.ALL_GROUPS_FILTER : currentFilter; Set<String> groupNames = new HashSet<String>(); List<Schedule> scheduleList = schedulesModel.getScheduleList(); for ( int ii=0; ii<scheduleList.size(); ++ii ) { Schedule s = scheduleList.get( ii ); String groupName = s.getJobGroup(); if ( !groupNames.contains( groupName ) ) { groupNames.add( groupName ); } } schedulerToolbar.clearFilters(); schedulerToolbar.addFilterItem( SchedulerToolbar.ALL_GROUPS_FILTER ); for ( String name : groupNames ) { schedulerToolbar.addFilterItem(name ); } schedulerToolbar.setFilterValue( currentFilter ); } private void loadJobsTable() { final ProgressPopupPanel loadingPanel = new ProgressPopupPanel(); loadingPanel.setLabelText( Messages.getString("loading") ); //$NON-NLS-1$ loadingPanel.center(); final int currScrollPos = schedulesListCtrl.getScrollPosition(); final Map<String,Schedule> schedulesMap = new HashMap<String,Schedule>(); AsyncCallback<Map<String,Schedule>> schedulerServiceCallback = new AsyncCallback<Map<String,Schedule>>() { public void onSuccess( Map<String,Schedule> pSchedulesMap ) { schedulesMap.putAll( pSchedulesMap ); enableTools(); AsyncCallback<Map<String,Schedule>> subscriptionServiceCallback = new AsyncCallback<Map<String,Schedule>>() { public void onSuccess( Map<String,Schedule> subscriptionSchedulesMap ) { List<Schedule> schedulesList = mergeSchedules( schedulesMap, subscriptionSchedulesMap ); schedulesModel = new SchedulesModel(); schedulesModel.add( schedulesList ); initFilterList(); updateSchedulesTable(); if ( INVALID_SCROLL_POS != currScrollPos ) { schedulesListCtrl.setScrollPosition( currScrollPos ); } enableTools(); loadingPanel.hide(); } // end inner onSuccess public void onFailure(Throwable caught) { loadingPanel.hide(); schedulesListCtrl.setTempMessage( Messages.getString("noSchedules") ); //$NON-NLS-1$ MessageDialog messageDialog = new MessageDialog( Messages.getString("error"), //$NON-NLS-1$ caught.getMessage() ); messageDialog.center(); enableTools(); } // end inner onFailure }; // end subscriptionServiceCallback PacServiceFactory.getSubscriptionService().getJobNames( subscriptionServiceCallback ); } // end outer onSuccess public void onFailure(Throwable caught) { loadingPanel.hide(); schedulesListCtrl.setTempMessage( Messages.getString("noSchedules") ); //$NON-NLS-1$ MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); messageDialog.show(); enableTools(); } // end outer onFailure }; // end schedulerServiceCallback PacServiceFactory.getSchedulerService().getJobNames( schedulerServiceCallback ); } public void enableTools() { List<Schedule> scheduleList = schedulesListCtrl.getSelectedSchedules(); boolean suspendEnabled = false, resumeEnabled = false; boolean resolvedSuspended = false, resolvedEnabled = false; for (Schedule schedule:scheduleList) { if (!resolvedSuspended && !schedule.getTriggerState().equalsIgnoreCase(SUSPENDED_SCHEDULER_STATE)){ suspendEnabled = true; resolvedSuspended = true; } if (!resolvedEnabled && !schedule.getTriggerState().equalsIgnoreCase(NORMAL_SCHEDULER_STATE)){ resumeEnabled = true; resolvedEnabled = true; } } int numSelectedItems = scheduleList.size(); enableWidget( schedulerToolbar.getCreateBtn(), true ); enableWidget( schedulerToolbar.getUpdateBtn(), 1 == numSelectedItems ); enableWidget( schedulerToolbar.getDeleteBtn(), numSelectedItems > 0 ); enableWidget( schedulerToolbar.getSuspendBtn(), suspendEnabled ); enableWidget( schedulerToolbar.getResumeBtn(), resumeEnabled ); enableWidget( schedulerToolbar.getRunNowBtn(), numSelectedItems > 0 ); enableWidget( schedulerToolbar.getRefreshBtn(), true ); } private static void enableWidget( ButtonBase btn, boolean isEnabled ) { btn.setEnabled( isEnabled ); if ( isEnabled ) { btn.removeStyleDependentName( DISABLED ); } else { btn.addStyleDependentName( DISABLED ); } } /** * NOTE: this method is extremely similar to updateSchedule, when modifying this method, * consider modifying updateSchedule in a similar way. */ @SuppressWarnings("fallthrough") private void createSchedule() { // TODO, List<Schedule> is probably not what we will get back AsyncCallback<Object> responseCallback = new AsyncCallback<Object>() { public void onSuccess( Object o ) { scheduleCreatorDialog.hide(); loadJobsTable(); } public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // end responseCallback // TODO sbarkdull scheduleCreatorDialog -> scheduleEditorDialog DualModeScheduleEditor scheduleEditor = scheduleCreatorDialog.getScheduleEditor(); String cronStr = scheduleEditor.getCronString(); Date startDate = scheduleEditor.getStartDate(); Date endDate = scheduleEditor.getEndDate(); if ( null == cronStr ) { // must be a repeating schedule String startTime = scheduleEditor.getStartTime(); // format of string should be: HH:MM:SS AM/PM, e.g. 7:12:28 PM startDate = TimeUtil.getDateTime( startTime, startDate ); endDate = (null != endDate) ? TimeUtil.getDateTime( startTime, endDate ) : null; } ScheduleEditor.ScheduleType rt = scheduleEditor.getScheduleType(); // TODO sbarkdull, if we want to support creation of scheduler schedules, we need to supply // a UI mechanism like a checkbox to allow user to identify scheduler vs subscription, // and then test the value of the check box instead of the following "true". ISchedulerServiceAsync schedSvc = scheduleEditor.isSubscriptionSchedule() ? PacServiceFactory.getSubscriptionService() : PacServiceFactory.getSchedulerService(); switch ( rt ) { case RUN_ONCE: schedSvc.createRepeatSchedule( scheduleEditor.getName().trim(), scheduleEditor.getGroupName().trim(), scheduleEditor.getDescription().trim(), startDate, endDate, "0" /*repeat count*/, //$NON-NLS-1$ "0" /*repeat time*/, //$NON-NLS-1$ scheduleCreatorDialog.getSolutionRepositoryActionSequenceEditor().getActionsAsString().trim(), responseCallback ); break; case SECONDS: // fall through case MINUTES: // fall through case HOURS: // fall through case DAILY: // fall through case WEEKLY: // fall through case MONTHLY: // fall through case YEARLY: if ( null == cronStr ) { String repeatInterval = Long.toString( TimeUtil.secsToMillisecs( scheduleEditor.getRepeatInSecs() ) ); schedSvc.createRepeatSchedule( scheduleEditor.getName().trim(), scheduleEditor.getGroupName().trim(), scheduleEditor.getDescription().trim(), startDate, endDate, null /*repeat count*/, repeatInterval.trim(), scheduleCreatorDialog.getSolutionRepositoryActionSequenceEditor().getActionsAsString().trim(), responseCallback ); break; } else { // fall through to case CRON } case CRON: schedSvc.createCronSchedule( scheduleEditor.getName().trim(), scheduleEditor.getGroupName().trim(), scheduleEditor.getDescription().trim(), startDate, endDate, cronStr.trim(), scheduleCreatorDialog.getSolutionRepositoryActionSequenceEditor().getActionsAsString().trim(), responseCallback ); break; default: throw new RuntimeException( Messages.getString("invalidRunType", rt.toString() ) ); //$NON-NLS-1$ } } private void deleteSelectedSchedules() { final List<Schedule> selectedScheduleList = schedulesListCtrl.getSelectedSchedules(); AsyncCallback<Object> outerCallback = new AsyncCallback<Object>() { public void onSuccess(Object result) { AsyncCallback<Object> innerCallback = new AsyncCallback<Object>() { public void onSuccess(Object pResult) { loadJobsTable(); } public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // end inner callback final List<Schedule> subscriptionSchedList = getSubscriptionSchedules( selectedScheduleList ); PacServiceFactory.getSubscriptionService().deleteJobs( subscriptionSchedList, innerCallback ); } // end onSuccess public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // end outer callback ----------- List<Schedule> nonSubscriptionSchedList = getSchedules( selectedScheduleList ); PacServiceFactory.getSchedulerService().deleteJobs( nonSubscriptionSchedList, outerCallback ); } /** * initialize the <code>scheduleEditor</code>'s user interface with * the contents of the <code>sched</code>. * * @param scheduleEditor * @param sched * @throws CronParseException if sched has a non-empty CRON string, and the CRON string is not valid. */ private void initScheduleCreatorDialog( Schedule sched ) throws CronParseException { scheduleCreatorDialog.reset( new Date() ); initScheduleEditor( sched ); initSolutionRepositoryActionSequenceEditor( sched ); } private void initScheduleEditor( Schedule sched ) throws CronParseException { DualModeScheduleEditor scheduleEditor = scheduleCreatorDialog.getScheduleEditor(); scheduleEditor.setSubscriptionSchedule( sched.isSubscriptionSchedule() ); scheduleEditor.setName( sched.getJobName() ); scheduleEditor.setGroupName( sched.getJobGroup() ); scheduleEditor.setDescription( sched.getDescription() ); String repeatIntervalInMillisecs = sched.getRepeatInterval(); if ( sched.isCronSchedule() ) { scheduleEditor.setCronString( sched.getCronString() ); // throws CronParseException } else if ( sched.isRepeatSchedule() ) { long repeatIntervalInSecs = TimeUtil.millsecondsToSecs( Long.parseLong( repeatIntervalInMillisecs ) ); if ( 0 == repeatIntervalInSecs ) { // run once scheduleEditor.setScheduleType( ScheduleEditor.ScheduleType.RUN_ONCE ); } else { // run multiple scheduleEditor.setRepeatInSecs( (int) repeatIntervalInSecs ); } } else { throw new RuntimeException( Messages.getString("illegalStateMissingCronAndRepeat") ); //$NON-NLS-1$ } String timePart = null; String strDate = sched.getStartDate(); if ( null != strDate ) { Date startDate = TimeUtil.getDate( strDate ); if ( sched.isRepeatSchedule() ) { timePart = TimeUtil.getTimePart( startDate ); scheduleEditor.setStartTime( timePart ); startDate = TimeUtil.zeroTimePart( startDate ); } scheduleEditor.setStartDate( startDate ); } // scheduleEditor.getRunOnceEditor().setStartTime(strTime) // scheduleEditor.getRunOnceEditor().setStartDate(strTime) strDate = sched.getEndDate(); if ( null != strDate ) { scheduleEditor.setEndBy(); Date endDate = TimeUtil.getDate( strDate ); if ( sched.isRepeatSchedule() ) { endDate = TimeUtil.zeroTimePart( endDate ); } scheduleEditor.setEndDate(endDate); } else { scheduleEditor.setNoEndDate(); } } private void initSolutionRepositoryActionSequenceEditor( Schedule sched ) { solRepActionSequenceEditorController.init( sched.getActionsList() ); } private boolean isNewScheduleCreatorDialogValid() { ScheduleEditor schedEd = scheduleCreatorDialog.getScheduleEditor(); ScheduleEditorValidator schedEdValidator = new NewScheduleEditorValidator( schedEd, schedulesModel ); return isScheduleCreatorDialogValid( schedEdValidator ); } private boolean isUpdateScheduleCreatorDialogValid() { ScheduleEditor schedEd = scheduleCreatorDialog.getScheduleEditor(); ScheduleEditorValidator schedEdValidator = new ScheduleEditorValidator( schedEd, schedulesModel ); return isScheduleCreatorDialogValid( schedEdValidator ); } private void handleCreateSchedule() { final SchedulerToolbarController localThis = this; scheduleCreatorDialog.setTitle( Messages.getString("scheduleCreator") ); //$NON-NLS-1$ scheduleCreatorDialog.reset( new Date() ); if(!loadingInitialized) { scheduleCreatorDialog.setOkBtnEnabled( false ); } scheduleCreatorDialog.setOnOkHandler( new ICallback<MessageDialog>() { public void onHandle(MessageDialog d) { localThis.createSchedule(); } }); this.scheduleCreatorDialog.setOnValidateHandler( new IResponseCallback<MessageDialog, Boolean>() { public Boolean onHandle( MessageDialog schedDlg ) { return isNewScheduleCreatorDialogValid(); } }); scheduleCreatorDialog.center(); solRepActionSequenceEditorController.init( null ); scheduleCreatorDialog.getScheduleEditor().setFocus(); } private void handleUpdateSchedule() { final SchedulerToolbarController localThis = this; scheduleCreatorDialog.setTitle( Messages.getString("scheduleEditor") ); //$NON-NLS-1$ final List<Schedule> scheduleList = schedulesListCtrl.getSelectedSchedules(); if(!loadingInitialized) { scheduleCreatorDialog.setOkBtnEnabled( false ); } scheduleCreatorDialog.setOnOkHandler( new ICallback<MessageDialog>() { public void onHandle(MessageDialog d) { localThis.updateScheduleWithNewScheduleType(); } }); this.scheduleCreatorDialog.setOnValidateHandler( new IResponseCallback<MessageDialog, Boolean>() { public Boolean onHandle( MessageDialog schedDlg ) { return isUpdateScheduleCreatorDialogValid(); } }); // the update button should be enabled/disabled to guarantee that one and only one schedule is selected assert scheduleList.size() == 1 : "When clicking update, exactly one schedule should be selected."; //$NON-NLS-1$ Schedule sched = scheduleList.get( 0 ); try { initScheduleCreatorDialog( sched ); scheduleCreatorDialog.center(); scheduleCreatorDialog.getScheduleEditor().setFocus(); } catch (CronParseException e) { final MessageDialog errorDialog = new MessageDialog( Messages.getString("error"), //$NON-NLS-1$ Messages.getString("invalidCronInInitOfRecurrenceDialog", sched.getCronString(), e.getMessage() ) ); //$NON-NLS-1$ errorDialog.setOnOkHandler( new ICallback<MessageDialog>() { public void onHandle(MessageDialog messageDialog ) { errorDialog.hide(); scheduleCreatorDialog.center(); } }); errorDialog.center(); } } private void handleLoadingComplete() { scheduleCreatorDialog.setOkBtnEnabled( true ); loadingInitialized = true; } private void handleDeleteSchedules() { final SchedulerToolbarController localThis = this; final ConfirmDialog confirm = new ConfirmDialog( Messages.getString("confirmDelete"), //$NON-NLS-1$ Messages.getString("confirmDeleteQuestion", Integer.toString( getNumSubscribers() ) ) ); //$NON-NLS-1$ confirm.setOnOkHandler( new ICallback<MessageDialog>() { public void onHandle( MessageDialog d ) { confirm.hide(); localThis.deleteSelectedSchedules(); } }); confirm.center(); } private int getNumSubscribers() { List<Schedule> schedList = schedulesListCtrl.getSelectedSchedules(); int numSubscribers = 0; for ( Schedule sched: schedList ) { try { numSubscribers += Integer.parseInt( sched.getSubscriberCount() ); } catch (NumberFormatException ex) { // Do nothing, we'll return 0. } } return numSubscribers; } private void handleResumeSchedules() { final List<Schedule> selectedScheduleList = schedulesListCtrl.getSelectedSchedules(); AsyncCallback<Object> outerCallback = new AsyncCallback<Object>() { public void onSuccess(Object result) { AsyncCallback<Object> innerCallback = new AsyncCallback<Object>() { public void onSuccess(Object pResult) { loadJobsTable(); } public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // end inner callback final List<Schedule> subscriptionSchedList = getSubscriptionSchedules( selectedScheduleList ); PacServiceFactory.getSubscriptionService().resumeJobs( subscriptionSchedList, innerCallback ); } // end onSuccess public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // end outer callback ----------- List<Schedule> nonSubscriptionSchedList = getSchedules( selectedScheduleList ); PacServiceFactory.getSchedulerService().resumeJobs( nonSubscriptionSchedList, outerCallback ); } private void handlePauseSchedules() { final List<Schedule> selectedScheduleList = schedulesListCtrl.getSelectedSchedules(); AsyncCallback<Object> outerCallback = new AsyncCallback<Object>() { public void onSuccess(Object result) { AsyncCallback<Object> innerCallback = new AsyncCallback<Object>() { public void onSuccess(Object pResult) { loadJobsTable(); } public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // end inner callback final List<Schedule> subscriptionSchedList = getSubscriptionSchedules( selectedScheduleList ); PacServiceFactory.getSubscriptionService().pauseJobs( subscriptionSchedList, innerCallback ); } // end onSuccess public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // end outer callback ----------- List<Schedule> nonSubscriptionSchedList = getSchedules( selectedScheduleList ); PacServiceFactory.getSchedulerService().pauseJobs( nonSubscriptionSchedList, outerCallback ); } private void handleRunNowSchedules() { final List<Schedule> selectedScheduleList = schedulesListCtrl.getSelectedSchedules(); AsyncCallback<Object> outerCallback = new AsyncCallback<Object>() { public void onSuccess(Object result) { AsyncCallback<Object> innerCallback = new AsyncCallback<Object>() { public void onSuccess(Object pResult) { loadJobsTable(); } public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // end inner callback final List<Schedule> subscriptionSchedList = getSubscriptionSchedules( selectedScheduleList ); PacServiceFactory.getSubscriptionService().executeJobs( subscriptionSchedList, innerCallback ); } // end onSuccess public void onFailure(Throwable caught) { MessageDialogBox messageDialog = new MessageDialogBox(ExceptionParser.getErrorHeader(caught.getMessage()), ExceptionParser.getErrorMessage(caught.getMessage(), caught.getMessage()), false, false, true); messageDialog.center(); } }; // end outer callback ----------- List<Schedule> nonSubscriptionSchedList = getSchedules( selectedScheduleList ); PacServiceFactory.getSchedulerService().executeJobs( nonSubscriptionSchedList, outerCallback ); } private static List<Schedule> getSchedules( List<Schedule> schedList ) { List<Schedule> list = new ArrayList<Schedule>(); for ( Schedule sched : schedList ) { if ( !sched.isSubscriptionSchedule() ) { list.add( sched); } } return list; } private static List<Schedule> getSubscriptionSchedules( List<Schedule> schedList ) { List<Schedule> list = new ArrayList<Schedule>(); for ( Schedule sched : schedList ) { if ( sched.isSubscriptionSchedule() ) { list.add( sched); } } return list; } /** * NOTE: This method should not be called directly except by isNewScheduleCreatorDialogValid and isUpdateScheduleCreatorDialogValid * NOTE: code in this method must stay in sync with isScheduleEditorValid(), i.e. all error msgs * that may be cleared in clearScheduleEditorValidationMsgs(), must be set-able here. */ private boolean isScheduleCreatorDialogValid( ScheduleEditorValidator schedEdValidator ) { boolean isValid = true; boolean isSubscriptionSched = scheduleCreatorDialog.getScheduleEditor().isSubscriptionSchedule(); SolutionRepositoryActionSequenceListEditor solRepPicker = scheduleCreatorDialog.getSolutionRepositoryActionSequenceEditor(); SolutionRepositoryActionSequenceListEditorValidator solRepValidator = new SolutionRepositoryActionSequenceListEditorValidator( solRepPicker, isSubscriptionSched ); scheduleCreatorDialog.clearTabError(); schedEdValidator.clear(); solRepValidator.clear(); /* * If a tab's controls have errors, change the tab's appearance so that * the tab-label displays in an error-color (red). If the current tab * does not have an error, find the first tab that does have an error, * and set it to the current tab. */ TabIndex firstTabWithError = null; boolean doesSelectedTabHaveError = false; TabIndex selectedIdx = scheduleCreatorDialog.getSelectedTab(); if ( !schedEdValidator.isValid() ) { isValid = false ; scheduleCreatorDialog.setTabError( TabIndex.SCHEDULE ); if ( null == firstTabWithError ) { firstTabWithError = TabIndex.SCHEDULE; } if ( TabIndex.SCHEDULE == selectedIdx ) { doesSelectedTabHaveError = true; } } if ( !solRepValidator.isValid() ) { isValid = false ; scheduleCreatorDialog.setTabError( TabIndex.SCHEDULE_ACTION ); if ( null == firstTabWithError ) { firstTabWithError = TabIndex.SCHEDULE_ACTION; } if ( TabIndex.SCHEDULE_ACTION == selectedIdx ) { doesSelectedTabHaveError = true; } } if ( false == doesSelectedTabHaveError && firstTabWithError != null ) { scheduleCreatorDialog.setSelectedTab( firstTabWithError ); } return isValid; } public SchedulesModel getSchedulesModel() { return schedulesModel; } }