/*
* 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.process;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.TreePath;
import com.rapid_i.repository.wsimport.ProcessResponse;
import com.rapid_i.repository.wsimport.Response;
import com.rapidminer.RepositoryProcessLocation;
import com.rapidminer.gui.MainFrame;
import com.rapidminer.gui.actions.OpenAction;
import com.rapidminer.gui.actions.RunRemoteAction;
import com.rapidminer.gui.tools.ExtendedJScrollPane;
import com.rapidminer.gui.tools.ResourceAction;
import com.rapidminer.gui.tools.ResourceDockKey;
import com.rapidminer.gui.tools.ResourceLabel;
import com.rapidminer.gui.tools.SwingTools;
import com.rapidminer.gui.tools.ViewToolBar;
import com.rapidminer.gui.tools.components.ToolTipWindow;
import com.rapidminer.gui.tools.components.ToolTipWindow.TipProvider;
import com.rapidminer.repository.IOObjectEntry;
import com.rapidminer.repository.MalformedRepositoryLocationException;
import com.rapidminer.repository.RemoteProcessState;
import com.rapidminer.repository.Repository;
import com.rapidminer.repository.RepositoryConstants;
import com.rapidminer.repository.RepositoryException;
import com.rapidminer.repository.RepositoryLocation;
import com.rapidminer.repository.gui.ToolTipProviderHelper;
import com.rapidminer.repository.remote.RemoteRepository;
import com.rapidminer.tools.I18N;
import com.rapidminer.tools.LogService;
import com.vlsolutions.swing.docking.DockKey;
import com.vlsolutions.swing.docking.Dockable;
/**
* Displays a tree of processes running on a remote server.
*
* @author Simon Fischer, Tobias Malbrecht
*/
public class RemoteProcessViewer extends JPanel implements Dockable {
private static final long serialVersionUID = 1L;
private JTree tree;
private RemoteProcessesTreeModel treeModel;
private Action STOP_ACTION = new ResourceAction(true, "remoteprocessviewer.stop") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
TreePath selectionPath = tree.getSelectionPath();
if (selectionPath != null) {
Object selection = selectionPath.getLastPathComponent();
if (selection instanceof ProcessResponse) {
ProcessResponse processResponse = (ProcessResponse)selection;
if (!RemoteProcessState.valueOf(processResponse.getState()).isTerminated()) {
if (selectionPath.getLastPathComponent() instanceof ProcessResponse) {
RemoteRepository repository = (RemoteRepository) selectionPath.getPath()[1];
try {
Response stopResponse = repository.getProcessService().stopProcess(processResponse.getId());
if (stopResponse.getStatus() != RepositoryConstants.OK) {
SwingTools.showVerySimpleErrorMessage("remoteprocessviewer.stop_failed", stopResponse.getErrorMessage());
}
} catch (RepositoryException e1) {
SwingTools.showSimpleErrorMessage("remoteprocessviewer.stop_failed", e1);
}
}
}
}
}
}
};
private Action SHOW_LOG_ACTION = new ResourceAction(true, "remoteprocessviewer.show_log") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
TreePath selectionPath = tree.getSelectionPath();
if (selectionPath != null) {
Object selection = selectionPath.getLastPathComponent();
if (selection instanceof ProcessResponse) {
ProcessResponse processResponse = (ProcessResponse)selection;
if (selection instanceof ProcessResponse) {
RemoteRepository repository = (RemoteRepository) selectionPath.getPath()[1];
repository.showLog(processResponse.getId());
}
}
}
}
};
private Action OPEN_ACTION = new ResourceAction(true, "remoteprocessviewer.open") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
TreePath selectionPath = tree.getSelectionPath();
if (selectionPath != null) {
Object selection = selectionPath.getLastPathComponent();
if (selection instanceof ProcessResponse) {
Repository repository = (Repository) selectionPath.getPath()[1];
String locStr = RepositoryLocation.REPOSITORY_PREFIX+repository.getName()+
((ProcessResponse) selection).getProcessLocation();
RepositoryLocation loc;
try {
loc = new RepositoryLocation(locStr);
} catch (MalformedRepositoryLocationException e1) {
SwingTools.showSimpleErrorMessage("while_loading", e1, locStr, e1.getMessage());
return;
}
OpenAction.open(new RepositoryProcessLocation(loc), true);
} else if (selection instanceof OutputLocation) {
try {
Repository repository = (Repository) selectionPath.getPath()[1];
ProcessResponse proResponse = (ProcessResponse) selectionPath.getPath()[2];
RepositoryLocation procLoc = new RepositoryLocation(RepositoryLocation.REPOSITORY_PREFIX+repository.getName()+
proResponse.getProcessLocation());
RepositoryLocation ioLoc = new RepositoryLocation(procLoc.parent(), ((OutputLocation)selection).getLocation());
OpenAction.showAsResult((IOObjectEntry)ioLoc.locateEntry());
} catch (Exception e1) {
SwingTools.showSimpleErrorMessage("cannot_fetch_data_from_repository", e1);
}
}
}
}
};
private Action BROWSE_ACTION = new ResourceAction(true, "remoteprocessviewer.browse") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
TreePath selectionPath = tree.getSelectionPath();
if (selectionPath != null) {
Object selection = selectionPath.getLastPathComponent();
if (selection instanceof ProcessResponse) {
RemoteRepository repository = (RemoteRepository) selectionPath.getPath()[1];
repository.browse(((ProcessResponse) selection).getProcessLocation());
} else if (selection instanceof OutputLocation) {
try {
RemoteRepository repository = (RemoteRepository) selectionPath.getPath()[1];
ProcessResponse proResponse = (ProcessResponse) selectionPath.getPath()[2];
RepositoryLocation procLoc = new RepositoryLocation(RepositoryLocation.REPOSITORY_PREFIX+repository.getName()+
proResponse.getProcessLocation());
RepositoryLocation ioLoc = new RepositoryLocation(procLoc.parent(), ((OutputLocation)selection).getLocation());
repository.browse(ioLoc.getPath());
} catch (Exception e1) {
SwingTools.showSimpleErrorMessage("cannot_fetch_data_from_repository", e1);
}
}
}
}
};
private Date sessionStartDate = new Date();
private JComboBox sinceWhenCombo = new JComboBox(new Object[] {
I18N.getMessage(I18N.getGUIBundle(), "gui.combo.remoteprocessviewer.since_session_start"),
I18N.getMessage(I18N.getGUIBundle(), "gui.combo.remoteprocessviewer.for_today"),
I18N.getMessage(I18N.getGUIBundle(), "gui.combo.remoteprocessviewer.all")
});
public RemoteProcessViewer() {
setLayout(new BorderLayout());
treeModel = new RemoteProcessesTreeModel();
treeModel.setSince(sessionStartDate);
tree = new JTree(treeModel);
tree.setCellRenderer(new RemoteProcessTreeCellRenderer());
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
JScrollPane scrollPane = new ExtendedJScrollPane(tree);
scrollPane.setBorder(null);
add(scrollPane, BorderLayout.CENTER);
JToolBar toolBar = new ViewToolBar();
add(toolBar, BorderLayout.NORTH);
toolBar.add(new RunRemoteAction());
toolBar.add(OPEN_ACTION);
toolBar.add(BROWSE_ACTION);
toolBar.add(STOP_ACTION);
toolBar.add(SHOW_LOG_ACTION);
toolBar.addSeparator();
ResourceLabel label = new ResourceLabel("remoteprocessviewer.filter");
label.setLabelFor(sinceWhenCombo);
toolBar.add(label);
toolBar.add(sinceWhenCombo);
new ToolTipWindow(new TipProvider() {
@Override
public Component getCustomComponent(Object id) {
if (id instanceof TreePath) {
RepositoryLocation loc = getSelectedRepositoryLocation((TreePath) id);
if (loc != null) {
try {
return ToolTipProviderHelper.getCustomComponent(loc.locateEntry());
} catch (RepositoryException e) {
LogService.getRoot().log(Level.WARNING, "Error locating entry for "+loc+": "+e, e);
return null;
}
} else {
return null;
}
} else {
return null;
}
}
@Override
public Object getIdUnder(Point point) {
TreePath path = tree.getPathForLocation((int)point.getX(), (int)point.getY());
if (path != null) {
return path;
} else {
return null;
}
}
@Override
public String getTip(Object o) {
if (o instanceof TreePath) {
Object last = ((TreePath) o).getLastPathComponent();
if (last instanceof ProcessResponse) {
ProcessResponse pr = (ProcessResponse) last;
StringBuilder b = new StringBuilder();
b.append("<html><body>");
b.append("<strong>").append(pr.getProcessLocation()).append("</strong> ");
if (RemoteProcessState.valueOf(pr.getState()) == RemoteProcessState.FAILED) {
b.append("<span style=\"color:red\">(").append(pr.getState().toLowerCase()).append(")</span><br/>");
} else {
b.append("(").append(pr.getState().toLowerCase()).append(")<br/>");
}
if (pr.getStartTime() != null) {
b.append("<em>Started: </em>").append(DateFormat.getDateTimeInstance().format(pr.getStartTime().toGregorianCalendar().getTime())).append("<br/>");
}
if (pr.getCompletionTime() != null) {
b.append("<em>Completed: </em>").append(DateFormat.getDateTimeInstance().format(pr.getCompletionTime().toGregorianCalendar().getTime())).append("<br/>");
}
if (pr.getException() != null) {
b.append("<span style=\"color:red\">").append(pr.getException()).append("</span><br/>");
}
RemoteRepository repos = (RemoteRepository) ((TreePath)o).getPath()[1];
b.append("<a href=\""+repos.getProcessLogURI(pr.getId()).toString()+"\">View Log</a>");
b.append("</body></html>");
return b.toString();
} else {
RepositoryLocation loc = getSelectedRepositoryLocation((TreePath)o);
if (loc != null) {
try {
return ToolTipProviderHelper.getTip(loc.locateEntry());
} catch (RepositoryException e) {
LogService.getRoot().log(Level.WARNING, "Error locating entry for "+loc+": "+e, e);
return null;
}
} else {
return null;
}
}
} else {
return null;
}
}
}, tree);
sinceWhenCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
switch (sinceWhenCombo.getSelectedIndex()) {
case 0:
treeModel.setSince(sessionStartDate);
break;
case 1:
Calendar today = new GregorianCalendar();
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
treeModel.setSince(today.getTime());
break;
case 2:
treeModel.setSince(null);
}
}
});
tree.addTreeExpansionListener(new TreeExpansionListener() {
@Override
public void treeExpanded(TreeExpansionEvent event) {
Object leaf = event.getPath().getLastPathComponent();
if (leaf instanceof RemoteRepository) {
treeModel.observe((RemoteRepository) leaf);
}
}
@Override
public void treeCollapsed(TreeExpansionEvent event) {
Object leaf = event.getPath().getLastPathComponent();
if (leaf instanceof RemoteRepository) {
treeModel.ignore((RemoteRepository) leaf);
}
}
});
}
private RepositoryLocation getSelectedRepositoryLocation(TreePath selectionPath) {
try {
if (selectionPath != null) {
Object selection = selectionPath.getLastPathComponent();
if (selection instanceof ProcessResponse) {
Repository repository = (Repository) selectionPath.getPath()[1];
return new RepositoryLocation(RepositoryLocation.REPOSITORY_PREFIX+repository.getName()+
((ProcessResponse) selection).getProcessLocation());
} else if (selection instanceof OutputLocation) {
Repository repository = (Repository) selectionPath.getPath()[1];
ProcessResponse proResponse = (ProcessResponse) selectionPath.getPath()[2];
RepositoryLocation procLoc = new RepositoryLocation(RepositoryLocation.REPOSITORY_PREFIX+repository.getName()+
proResponse.getProcessLocation());
return new RepositoryLocation(procLoc.parent(), ((OutputLocation)selection).getLocation());
}
}
} catch (MalformedRepositoryLocationException e) {
return null;
}
return null;
}
public static final String PROCESS_PANEL_DOCK_KEY = "remote_process_viewer";
private final DockKey DOCK_KEY = new ResourceDockKey(PROCESS_PANEL_DOCK_KEY);
{
DOCK_KEY.setDockGroup(MainFrame.DOCK_GROUP_ROOT);
}
@Override
public Component getComponent() {
return this;
}
@Override
public DockKey getDockKey() {
return DOCK_KEY;
}
}