/*
* RapidMiner
*
* Copyright (C) 2001-2011 by Rapid-I and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapid-i.com
*
* 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 com.rapidminer.repository.gui;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.xml.datatype.XMLGregorianCalendar;
import com.michaelbaranov.microba.calendar.DatePicker;
import com.rapid_i.repository.wsimport.ExecutionResponse;
import com.rapid_i.repository.wsimport.MacroDefinition;
import com.rapid_i.repository.wsimport.ProcessContextWrapper;
import com.rapidminer.Process;
import com.rapidminer.ProcessContext;
import com.rapidminer.ProcessLocation;
import com.rapidminer.RepositoryProcessLocation;
import com.rapidminer.gui.processeditor.ProcessContextEditor;
import com.rapidminer.gui.tools.ResourceAction;
import com.rapidminer.gui.tools.ResourceLabel;
import com.rapidminer.gui.tools.ResourceTabbedPane;
import com.rapidminer.gui.tools.SwingTools;
import com.rapidminer.gui.tools.dialogs.ButtonDialog;
import com.rapidminer.io.process.XMLTools;
import com.rapidminer.repository.Repository;
import com.rapidminer.repository.RepositoryConstants;
import com.rapidminer.repository.RepositoryException;
import com.rapidminer.repository.RepositoryLocation;
import com.rapidminer.repository.RepositoryManager;
import com.rapidminer.repository.remote.RemoteRepository;
import com.rapidminer.tools.Observable;
import com.rapidminer.tools.Observer;
import com.rapidminer.tools.container.Pair;
/**
* A dialog that lets the user run a process on a remote server, either now, at
* a fixed later point of time or scheduled by a cron expression.
*
* @author Simon Fischer
*
*/
public class RunRemoteDialog extends ButtonDialog {
private static final long serialVersionUID = 1L;
private static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance(); //new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
private final DatePicker dateField = new DatePicker(new Date(), DATE_FORMAT); // new
// JTextField(DATE_FORMAT.format(new
// Date()), 30);
private final JTextField cronField = new JTextField(30);
private final JComboBox repositoryBox = new JComboBox();
private static int lastRepositoryIndexSelected = 0;
private final JLabel dateLabel = new ResourceLabel("runremotedialog.date");
private final JLabel cronLabel = new ResourceLabel("runremotedialog.cronexpression");
private final JCheckBox startBox = new JCheckBox(new ResourceAction("runremotedialog.cronstart") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
enableComponents();
}
});
private final DatePicker startField = new DatePicker(new Date(), DATE_FORMAT);
private final DatePicker endField = new DatePicker(new Date(), DATE_FORMAT);
private final JCheckBox endBox = new JCheckBox(new ResourceAction("runremotedialog.cronend") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
enableComponents();
}
});
private final JTextField processField = new JTextField(30);
private JRadioButton nowButton;
private JRadioButton onceButton;
private JRadioButton cronButton;;
private final ResourceTabbedPane tabs = new ResourceTabbedPane("runremotedialog");
private ProcessContext context = new ProcessContext();
public RunRemoteDialog(Process process) {
super("runremotedialog", true);
setModal(true);
dateField.setStripTime(false);
dateField.setKeepTime(true);
startField.setStripTime(false);
startField.setKeepTime(true);
endField.setStripTime(false);
endField.setKeepTime(true);
startBox.setSelected(false);
endBox.setSelected(false);
ProcessLocation processLocation = process.getProcessLocation();
if ((processLocation != null) && (processLocation instanceof RepositoryProcessLocation)) {
processField.setText(((RepositoryProcessLocation) processLocation).getRepositoryLocation().getPath());
} else {
processField.setText("");
}
processField.selectAll();
final JButton okButton = makeOkButton();
final JButton cancelButton = makeCancelButton();
repositoryBox.setModel(new DefaultComboBoxModel(RepositoryManager.getInstance(null).getRemoteRepositories().toArray()));
if (repositoryBox.getItemCount() < lastRepositoryIndexSelected){
lastRepositoryIndexSelected = 0;
}
repositoryBox.setSelectedIndex(lastRepositoryIndexSelected);
repositoryBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
okButton.setEnabled(repositoryBox.getSelectedItem() != null);
lastRepositoryIndexSelected = repositoryBox.getSelectedIndex();
}
});
RepositoryManager.getInstance(null).addObserver(new Observer<Repository>() {
@Override
public void update(Observable<Repository> observable, Repository arg) {
repositoryBox.setModel(new DefaultComboBoxModel(RepositoryManager.getInstance(null).getRemoteRepositories().toArray()));
if ((arg != null) && (arg instanceof RemoteRepository)) {
repositoryBox.setSelectedItem(arg);
}
pack();
}
}, true);
JPanel schedulePanel = makeSchedulePanel();
// copy context
// List<String> inputRepositoryLocations = new LinkedList<String>();
// inputRepositoryLocations.addAll(process.getContext().getInputRepositoryLocations());
// context.setInputRepositoryLocations(inputRepositoryLocations);
//
// List<String> outputRepositoryLocations = new LinkedList<String>();
// outputRepositoryLocations.addAll(process.getContext().getOutputRepositoryLocations());
// context.setOutputRepositoryLocations(outputRepositoryLocations);
//
// List<Pair<String, String>> macros = new LinkedList<Pair<String,String>>();
// for (Pair<String,String> macro : process.getContext().getMacros()) {
// macros.add(new Pair<String,String>(macro.getFirst(),macro.getSecond()));
// }
// context.setMacros(macros);
ProcessContextEditor contextPanel = new ProcessContextEditor(process, context);
tabs.addTabI18N("schedule", schedulePanel);
tabs.addTabI18N("context", contextPanel);
// Buttons
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(nowButton);
buttonGroup.add(onceButton);
buttonGroup.add(cronButton);
nowButton.setSelected(true);
layoutDefault(tabs, NORMAL, okButton, cancelButton);
enableComponents();
okButton.setEnabled(repositoryBox.getSelectedItem() != null);
}
private JPanel makeSchedulePanel() {
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1;
c.weighty = 0;
// Repository
JPanel repositoryPanel = new JPanel(new GridBagLayout());
c.insets = new Insets(0, GAP, 0, GAP);
JLabel label = new ResourceLabel("runremotedialog.repository");
label.setLabelFor(repositoryBox);
c.insets = new Insets(GAP, GAP, GAP, GAP);
repositoryPanel.add(label, c);
c.gridwidth = GridBagConstraints.RELATIVE;
c.insets = new Insets(0, GAP, GAP, 0);
repositoryPanel.add(repositoryBox, c);
JButton addRepositoryButton = new JButton(RepositoryBrowser.ADD_REPOSITORY_ACTION);
addRepositoryButton.setText("");
c.weightx = 0;
c.gridwidth = GridBagConstraints.REMAINDER;
c.insets = new Insets(0, 0, GAP, GAP);
repositoryPanel.add(addRepositoryButton, c);
// Process
label = new ResourceLabel("runremotedialog.process_location");
label.setLabelFor(processField);
c.weightx = 1;
c.insets = new Insets(GAP, GAP, 0, GAP);
repositoryPanel.add(label, c);
c.gridwidth = GridBagConstraints.RELATIVE;
c.insets = new Insets(0, GAP, GAP, 0);
repositoryPanel.add(processField, c);
JButton selectButton = new JButton(new ResourceAction(true, "repository_select_location") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
String selected = RepositoryLocationChooser.selectLocation(null, RunRemoteDialog.this);
if (selected != null) {
try {
RepositoryLocation location = new RepositoryLocation(selected);
Repository repository = location.getRepository();
String relative = location.getPath();
repositoryBox.setSelectedItem(repository);
processField.setText(relative);
} catch (Exception ex) {
processField.setText(selected);
}
processField.selectAll();
}
}
});
selectButton.setText("");
c.weightx = 0;
c.gridwidth = GridBagConstraints.REMAINDER;
c.insets = new Insets(0, 0, GAP, GAP);
repositoryPanel.add(selectButton, c);
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
JPanel dummy = new JPanel();
repositoryPanel.add(dummy, c);
// RIGHT SIDE
// Now
JPanel schedPanel = new JPanel(new GridBagLayout());
nowButton = new JRadioButton(new ResourceAction("runremotedialog.now") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
enableComponents();
}
});
c.weightx = 1;
c.insets = new Insets(GAP, GAP, GAP, GAP);
c.gridwidth = GridBagConstraints.REMAINDER;
schedPanel.add(nowButton, c);
// Once
onceButton = new JRadioButton(new ResourceAction("runremotedialog.once") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
enableComponents();
}
});
c.insets = new Insets(3 * GAP, GAP, GAP, GAP);
c.gridwidth = GridBagConstraints.REMAINDER;
schedPanel.add(onceButton, c);
dateLabel.setLabelFor(dateField);
c.insets = new Insets(0, 8 * GAP, 0, GAP);
c.gridwidth = GridBagConstraints.REMAINDER;
schedPanel.add(dateLabel, c);
c.insets = new Insets(0, 8 * GAP, GAP, GAP);
schedPanel.add(dateField, c);
// Cron
cronButton = new JRadioButton(new ResourceAction("runremotedialog.cron") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
enableComponents();
}
});
c.insets = new Insets(3 * GAP, GAP, GAP, GAP);
c.gridwidth = GridBagConstraints.REMAINDER;
schedPanel.add(cronButton, c);
c.insets = new Insets(0, 8 * GAP, 0, GAP);
cronLabel.setLabelFor(cronField);
schedPanel.add(cronLabel, c);
c.insets = new Insets(0, 8 * GAP, GAP, 0);
c.gridwidth = GridBagConstraints.RELATIVE;
schedPanel.add(cronField, c);
c.insets = new Insets(0, 0, GAP, GAP);
// ResourceLabel cronHelp = new ResourceLabel("cron_help");
JButton cronHelpButton = new JButton(new ResourceAction(true, "cron_help") {
private static final long serialVersionUID = 1L;
{
putValue(Action.NAME, "");
}
@Override
public void actionPerformed(ActionEvent e) {
SwingTools.showMessageDialog("cron_long_help");
}
});
c.weightx = 0;
c.gridwidth = GridBagConstraints.REMAINDER;
schedPanel.add(cronHelpButton, c);
c.weightx = 1;
c.insets = new Insets(GAP, 8 * GAP, 0, GAP);
schedPanel.add(startBox, c);
c.insets = new Insets(0, 8 * GAP, GAP, GAP);
schedPanel.add(startField, c);
c.insets = new Insets(GAP, 8 * GAP, 0, GAP);
schedPanel.add(endBox, c);
c.insets = new Insets(0, 8 * GAP, GAP, GAP);
schedPanel.add(endField, c);
JPanel panel = new JPanel(createGridLayout(1, 2));
panel.add(repositoryPanel);
panel.add(schedPanel);
return panel;
}
private void enableComponents() {
dateLabel.setEnabled(onceButton.isSelected());
dateField.setEnabled(onceButton.isSelected());
cronLabel.setEnabled(cronButton.isSelected());
cronField.setEnabled(cronButton.isSelected());
startBox.setEnabled(cronButton.isSelected());
endBox.setEnabled(cronButton.isSelected());
startField.setEnabled(cronButton.isSelected() && startBox.isSelected());
endField.setEnabled(cronButton.isSelected() && endBox.isSelected());
}
public static void showDialog(Process process) {
RunRemoteDialog d = new RunRemoteDialog(process);
d.setVisible(true);
}
@Override
public void ok() {
RemoteRepository repos = (RemoteRepository) repositoryBox.getSelectedItem();
if (repos != null) {
String location = processField.getText();
ProcessContextWrapper pcWrapper = new ProcessContextWrapper();
for (String loc : context.getInputRepositoryLocations()) {
pcWrapper.getInputRepositoryLocations().add(loc);
}
for (String loc : context.getOutputRepositoryLocations()) {
pcWrapper.getOutputRepositoryLocations().add(loc);
}
for (Pair<String, String> macro : context.getMacros()) {
final MacroDefinition macroDef = new MacroDefinition();
macroDef.setKey(macro.getFirst());
macroDef.setValue(macro.getSecond());
pcWrapper.getMacros().add(macroDef);
}
ExecutionResponse response;
if (nowButton.isSelected()) {
try {
response = repos.getProcessService().executeProcessSimple(location, null, pcWrapper);
} catch (RepositoryException e) {
SwingTools.showSimpleErrorMessage("error_connecting_to_server", e);
return;
}
} else if (onceButton.isSelected()) {
try {
Date date = dateField.getDate();
response = repos.getProcessService().executeProcessSimple(location, XMLTools.getXMLGregorianCalendar(date), pcWrapper);
} catch (RepositoryException e) {
SwingTools.showSimpleErrorMessage("error_connecting_to_server", e);
return;
}
} else if (cronButton.isSelected()) {
try {
XMLGregorianCalendar start = startBox.isSelected() ? XMLTools.getXMLGregorianCalendar(startField.getDate()) : null;
XMLGregorianCalendar end = endBox.isSelected() ? XMLTools.getXMLGregorianCalendar(endField.getDate()) : null;
response = repos.getProcessService().executeProcessCron(location, cronField.getText(), start, end, pcWrapper);
} catch (RepositoryException e) {
SwingTools.showSimpleErrorMessage("error_connecting_to_server ", e);
return;
}
} else {
throw new RuntimeException("No radio button selected. (This cannot happen)");
}
if (response.getStatus() != RepositoryConstants.OK) {
SwingTools.showSimpleErrorMessage("run_proc_remote", response.getErrorMessage());
} else {
dispose();
Date firstExec = response.getFirstExecution().toGregorianCalendar().getTime();
JOptionPane.showMessageDialog(this, "Process will first run on: " + firstExec, "Process scheduled", JOptionPane.INFORMATION_MESSAGE);
}
}
}
}