/*******************************************************************************
* Copyright (c) 2013 AGETO Service GmbH and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Gunnar Wagenknecht - initial API and implementation
*******************************************************************************/
package org.eclipse.gyrex.admin.ui.jobs.internal;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.gyrex.admin.ui.internal.widgets.NonBlockingMessageDialogs;
import org.eclipse.gyrex.admin.ui.jobs.configuration.wizard.JobConfigurationWizardAdapter;
import org.eclipse.gyrex.admin.ui.jobs.configuration.wizard.JobConfigurationWizardSession;
import org.eclipse.gyrex.admin.ui.jobs.internal.generic.GenericJobParameterPage;
import org.eclipse.gyrex.common.identifiers.IdHelper;
import org.eclipse.gyrex.jobs.internal.schedules.ScheduleEntryImpl;
import org.eclipse.gyrex.jobs.internal.schedules.ScheduleImpl;
import org.eclipse.gyrex.jobs.manager.IJobManager;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Wizard for adding/updating a schedule entry.
*/
public class ScheduleEntryWizard extends Wizard {
private static final Logger LOG = LoggerFactory.getLogger(ScheduleEntryWizard.class);
private static final IWizardPage[] NO_PAGES = new IWizardPage[0];
private final Map<String, JobConfigurationWizardSession> sessionsByJobTypeId = new HashMap<String, JobConfigurationWizardSession>(2);
private final ScheduleImpl schedule;
private final ScheduleEntryImpl entry;
private final ScheduleEntryWizardPage scheduleEntryPage;
private JobConfigurationWizardSession currentSession;
private final ExclusiveLockWizardPage exclusiveLockPage;
public ScheduleEntryWizard(final ScheduleImpl schedule, final ScheduleEntryImpl entry) {
this.schedule = schedule;
this.entry = entry;
scheduleEntryPage = new ScheduleEntryWizardPage(schedule, entry);
exclusiveLockPage = new ExclusiveLockWizardPage(schedule, entry);
// force previous and next buttons (we don't know about potential job type pages)
setForcePreviousAndNextButtons(true);
}
@Override
public void addPages() {
addPage(scheduleEntryPage);
addPage(exclusiveLockPage);
}
@Override
public boolean canFinish() {
return scheduleEntryPage.isPageComplete() && exclusiveLockPage.isPageComplete() && (currentSession != null) && currentSession.canFinish();
}
void clearCurrentJobConfigurationSession() {
currentSession = null;
getContainer().showPage(scheduleEntryPage);
}
@Override
public IWizardPage getNextPage(final IWizardPage page) {
// REMINDER: this logic is inverted in #getPreviousPage
// the flow is as follows
// first: scheduleEntryPage
// 2-..: job type specific pages
// last: exclusiveLockPage
final IWizardPage[] sessionPages = null != currentSession ? currentSession.getPages() : NO_PAGES;
if (page == scheduleEntryPage) {
if (sessionPages.length > 0)
// show first job type page after scheduleEntryPage
return sessionPages[0];
else
// or go to exclusiveLockPage right away if there are no job type pages
return exclusiveLockPage;
}
if (page == exclusiveLockPage)
// no next page for the first page
return null;
// find the current job type page
for (int i = 0; i < sessionPages.length; i++) {
if (page == sessionPages[i]) {
if ((i + 1) < sessionPages.length)
// show next job type page
return sessionPages[i + 1];
else
// no next job type page; go to exclusiveLockPage
return exclusiveLockPage;
}
}
// no next page
return null;
}
@Override
public IWizardPage getPreviousPage(final IWizardPage page) {
// REMINDER: this logic is inverted in #getPreviousPage
// the flow is as follows
// first: scheduleEntryPage
// 2-..: job type specific pages
// last: exclusiveLockPage
final IWizardPage[] sessionPages = null != currentSession ? currentSession.getPages() : NO_PAGES;
if (page == exclusiveLockPage) {
if (sessionPages.length > 0)
// show last job type page before exclusiveLockPage
return sessionPages[sessionPages.length - 1];
else
// or go to scheduleEntryPage right away if there are no job type pages
return scheduleEntryPage;
}
if (page == scheduleEntryPage)
// no previous page for the first page
return null;
// find the current job type page
for (int i = sessionPages.length - 1; i >= 0; i--) {
if (page == sessionPages[i]) {
if ((i - 1) >= 0)
// show previous job type page
return sessionPages[i - 1];
else
// no previous job type page; go to scheduleEntryPage
return scheduleEntryPage;
}
}
// no previous page
return null;
}
public ScheduleImpl getSchedule() {
return schedule;
}
public ScheduleEntryImpl getScheduleEntry() {
return entry;
}
void initializeCurrentJobConfigurationSession(final String id, final String name, final JobConfigurationWizardAdapter wizardAdapter) {
if (!sessionsByJobTypeId.containsKey(id)) {
final JobConfigurationWizardSession session = new JobConfigurationWizardSession(id, name);
if (entry != null) {
// clone job parameter into new session
// (subsequent modifications MUST NOT be reflected into the entry or other sessions)
session.getParameter().putAll(entry.getJobParameter());
}
sessionsByJobTypeId.put(id, session);
}
final JobConfigurationWizardSession session = sessionsByJobTypeId.get(id);
if (session == currentSession)
// nothing changed
return;
// lazy initialize pages
if (null == session.getPages()) {
final IWizardPage[] pages = wizardAdapter != null ? wizardAdapter.createPages(session) : new IWizardPage[] { new GenericJobParameterPage(session) };
if (pages != null) {
session.setPages(pages);
for (final IWizardPage page : pages) {
addPage(page);
}
} else {
LOG.debug("No pages returned for job type {} (adapter {})", id, wizardAdapter);
session.setPages(NO_PAGES);
}
}
currentSession = session;
if (null != getContainer().getCurrentPage()) {
getContainer().updateButtons();
}
}
@Override
public boolean performFinish() {
final String entryId = scheduleEntryPage.getEntryId();
ScheduleEntryImpl entry = null;
try {
if (this.entry == null) {
entry = schedule.createEntry(entryId);
entry.setJobTypeId(scheduleEntryPage.getJobTypeId());
} else {
entry = this.entry;
}
if (scheduleEntryPage.isScheduleUsingCronExpression()) {
entry.setCronExpression(scheduleEntryPage.getCronExpression());
} else {
entry.setCronExpression(null);
}
if (scheduleEntryPage.isScheduleUsingPreceedingEntries()) {
entry.setPrecedingEntries(scheduleEntryPage.getPreceedingEntryIds());
} else {
entry.setPrecedingEntries();
}
// get parameter from current session (as copy)
final Map<String, String> parameter = new HashMap<>(currentSession.getParameter());
// add lock id
if (IdHelper.isValidId(exclusiveLockPage.getLockId())) {
parameter.put(IJobManager.LOCK_ID, exclusiveLockPage.getLockId());
}
// set parameter
entry.setJobParameter(parameter);
// save schedule
schedule.save();
return true;
} catch (final Exception | LinkageError | AssertionError e) {
// remove entry if we created one
// (keep schedule clean, to allow further entry id updates)
if (entry != this.entry) {
schedule.removeEntry(entryId);
}
// handle error
LOG.debug("Error saving schedule. ", e);
NonBlockingMessageDialogs.openError(getShell(), "Error Saving Schedule", "Unable to save schedule. " + e.getMessage(), null);
// Policy.getStatusHandler().show(new Status(IStatus.ERROR, JobsUiActivator.SYMBOLIC_NAME, "Unable to update schedule.", e), "Error Saving Schedule");
return false;
}
}
}