http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuAction.java b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuAction.java new file mode 100644 index 0000000..eeaecb3 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuAction.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl.menu; + +import static net.sf.taverna.t2.workbench.file.impl.menu.FileSaveMenuSection.FILE_SAVE_SECTION_URI; + +import javax.swing.Action; + +import net.sf.taverna.t2.ui.menu.AbstractMenuAction; +import net.sf.taverna.t2.workbench.edits.EditManager; +import net.sf.taverna.t2.workbench.file.FileManager; +import net.sf.taverna.t2.workbench.file.impl.actions.SaveWorkflowAction; + +public class FileSaveMenuAction extends AbstractMenuAction { + private final EditManager editManager; + private final FileManager fileManager; + + public FileSaveMenuAction(EditManager editManager, FileManager fileManager) { + super(FILE_SAVE_SECTION_URI, 10); + this.editManager = editManager; + this.fileManager = fileManager; + } + + @Override + protected Action createAction() { + return new SaveWorkflowAction(editManager, fileManager); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuSection.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuSection.java b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuSection.java new file mode 100644 index 0000000..a75a855 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuSection.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl.menu; + +import java.net.URI; + +import net.sf.taverna.t2.ui.menu.AbstractMenuSection; + +public class FileSaveMenuSection extends AbstractMenuSection { + public static final URI FILE_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#file"); + public static final URI FILE_SAVE_SECTION_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#fileSaveSection"); + + public FileSaveMenuSection() { + super(FILE_URI, 40, FILE_SAVE_SECTION_URI); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/WorkflowsMenu.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/WorkflowsMenu.java b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/WorkflowsMenu.java new file mode 100644 index 0000000..e056572 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/WorkflowsMenu.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl.menu; + +import static java.awt.event.KeyEvent.VK_0; +import static java.awt.event.KeyEvent.VK_W; +import static javax.swing.Action.MNEMONIC_KEY; +import static javax.swing.SwingUtilities.invokeLater; +import static net.sf.taverna.t2.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; + +import java.awt.Component; +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.ButtonGroup; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; + +import net.sf.taverna.t2.lang.observer.Observable; +import net.sf.taverna.t2.lang.observer.Observer; +import net.sf.taverna.t2.ui.menu.AbstractMenuCustom; +import net.sf.taverna.t2.workbench.edits.EditManager; +import net.sf.taverna.t2.workbench.edits.EditManager.AbstractDataflowEditEvent; +import net.sf.taverna.t2.workbench.edits.EditManager.EditManagerEvent; +import net.sf.taverna.t2.workbench.file.FileManager; +import net.sf.taverna.t2.workbench.file.events.AbstractDataflowEvent; +import net.sf.taverna.t2.workbench.file.events.FileManagerEvent; +import uk.org.taverna.scufl2.api.container.WorkflowBundle; + +public class WorkflowsMenu extends AbstractMenuCustom { + private EditManagerObserver editManagerObserver = new EditManagerObserver(); + private FileManager fileManager; + private FileManagerObserver fileManagerObserver = new FileManagerObserver(); + + private JMenu workflowsMenu; + + public WorkflowsMenu(EditManager editManager, FileManager fileManager) { + super(DEFAULT_MENU_BAR, 900); + this.fileManager = fileManager; + fileManager.addObserver(fileManagerObserver); + editManager.addObserver(editManagerObserver); + } + + @Override + protected Component createCustomComponent() { + DummyAction action = new DummyAction("Workflows"); + action.putValue(MNEMONIC_KEY, VK_W); + + workflowsMenu = new JMenu(action); + + updateWorkflowsMenu(); + return workflowsMenu; + } + + public void updateWorkflowsMenu() { + invokeLater(new Runnable() { + @Override + public void run() { + updateWorkflowsMenuUI(); + } + }); + } + + protected void updateWorkflowsMenuUI() { + workflowsMenu.setEnabled(false); + workflowsMenu.removeAll(); + ButtonGroup workflowsGroup = new ButtonGroup(); + + int i = 0; + WorkflowBundle currentDataflow = fileManager.getCurrentDataflow(); + for (WorkflowBundle workflowBundle : fileManager.getOpenDataflows()) { + String name = fileManager.getDataflowName(workflowBundle); + if (fileManager.isDataflowChanged(workflowBundle)) + name = "*" + name; + // A counter + name = ++i + " " + name; + + SwitchWorkflowAction switchWorkflowAction = new SwitchWorkflowAction( + name, workflowBundle); + if (i < 10) + switchWorkflowAction.putValue(MNEMONIC_KEY, new Integer(VK_0 + + i)); + + JRadioButtonMenuItem switchWorkflowMenuItem = new JRadioButtonMenuItem( + switchWorkflowAction); + workflowsGroup.add(switchWorkflowMenuItem); + if (workflowBundle.equals(currentDataflow)) + switchWorkflowMenuItem.setSelected(true); + workflowsMenu.add(switchWorkflowMenuItem); + } + if (i == 0) + workflowsMenu.add(new NoWorkflowsOpen()); + workflowsMenu.setEnabled(true); + workflowsMenu.revalidate(); + } + + private final class EditManagerObserver implements + Observer<EditManagerEvent> { + @Override + public void notify(Observable<EditManagerEvent> sender, + EditManagerEvent message) throws Exception { + if (message instanceof AbstractDataflowEditEvent) + updateWorkflowsMenu(); + } + } + + private final class FileManagerObserver implements + Observer<FileManagerEvent> { + @Override + public void notify(Observable<FileManagerEvent> sender, + FileManagerEvent message) throws Exception { + if (message instanceof AbstractDataflowEvent) + updateWorkflowsMenu(); + // TODO: Don't rebuild whole menu + } + } + + @SuppressWarnings("serial") + private final class NoWorkflowsOpen extends AbstractAction { + private NoWorkflowsOpen() { + super("No workflows open"); + setEnabled(false); + } + + @Override + public void actionPerformed(ActionEvent e) { + // No-op + } + } + + @SuppressWarnings("serial") + private final class SwitchWorkflowAction extends AbstractAction { + private final WorkflowBundle workflowBundle; + + private SwitchWorkflowAction(String name, WorkflowBundle workflowBundle) { + super(name); + this.workflowBundle = workflowBundle; + } + + @Override + public void actionPerformed(ActionEvent e) { + fileManager.setCurrentDataflow(workflowBundle); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/CloseToolbarAction.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/CloseToolbarAction.java b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/CloseToolbarAction.java new file mode 100644 index 0000000..68ef3f9 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/CloseToolbarAction.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl.toolbar; + +import static net.sf.taverna.t2.workbench.file.impl.toolbar.FileToolbarMenuSection.FILE_TOOLBAR_SECTION; + +import java.net.URI; + +import javax.swing.Action; + +import net.sf.taverna.t2.ui.menu.AbstractMenuAction; +import net.sf.taverna.t2.workbench.edits.EditManager; +import net.sf.taverna.t2.workbench.file.FileManager; +import net.sf.taverna.t2.workbench.file.impl.actions.CloseWorkflowAction; + +/** + * Action to close the current workflow. + * + * @author Alex Nenadic + */ +public class CloseToolbarAction extends AbstractMenuAction { + private static final URI FILE_CLOSE_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#fileToolbarClose"); + private final EditManager editManager; + private final FileManager fileManager; + + public CloseToolbarAction(EditManager editManager, FileManager fileManager) { + super(FILE_TOOLBAR_SECTION, 30, FILE_CLOSE_URI); + this.editManager = editManager; + this.fileManager = fileManager; + } + + @Override + protected Action createAction() { + return new CloseWorkflowAction(editManager, fileManager); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/FileToolbarMenuSection.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/FileToolbarMenuSection.java b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/FileToolbarMenuSection.java new file mode 100644 index 0000000..257d590 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/FileToolbarMenuSection.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl.toolbar; + +import static net.sf.taverna.t2.ui.menu.DefaultToolBar.DEFAULT_TOOL_BAR; + +import java.net.URI; + +import net.sf.taverna.t2.ui.menu.AbstractMenuSection; + +public class FileToolbarMenuSection extends AbstractMenuSection { + public static final URI FILE_TOOLBAR_SECTION = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#fileToolbarSection"); + + public FileToolbarMenuSection() { + super(DEFAULT_TOOL_BAR, 10, FILE_TOOLBAR_SECTION); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/NewToolbarAction.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/NewToolbarAction.java b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/NewToolbarAction.java new file mode 100644 index 0000000..2c8e922 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/NewToolbarAction.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl.toolbar; + +import static net.sf.taverna.t2.workbench.file.impl.toolbar.FileToolbarMenuSection.FILE_TOOLBAR_SECTION; + +import java.net.URI; + +import javax.swing.Action; + +import net.sf.taverna.t2.ui.menu.AbstractMenuAction; +import net.sf.taverna.t2.workbench.file.FileManager; +import net.sf.taverna.t2.workbench.file.impl.actions.NewWorkflowAction; + +public class NewToolbarAction extends AbstractMenuAction { + private static final URI FILE_NEW_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#fileToolbarNew"); + private final FileManager fileManager; + + public NewToolbarAction(FileManager fileManager) { + super(FILE_TOOLBAR_SECTION, 10, FILE_NEW_URI); + this.fileManager = fileManager; + } + + @Override + protected Action createAction() { + return new NewWorkflowAction(fileManager); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenToolbarAction.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenToolbarAction.java b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenToolbarAction.java new file mode 100644 index 0000000..ae99509 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenToolbarAction.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl.toolbar; + +import static net.sf.taverna.t2.workbench.file.impl.toolbar.FileToolbarMenuSection.FILE_TOOLBAR_SECTION; + +import java.net.URI; + +import javax.swing.Action; + +import net.sf.taverna.t2.ui.menu.AbstractMenuAction; +import net.sf.taverna.t2.workbench.file.FileManager; +import net.sf.taverna.t2.workbench.file.impl.actions.OpenWorkflowAction; + +public class OpenToolbarAction extends AbstractMenuAction { + private static final URI FILE_OPEN_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#fileToolbarOpen"); + private final FileManager fileManager; + + public OpenToolbarAction(FileManager fileManager) { + super(FILE_TOOLBAR_SECTION, 20, FILE_OPEN_URI); + this.fileManager = fileManager; + } + + @Override + protected Action createAction() { + return new OpenWorkflowAction(fileManager); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenWorkflowFromURLToolbarAction.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenWorkflowFromURLToolbarAction.java b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenWorkflowFromURLToolbarAction.java new file mode 100644 index 0000000..2554063 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenWorkflowFromURLToolbarAction.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl.toolbar; + +import static net.sf.taverna.t2.workbench.file.impl.toolbar.FileToolbarMenuSection.FILE_TOOLBAR_SECTION; + +import java.net.URI; + +import javax.swing.Action; + +import net.sf.taverna.t2.ui.menu.AbstractMenuAction; +import net.sf.taverna.t2.workbench.file.FileManager; +import net.sf.taverna.t2.workbench.file.impl.actions.OpenWorkflowFromURLAction; + +public class OpenWorkflowFromURLToolbarAction extends AbstractMenuAction { + private static final URI FILE_OPEN_FROM_URL_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#fileToolbarOpenFromURL"); + private final FileManager fileManager; + + public OpenWorkflowFromURLToolbarAction(FileManager fileManager) { + super(FILE_TOOLBAR_SECTION, 25, FILE_OPEN_FROM_URL_URI); + this.fileManager = fileManager; + } + + @Override + protected Action createAction() { + return new OpenWorkflowFromURLAction(null, fileManager); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/SaveToolbarAction.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/SaveToolbarAction.java b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/SaveToolbarAction.java new file mode 100644 index 0000000..53ba720 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/SaveToolbarAction.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl.toolbar; + +import static net.sf.taverna.t2.workbench.file.impl.toolbar.FileToolbarMenuSection.FILE_TOOLBAR_SECTION; + +import java.net.URI; + +import javax.swing.Action; + +import net.sf.taverna.t2.ui.menu.AbstractMenuAction; +import net.sf.taverna.t2.workbench.edits.EditManager; +import net.sf.taverna.t2.workbench.file.FileManager; +import net.sf.taverna.t2.workbench.file.impl.actions.SaveWorkflowAction; + +public class SaveToolbarAction extends AbstractMenuAction { + private static final URI FILE_SAVE_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#fileToolbarSave"); + private final EditManager editManager; + private final FileManager fileManager; + + public SaveToolbarAction(EditManager editManager, FileManager fileManager) { + super(FILE_TOOLBAR_SECTION, 40, FILE_SAVE_URI); + this.editManager = editManager; + this.fileManager = fileManager; + } + + @Override + protected Action createAction() { + return new SaveWorkflowAction(editManager, fileManager); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent b/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent new file mode 100644 index 0000000..100915c --- /dev/null +++ b/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent @@ -0,0 +1,20 @@ +net.sf.taverna.t2.workbench.file.impl.menu.FileCloseMenuAction +net.sf.taverna.t2.workbench.file.impl.menu.FileNewMenuAction +net.sf.taverna.t2.workbench.file.impl.menu.FileOpenMenuAction +net.sf.taverna.t2.workbench.file.impl.menu.FileOpenFromURLMenuAction +net.sf.taverna.t2.workbench.file.impl.menu.FileOpenMenuSection +net.sf.taverna.t2.workbench.file.impl.menu.FileOpenRecentMenuAction +net.sf.taverna.t2.workbench.file.impl.menu.FileSaveMenuSection +net.sf.taverna.t2.workbench.file.impl.menu.FileSaveMenuAction +net.sf.taverna.t2.workbench.file.impl.menu.FileSaveAllMenuAction +net.sf.taverna.t2.workbench.file.impl.menu.FileSaveAsMenuAction + +net.sf.taverna.t2.workbench.file.impl.menu.WorkflowsMenu +net.sf.taverna.t2.workbench.file.impl.menu.FileCloseAllMenuAction + +net.sf.taverna.t2.workbench.file.impl.toolbar.FileToolbarMenuSection +net.sf.taverna.t2.workbench.file.impl.toolbar.NewToolbarAction +net.sf.taverna.t2.workbench.file.impl.toolbar.OpenToolbarAction +net.sf.taverna.t2.workbench.file.impl.toolbar.OpenWorkflowFromURLToolbarAction +net.sf.taverna.t2.workbench.file.impl.toolbar.SaveToolbarAction +net.sf.taverna.t2.workbench.file.impl.toolbar.CloseToolbarAction http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ShutdownSPI ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ShutdownSPI b/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ShutdownSPI new file mode 100644 index 0000000..cc53d36 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ShutdownSPI @@ -0,0 +1 @@ +net.sf.taverna.t2.workbench.file.impl.hooks.CloseWorkflowsOnShutdown http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler b/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler new file mode 100644 index 0000000..cfd1c7a --- /dev/null +++ b/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler @@ -0,0 +1,2 @@ +net.sf.taverna.t2.workbench.file.impl.T2DataflowOpener +net.sf.taverna.t2.workbench.file.impl.DataflowFromDataflowPersistenceHandler \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.file.FileManager ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.file.FileManager b/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.file.FileManager new file mode 100644 index 0000000..656feeb --- /dev/null +++ b/taverna-workbench-file-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.file.FileManager @@ -0,0 +1 @@ +net.sf.taverna.t2.workbench.file.impl.FileManagerImpl \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/resources/META-INF/spring/file-impl-context-osgi.xml ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/resources/META-INF/spring/file-impl-context-osgi.xml b/taverna-workbench-file-impl/src/main/resources/META-INF/spring/file-impl-context-osgi.xml new file mode 100644 index 0000000..7c6e290 --- /dev/null +++ b/taverna-workbench-file-impl/src/main/resources/META-INF/spring/file-impl-context-osgi.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans:beans xmlns="http://www.springframework.org/schema/osgi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:beans="http://www.springframework.org/schema/beans" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/osgi + http://www.springframework.org/schema/osgi/spring-osgi.xsd"> + + <service ref="FileCloseMenuAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="file.close" /> + </service-properties> + </service> + <service ref="FileNewMenuAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="file.new" /> + </service-properties> + </service> + <service ref="FileOpenMenuAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="file.open" /> + </service-properties> + </service> + <service ref="FileOpenFromURLMenuAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="file.open.url" /> + </service-properties> + </service> + <service ref="FileOpenMenuSection" auto-export="interfaces" /> + <service ref="FileOpenRecentMenuAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="file.open.recent" /> + </service-properties> + </service> + <service ref="FileSaveMenuSection" auto-export="interfaces" /> + <service ref="FileSaveMenuAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="file.save" /> + </service-properties> + </service> + <service ref="FileSaveAllMenuAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="file.save.all" /> + </service-properties> + </service> + <service ref="FileSaveAsMenuAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="file.save.as" /> + </service-properties> + </service> + <service ref="WorkflowsMenu" auto-export="interfaces" /> + <service ref="FileCloseAllMenuAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="file.close.all" /> + </service-properties> + </service> + <service ref="FileToolbarMenuSection" auto-export="interfaces" /> + <service ref="NewToolbarAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="toolbar.new" /> + </service-properties> + </service> + <service ref="OpenToolbarAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="toolbar.open" /> + </service-properties> + </service> + <service ref="OpenWorkflowFromURLToolbarAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="toolbar.open.url" /> + </service-properties> + </service> + <service ref="SaveToolbarAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="toolbar.save" /> + </service-properties> + </service> + <service ref="CloseToolbarAction" auto-export="interfaces"> + <service-properties> + <beans:entry key="menu.action" value="toolbar.close" /> + </service-properties> + </service> + + <service ref="T2DataflowOpener" interface="net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler" /> + + <service ref="WorkflowBundleOpener" interface="net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler" /> + <service ref="WorkflowBundleSaver" interface="net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler" /> + + <service ref="CloseWorkflowsOnShutdown" interface="net.sf.taverna.t2.workbench.ShutdownSPI" /> + + <service ref="FileManagerImpl" interface="net.sf.taverna.t2.workbench.file.FileManager" /> + + <reference id="editManager" interface="net.sf.taverna.t2.workbench.edits.EditManager" /> + <reference id="applicationConfiguration" interface="uk.org.taverna.configuration.app.ApplicationConfiguration" /> + <reference id="workflowBundleIO" interface="uk.org.taverna.scufl2.api.io.WorkflowBundleIO" /> + + <list id="dataflowPersistenceHandlers" interface="net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler" cardinality="0..N"> + <listener ref="DataflowPersistenceHandlerRegistry" bind-method="update" unbind-method="update" /> + </list> +</beans:beans> http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/main/resources/META-INF/spring/file-impl-context.xml ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/main/resources/META-INF/spring/file-impl-context.xml b/taverna-workbench-file-impl/src/main/resources/META-INF/spring/file-impl-context.xml new file mode 100644 index 0000000..493df5f --- /dev/null +++ b/taverna-workbench-file-impl/src/main/resources/META-INF/spring/file-impl-context.xml @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd"> + + <bean id="FileCloseMenuAction" class="net.sf.taverna.t2.workbench.file.impl.menu.FileCloseMenuAction"> + <constructor-arg ref="editManager" /> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="FileNewMenuAction" class="net.sf.taverna.t2.workbench.file.impl.menu.FileNewMenuAction"> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="FileOpenMenuAction" class="net.sf.taverna.t2.workbench.file.impl.menu.FileOpenMenuAction"> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="FileOpenFromURLMenuAction" class="net.sf.taverna.t2.workbench.file.impl.menu.FileOpenFromURLMenuAction"> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="FileOpenMenuSection" class="net.sf.taverna.t2.workbench.file.impl.menu.FileOpenMenuSection" /> + <bean id="FileOpenRecentMenuAction" class="net.sf.taverna.t2.workbench.file.impl.menu.FileOpenRecentMenuAction"> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + <property name="applicationConfiguration" ref="applicationConfiguration"/> + </bean> + <bean id="FileSaveMenuSection" class="net.sf.taverna.t2.workbench.file.impl.menu.FileSaveMenuSection" /> + <bean id="FileSaveMenuAction" class="net.sf.taverna.t2.workbench.file.impl.menu.FileSaveMenuAction"> + <constructor-arg ref="editManager" /> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="FileSaveAllMenuAction" class="net.sf.taverna.t2.workbench.file.impl.menu.FileSaveAllMenuAction"> + <constructor-arg ref="editManager" /> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="FileSaveAsMenuAction" class="net.sf.taverna.t2.workbench.file.impl.menu.FileSaveAsMenuAction"> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="WorkflowsMenu" class="net.sf.taverna.t2.workbench.file.impl.menu.WorkflowsMenu"> + <constructor-arg ref="editManager" /> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="FileCloseAllMenuAction" class="net.sf.taverna.t2.workbench.file.impl.menu.FileCloseAllMenuAction"> + <constructor-arg ref="editManager" /> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="FileToolbarMenuSection" class="net.sf.taverna.t2.workbench.file.impl.toolbar.FileToolbarMenuSection" /> + <bean id="NewToolbarAction" class="net.sf.taverna.t2.workbench.file.impl.toolbar.NewToolbarAction"> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="OpenToolbarAction" class="net.sf.taverna.t2.workbench.file.impl.toolbar.OpenToolbarAction"> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="OpenWorkflowFromURLToolbarAction" class="net.sf.taverna.t2.workbench.file.impl.toolbar.OpenWorkflowFromURLToolbarAction"> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="SaveToolbarAction" class="net.sf.taverna.t2.workbench.file.impl.toolbar.SaveToolbarAction"> + <constructor-arg ref="editManager" /> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + <bean id="CloseToolbarAction" class="net.sf.taverna.t2.workbench.file.impl.toolbar.CloseToolbarAction"> + <constructor-arg ref="editManager" /> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + + <bean id="T2DataflowOpener" class="net.sf.taverna.t2.workbench.file.impl.T2DataflowOpener"> + <property name="workflowBundleIO" ref="workflowBundleIO"/> + </bean> + + <bean id="WorkflowBundleOpener" class="net.sf.taverna.t2.workbench.file.impl.WorkflowBundleOpener"> + <property name="workflowBundleIO" ref="workflowBundleIO"/> + </bean> + <bean id="WorkflowBundleSaver" class="net.sf.taverna.t2.workbench.file.impl.WorkflowBundleSaver"> + <property name="workflowBundleIO" ref="workflowBundleIO"/> + </bean> + + <bean id="CloseWorkflowsOnShutdown" class="net.sf.taverna.t2.workbench.file.impl.hooks.CloseWorkflowsOnShutdown"> + <constructor-arg ref="editManager" /> + <constructor-arg> + <ref local="FileManagerImpl" /> + </constructor-arg> + </bean> + + <bean id="FileManagerImpl" class="net.sf.taverna.t2.workbench.file.impl.FileManagerImpl"> + <constructor-arg name="editManager" ref="editManager" /> + <property name="dataflowPersistenceHandlerRegistry"> + <ref local="DataflowPersistenceHandlerRegistry"/> + </property> + </bean> + + <bean id="DataflowPersistenceHandlerRegistry" class="net.sf.taverna.t2.workbench.file.impl.DataflowPersistenceHandlerRegistry"> + <property name="dataflowPersistenceHandlers" ref="dataflowPersistenceHandlers" /> + </bean> + + +</beans> http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/test/java/net/sf/taverna/t2/workbench/file/impl/FileManagerTest.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/test/java/net/sf/taverna/t2/workbench/file/impl/FileManagerTest.java b/taverna-workbench-file-impl/src/test/java/net/sf/taverna/t2/workbench/file/impl/FileManagerTest.java new file mode 100644 index 0000000..691b278 --- /dev/null +++ b/taverna-workbench-file-impl/src/test/java/net/sf/taverna/t2/workbench/file/impl/FileManagerTest.java @@ -0,0 +1,385 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.file.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import net.sf.taverna.t2.lang.observer.Observable; +import net.sf.taverna.t2.lang.observer.Observer; +import net.sf.taverna.t2.workbench.edits.Edit; +import net.sf.taverna.t2.workbench.edits.EditManager; +import net.sf.taverna.t2.workbench.edits.impl.EditManagerImpl; +import net.sf.taverna.t2.workbench.file.DataflowInfo; +import net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler; +import net.sf.taverna.t2.workbench.file.FileManager; +import net.sf.taverna.t2.workbench.file.events.FileManagerEvent; +import net.sf.taverna.t2.workbench.file.events.SetCurrentDataflowEvent; +import net.sf.taverna.t2.workbench.file.exceptions.OpenException; +import net.sf.taverna.t2.workbench.file.exceptions.OverwriteException; +import net.sf.taverna.t2.workflow.edits.AddProcessorEdit; +import net.sf.taverna.t2.workflow.edits.RenameEdit; + +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import uk.org.taverna.scufl2.api.container.WorkflowBundle; +import uk.org.taverna.scufl2.api.core.Processor; +import uk.org.taverna.scufl2.api.core.Workflow; +import uk.org.taverna.scufl2.api.io.WorkflowBundleIO; +import uk.org.taverna.scufl2.api.io.WorkflowBundleReader; +import uk.org.taverna.scufl2.api.io.WorkflowBundleWriter; +import uk.org.taverna.scufl2.rdfxml.RDFXMLReader; +import uk.org.taverna.scufl2.rdfxml.RDFXMLWriter; +import uk.org.taverna.scufl2.translator.t2flow.T2FlowReader; + +public class FileManagerTest { + + private static final WorkflowBundleFileType WF_BUNDLE_FILE_TYPE = new WorkflowBundleFileType(); + private static final T2FlowFileType T2_FLOW_FILE_TYPE = new T2FlowFileType(); + + private static final String DUMMY_WORKFLOW_T2FLOW = "dummy-workflow.t2flow"; + + private FileManagerImpl fileManager; + private EditManager editManager; + + private FileManagerObserver fileManagerObserver= new FileManagerObserver();; + + @Test + public void close() throws Exception { + assertTrue("Non-empty set of open dataflows", fileManager + .getOpenDataflows().isEmpty()); + WorkflowBundle dataflow = openDataflow(); + assertEquals("Unexpected list of open dataflows", Arrays + .asList(dataflow), fileManager.getOpenDataflows()); + fileManager.closeDataflow(dataflow, true); + assertNotSame(dataflow, fileManager.getOpenDataflows().get(0)); + assertTrue("Did not insert empty dataflow after close", fileManager + .getOpenDataflows().get(0).getMainWorkflow().getProcessors().isEmpty()); + } + + @Test + public void openRemovesEmptyDataflow() throws Exception { + WorkflowBundle newDataflow = fileManager.newDataflow(); + assertEquals("Unexpected list of open dataflows", Arrays + .asList(newDataflow), fileManager.getOpenDataflows()); + WorkflowBundle dataflow = openDataflow(); + // Should have removed newDataflow + assertEquals("Unexpected list of open dataflows", Arrays + .asList(dataflow), fileManager.getOpenDataflows()); + } + + @Test + public void isChanged() throws Exception { + WorkflowBundle dataflow = openDataflow(); + assertFalse("Dataflow should not have changed", fileManager + .isDataflowChanged(dataflow)); + + // Do a change + Processor emptyProcessor = new Processor(); + Edit<Workflow> addProcessorEdit = new AddProcessorEdit(dataflow.getMainWorkflow(), + emptyProcessor); + editManager.doDataflowEdit(dataflow, addProcessorEdit); + assertTrue("Dataflow should have changed", fileManager + .isDataflowChanged(dataflow)); + + // Save it with the change + File dataflowFile = File.createTempFile("test", ".t2flow"); + dataflowFile.deleteOnExit(); + dataflowFile.delete(); + + fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false); + assertFalse("Dataflow should no longer be marked as changed", + fileManager.isDataflowChanged(dataflow)); + } + + @Ignore("Undo support for ischanged not yet implemented") + @Test + public void isChangedWithUndo() throws Exception { + WorkflowBundle dataflow = openDataflow(); + // Do a change + Processor emptyProcessor = new Processor(); + Edit<Workflow> addProcessorEdit = new AddProcessorEdit(dataflow.getMainWorkflow(), + emptyProcessor); + editManager.doDataflowEdit(dataflow, addProcessorEdit); + assertTrue("Dataflow should have changed", fileManager + .isDataflowChanged(dataflow)); + editManager.undoDataflowEdit(dataflow); + assertFalse( + "Dataflow should no longer be marked as changed after undo", + fileManager.isDataflowChanged(dataflow)); + editManager.redoDataflowEdit(dataflow); + assertTrue("Dataflow should have changed after redo before save", + fileManager.isDataflowChanged(dataflow)); + + // Save it with the change + File dataflowFile = File.createTempFile("test", ".t2flow"); + dataflowFile.deleteOnExit(); + dataflowFile.delete(); + fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false); + assertFalse("Dataflow should no longer be marked as changed", + fileManager.isDataflowChanged(dataflow)); + + editManager.undoDataflowEdit(dataflow); + assertTrue("Dataflow should have changed after undo", fileManager + .isDataflowChanged(dataflow)); + fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false); + editManager.redoDataflowEdit(dataflow); + assertTrue("Dataflow should have changed after redo after save", + fileManager.isDataflowChanged(dataflow)); + } + + @Test + public void isListed() throws Exception { + assertTrue("Non-empty set of open data flows", fileManager + .getOpenDataflows().isEmpty()); + WorkflowBundle dataflow = openDataflow(); + assertEquals("Unexpected list of open dataflows", Arrays + .asList(dataflow), fileManager.getOpenDataflows()); + } + + /** + * Always uses a <strong>new</strong> file manager instead of the instance + * one from {@link FileManager#getInstance()}. + * + * @see #getFileManagerInstance() + * + */ + @Before + public void makeFileManager() { + System.setProperty("java.awt.headless", "true"); + editManager = new EditManagerImpl(); + fileManager = new FileManagerImpl(editManager); + fileManagerObserver = new FileManagerObserver(); + fileManager.addObserver(fileManagerObserver); + WorkflowBundleIO workflowBundleIO = new WorkflowBundleIO(); + workflowBundleIO.setReaders(Arrays.<WorkflowBundleReader>asList(new RDFXMLReader(), new T2FlowReader())); + workflowBundleIO.setWriters(Arrays.<WorkflowBundleWriter>asList(new RDFXMLWriter())); + T2DataflowOpener t2DataflowOpener = new T2DataflowOpener(); + t2DataflowOpener.setWorkflowBundleIO(workflowBundleIO); + WorkflowBundleOpener workflowBundleOpener = new WorkflowBundleOpener(); + workflowBundleOpener.setWorkflowBundleIO(workflowBundleIO); + WorkflowBundleSaver workflowBundleSaver = new WorkflowBundleSaver(); + workflowBundleSaver.setWorkflowBundleIO(workflowBundleIO); + DataflowPersistenceHandlerRegistry dataflowPersistenceHandlerRegistry = new DataflowPersistenceHandlerRegistry(); + dataflowPersistenceHandlerRegistry.setDataflowPersistenceHandlers(Arrays.asList( + new DataflowPersistenceHandler[] {t2DataflowOpener, workflowBundleOpener, workflowBundleSaver})); + dataflowPersistenceHandlerRegistry.updateColletions(); + fileManager.setDataflowPersistenceHandlerRegistry(dataflowPersistenceHandlerRegistry); + } + + @Test + public void open() throws Exception { + assertTrue("ModelMapObserver already contained messages", + fileManagerObserver.messages.isEmpty()); + WorkflowBundle dataflow = openDataflow(); + assertNotNull("Dataflow was not loaded", dataflow); + assertEquals("Loaded dataflow was not set as current dataflow", + dataflow, fileManager.getCurrentDataflow()); + assertFalse("ModelMapObserver did not contain message", + fileManagerObserver.messages.isEmpty()); + assertEquals("ModelMapObserver contained unexpected messages", 2, + fileManagerObserver.messages.size()); + FileManagerEvent event = fileManagerObserver.messages.get(0); + assertTrue(event instanceof SetCurrentDataflowEvent); + assertEquals(dataflow, ((SetCurrentDataflowEvent) event).getDataflow()); + } + + @Test + public void openSilently() throws Exception { + assertTrue("ModelMapObserver already contained messages", + fileManagerObserver.messages.isEmpty()); + URL url = getClass().getResource(DUMMY_WORKFLOW_T2FLOW); + DataflowInfo info = fileManager.openDataflowSilently(T2_FLOW_FILE_TYPE, url); + + WorkflowBundle dataflow = info.getDataflow(); + assertNotNull("Dataflow was not loaded", dataflow); + + assertNotSame("Loaded dataflow was set as current dataflow", + dataflow, fileManager.getCurrentDataflow()); + assertTrue("ModelMapObserver contained unexpected messages", + fileManagerObserver.messages.isEmpty()); + } + + @Test + public void canSaveDataflow() throws Exception { + WorkflowBundle savedDataflow = openDataflow(); + File dataflowFile = File.createTempFile("test", ".t2flow"); + dataflowFile.deleteOnExit(); + dataflowFile.delete(); + fileManager.saveDataflow(savedDataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true); + assertTrue(fileManager.canSaveWithoutDestination(savedDataflow)); + fileManager.saveDataflow(savedDataflow, true); + fileManager.closeDataflow(savedDataflow, true); + + WorkflowBundle otherFlow = fileManager.openDataflow(WF_BUNDLE_FILE_TYPE, dataflowFile.toURI() + .toURL()); + assertTrue(fileManager.canSaveWithoutDestination(otherFlow)); + } + + @Test + public void save() throws Exception { + WorkflowBundle savedDataflow = openDataflow(); + File dataflowFile = File.createTempFile("test", ".t2flow"); + dataflowFile.deleteOnExit(); + dataflowFile.delete(); + assertFalse("File should not exist", dataflowFile.isFile()); + fileManager.saveDataflow(savedDataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false); + assertTrue("File should exist", dataflowFile.isFile()); + WorkflowBundle loadedDataflow = fileManager.openDataflow(WF_BUNDLE_FILE_TYPE, dataflowFile.toURI() + .toURL()); + assertNotSame("Dataflow was not reopened", savedDataflow, + loadedDataflow); + assertEquals("Unexpected number of processors in saved dataflow", 1, + savedDataflow.getMainWorkflow().getProcessors().size()); + assertEquals("Unexpected number of processors in loaded dataflow", 1, + loadedDataflow.getMainWorkflow().getProcessors().size()); + + Processor savedProcessor = savedDataflow.getMainWorkflow().getProcessors().first(); + Processor loadedProcessor = loadedDataflow.getMainWorkflow().getProcessors().first(); + assertEquals("Loaded processor had wrong name", savedProcessor + .getName(), loadedProcessor.getName()); + + // TODO convert to scufl2 +// BeanshellActivity savedActivity = (BeanshellActivity) savedProcessor +// .getActivityList().get(0); +// BeanshellActivity loadedActivity = (BeanshellActivity) loadedProcessor +// .getActivityList().get(0); +// String savedScript = savedActivity.getConfiguration().getScript(); +// String loadedScript = loadedActivity.getConfiguration().getScript(); +// assertEquals("Unexpected saved script", +// "String output = input + \"XXX\";", savedScript); +// assertEquals("Loaded script did not matched saved script", savedScript, +// loadedScript); + } + + @Test + public void saveSilent() throws Exception { + assertTrue("ModelMapObserver contained unexpected messages", + fileManagerObserver.messages.isEmpty()); + + URL url = getClass().getResource(DUMMY_WORKFLOW_T2FLOW); + DataflowInfo info = fileManager.openDataflowSilently(T2_FLOW_FILE_TYPE, url); + WorkflowBundle dataflow = info.getDataflow(); + assertTrue("ModelMapObserver contained unexpected messages", + fileManagerObserver.messages.isEmpty()); + + File dataflowFile = File.createTempFile("test", ".t2flow"); + dataflowFile.deleteOnExit(); + dataflowFile.delete(); + assertFalse("File should not exist", dataflowFile.isFile()); + + fileManager.saveDataflowSilently(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false); + assertTrue("File should exist", dataflowFile.isFile()); + + assertTrue("ModelMapObserver contained unexpected messages", + fileManagerObserver.messages.isEmpty()); + + } + + @Test + public void saveOverwriteAgain() throws Exception { + WorkflowBundle dataflow = openDataflow(); + File dataflowFile = File.createTempFile("test", ".t2flow"); + dataflowFile.delete(); + dataflowFile.deleteOnExit(); + // File did NOT exist, should not fail + fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true); + + Processor processor = dataflow.getMainWorkflow().getProcessors().first(); + Edit<Processor> renameEdit = new RenameEdit<Processor>(processor, + processor.getName() + "-changed"); + editManager.doDataflowEdit(dataflow, renameEdit); + + // Last save was OURs, so should *not* fail - even if we now use + // the specific saveDataflow() method + fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true); + + //Thread.sleep(1500); + WorkflowBundle otherFlow = openDataflow(); + // Saving another flow to same file should still fail + try { + fileManager.saveDataflow(otherFlow,WF_BUNDLE_FILE_TYPE, dataflowFile, true); + fail("Should have thrown OverwriteException"); + } catch (OverwriteException ex) { + // Expected + } + } + + @Test(expected = OverwriteException.class) + public void saveOverwriteWarningFails() throws Exception { + WorkflowBundle dataflow = openDataflow(); + File dataflowFile = File.createTempFile("test", ".t2flow"); + dataflowFile.deleteOnExit(); + // Should fail as file already exists + fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true); + } + + @Test + public void saveOverwriteWarningWorks() throws Exception { + WorkflowBundle dataflow = openDataflow(); + File dataflowFile = File.createTempFile("test", ".t2flow"); + dataflowFile.delete(); + dataflowFile.deleteOnExit(); + // File did NOT exist, should not fail + fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true); + } + + @After + public void stopListeningToModelMap() { + fileManager.removeObserver(fileManagerObserver); + } + + protected WorkflowBundle openDataflow() throws OpenException { + URL url = getClass().getResource(DUMMY_WORKFLOW_T2FLOW); + assertNotNull(url); + WorkflowBundle dataflow = fileManager.openDataflow(T2_FLOW_FILE_TYPE, url); + assertNotNull(dataflow); + return dataflow; + } + + private final class FileManagerObserver implements Observer<FileManagerEvent> { + protected List<FileManagerEvent> messages = new ArrayList<FileManagerEvent>(); + + @Override + public void notify(Observable<FileManagerEvent> sender, FileManagerEvent message) throws Exception { + messages.add(message); + if (message instanceof SetCurrentDataflowEvent) { + assertTrue("Dataflow was not listed as open when set current", + fileManager.getOpenDataflows().contains( + ((SetCurrentDataflowEvent) message).getDataflow())); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-file-impl/src/test/resources/net/sf/taverna/t2/workbench/file/impl/dummy-workflow.t2flow ---------------------------------------------------------------------- diff --git a/taverna-workbench-file-impl/src/test/resources/net/sf/taverna/t2/workbench/file/impl/dummy-workflow.t2flow b/taverna-workbench-file-impl/src/test/resources/net/sf/taverna/t2/workbench/file/impl/dummy-workflow.t2flow new file mode 100644 index 0000000..b9a1075 --- /dev/null +++ b/taverna-workbench-file-impl/src/test/resources/net/sf/taverna/t2/workbench/file/impl/dummy-workflow.t2flow @@ -0,0 +1,157 @@ +<workflow xmlns="http://taverna.sf.net/2008/xml/t2flow" version="1" producedBy="test"> + <dataflow id="ec0991ba-275c-49ed-b1d6-38534180fb7c" role="top"> + <name>simple_workflow_with_input</name> + <inputPorts> + <port> + <name>input</name> + <depth>0</depth> + <granularDepth>0</granularDepth> + </port> + </inputPorts> + <outputPorts> + <port> + <name>output</name> + </port> + </outputPorts> + <processors> + <processor> + <name>Concat_XXX</name> + <inputPorts> + <port> + <name>input</name> + <depth>0</depth> + </port> + </inputPorts> + <outputPorts> + <port> + <name>output</name> + <depth>0</depth> + <granularDepth>0</granularDepth> + </port> + </outputPorts> + <annotations /> + <activities> + <activity> + <class> + net.sf.taverna.t2.activities.beanshell.BeanshellActivity + </class> + <inputMap> + <map from="input" to="input" /> + </inputMap> + <outputMap> + <map from="output" to="output" /> + </outputMap> + <configBean encoding="xstream"> + <net.sf.taverna.t2.activities.beanshell.BeanshellActivityConfigurationBean + xmlns=""> + <script>String output = input + "XXX";</script> + <dependencies /> + <inputs> + <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean> + <handledReferenceSchemes /> + <translatedElementType>java.lang.String</translatedElementType> + <allowsLiteralValues>true</allowsLiteralValues> + <name>input</name> + <depth>0</depth> + <mimeTypes> + <string>'text/plain'</string> + </mimeTypes> + </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean> + </inputs> + <outputs> + <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean> + <granularDepth>0</granularDepth> + <name>output</name> + <depth>0</depth> + <mimeTypes> + <string>'text/plain'</string> + </mimeTypes> + </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean> + </outputs> + </net.sf.taverna.t2.activities.beanshell.BeanshellActivityConfigurationBean> + </configBean> + </activity> + </activities> + <dispatchStack> + <dispatchLayer> + <class> + net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.Parallelize + </class> + <configBean encoding="xstream"> + <net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.ParallelizeConfig + xmlns=""> + <maxJobs>1</maxJobs> + </net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.ParallelizeConfig> + </configBean> + </dispatchLayer> + <dispatchLayer> + <class> + net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.ErrorBounce + </class> + <configBean encoding="xstream"> + <null xmlns="" /> + </configBean> + </dispatchLayer> + <dispatchLayer> + <class> + net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.Failover + </class> + <configBean encoding="xstream"> + <null xmlns="" /> + </configBean> + </dispatchLayer> + <dispatchLayer> + <class> + net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.Retry + </class> + <configBean encoding="xstream"> + <net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.RetryConfig + xmlns=""> + <backoffFactor>1.0</backoffFactor> + <initialDelay>0</initialDelay> + <maxDelay>0</maxDelay> + <maxRetries>0</maxRetries> + </net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.RetryConfig> + </configBean> + </dispatchLayer> + <dispatchLayer> + <class> + net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.Invoke + </class> + <configBean encoding="xstream"> + <null xmlns="" /> + </configBean> + </dispatchLayer> + </dispatchStack> + <iterationStrategyStack> + <iteration> + <strategy> + <port name="input" depth="0" /> + </strategy> + </iteration> + </iterationStrategyStack> + </processor> + </processors> + <conditions /> + <datalinks> + <datalink> + <sink type="processor"> + <processor>Concat_XXX</processor> + <port>input</port> + </sink> + <source type="dataflow"> + <port>input</port> + </source> + </datalink> + <datalink> + <sink type="dataflow"> + <port>output</port> + </sink> + <source type="processor"> + <processor>Concat_XXX</processor> + <port>output</port> + </source> + </datalink> + </datalinks> + </dataflow> +</workflow> http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-helper/pom.xml ---------------------------------------------------------------------- diff --git a/taverna-workbench-helper/pom.xml b/taverna-workbench-helper/pom.xml new file mode 100644 index 0000000..70c0621 --- /dev/null +++ b/taverna-workbench-helper/pom.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.sf.taverna.t2</groupId> + <artifactId>ui-impl</artifactId> + <version>2.0-SNAPSHOT</version> + </parent> + <groupId>net.sf.taverna.t2.ui-impl</groupId> + <artifactId>helper</artifactId> + <name>Help System (legacy dependency)</name> + <dependencies> + <dependency> + <groupId>net.sf.taverna.t2.ui-api</groupId> + <artifactId>helper-api</artifactId> + <version>${t2.ui.api.version}</version> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-httpproxy-config/pom.xml ---------------------------------------------------------------------- diff --git a/taverna-workbench-httpproxy-config/pom.xml b/taverna-workbench-httpproxy-config/pom.xml new file mode 100644 index 0000000..f1a8328 --- /dev/null +++ b/taverna-workbench-httpproxy-config/pom.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.sf.taverna.t2</groupId> + <artifactId>ui-impl</artifactId> + <version>2.0-SNAPSHOT</version> + </parent> + <groupId>net.sf.taverna.t2.ui-impl</groupId> + <artifactId>httpproxy-config</artifactId> + <packaging>bundle</packaging> + <name>HTTP Proxy configuration</name> + <dependencies> + <dependency> + <groupId>net.sf.taverna.t2.lang</groupId> + <artifactId>ui</artifactId> + <version>${t2.lang.version}</version> + </dependency> + <dependency> + <groupId>uk.org.taverna.configuration</groupId> + <artifactId>taverna-configuration-api</artifactId> + <version>${taverna.configuration.version}</version> + </dependency> + <dependency> + <groupId>net.sf.taverna.t2.ui-api</groupId> + <artifactId>helper-api</artifactId> + <version>${t2.ui.api.version}</version> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationPanel.java ---------------------------------------------------------------------- diff --git a/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationPanel.java b/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationPanel.java new file mode 100644 index 0000000..1229d57 --- /dev/null +++ b/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationPanel.java @@ -0,0 +1,582 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package net.sf.taverna.t2.workbench.httpproxy.config; + +import static java.awt.GridBagConstraints.BOTH; +import static java.awt.GridBagConstraints.CENTER; +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.NONE; +import static java.awt.GridBagConstraints.WEST; +import static javax.swing.JOptionPane.showMessageDialog; +import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED; +import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED; +import static net.sf.taverna.t2.workbench.helper.Helper.showHelp; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.PROXY_USE_OPTION; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_NON_PROXY_HOSTS; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_PROXY_HOST; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_PROXY_PASSWORD; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_PROXY_PORT; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_PROXY_USER; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_NON_PROXY_HOSTS; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_PROXY_HOST; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_PROXY_PASSWORD; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_PROXY_PORT; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_PROXY_USER; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.USE_NO_PROXY_OPTION; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.USE_SPECIFIED_VALUES_OPTION; +import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.USE_SYSTEM_PROPERTIES_OPTION; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.AbstractAction; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.border.EmptyBorder; + +import net.sf.taverna.t2.lang.ui.DialogTextArea; +import uk.org.taverna.configuration.proxy.HttpProxyConfiguration; + +/** + * The HttpProxyConfigurationPanel provides the user interface to a + * {@link HttpProxyConfiguration} to determine how HTTP Connections are made by + * Taverna. + * + * @author alanrw + * @author David Withers + */ +public class HttpProxyConfigurationPanel extends JPanel { + static final long serialVersionUID = 3668473431971125038L; + /** + * The size of the field for the JTextFields. + */ + private static int TEXTFIELD_SIZE = 25; + + private final HttpProxyConfiguration httpProxyConfiguration; + /** + * RadioButtons that are in a common ButtonGroup. Selecting one of them + * indicates whether the system http proxy settings, the ad hoc specified + * values or no proxy settings at all should be used. + */ + private JRadioButton useSystemProperties; + private JRadioButton useSpecifiedValues; + private JRadioButton useNoProxy; + /** + * JTextFields and one DialogTextArea to hold the settings for the HTTP + * proxy properties. The values are only editable if the user picks + * useSpecifiedValues. + */ + private JTextField proxyHostField; + private JTextField proxyPortField; + private JTextField proxyUserField; + private JTextField proxyPasswordField; + private DialogTextArea nonProxyHostsArea; + private JScrollPane nonProxyScrollPane; + /** + * A string that indicates which HTTP setting option the user has currently + * picked. This does not necesarily match that which has been applied. + */ + private String shownOption = USE_SYSTEM_PROPERTIES_OPTION; + + /** + * The HttpProxyConfigurationPanel consists of a set of properties where the + * configuration values for HTTP can be specified and a set of buttons where + * the more general apply, help etc. appear. + */ + public HttpProxyConfigurationPanel( + HttpProxyConfiguration httpProxyConfiguration) { + this.httpProxyConfiguration = httpProxyConfiguration; + initComponents(); + } + + /** + * Populates the panel with a representation of the current HTTP proxy + * settings for the specified {@link HttpProxyConfiguration} and also the + * capability to alter them. + */ + private void initComponents() { + shownOption = httpProxyConfiguration.getProperty(PROXY_USE_OPTION); + + this.setLayout(new GridBagLayout()); + + GridBagConstraints gbc = new GridBagConstraints(); + + // Title describing what kind of settings we are configuring here + JTextArea descriptionText = new JTextArea("HTTP proxy configuration"); + descriptionText.setLineWrap(true); + descriptionText.setWrapStyleWord(true); + descriptionText.setEditable(false); + descriptionText.setFocusable(false); + descriptionText.setBorder(new EmptyBorder(10, 10, 10, 10)); + gbc.anchor = WEST; + gbc.gridx = 0; + gbc.gridy = 0; + gbc.gridwidth = 2; + gbc.weightx = 1.0; + gbc.weighty = 0.0; + gbc.fill = HORIZONTAL; + this.add(descriptionText, gbc); + + /** + * Generate the three radio buttons and put them in a group. Each button + * is bound to an action that alters the shownOption and re-populates + * the shown HTTP property fields. + */ + useNoProxy = new JRadioButton("Do not use a proxy"); + useNoProxy.setAlignmentX(LEFT_ALIGNMENT); + gbc.gridx = 0; + gbc.gridy = 1; + gbc.gridwidth = 2; + gbc.weightx = 0.0; + gbc.weighty = 0.0; + gbc.fill = NONE; + gbc.insets = new Insets(10, 0, 0, 0); + this.add(useNoProxy, gbc); + ActionListener useNoProxyListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + shownOption = USE_NO_PROXY_OPTION; + populateFields(); + } + }; + useNoProxy.addActionListener(useNoProxyListener); + + useSystemProperties = new JRadioButton("Use system properties"); + useSystemProperties.setAlignmentX(LEFT_ALIGNMENT); + gbc.gridx = 0; + gbc.gridy = 2; + gbc.insets = new Insets(0, 0, 0, 0); + this.add(useSystemProperties, gbc); + ActionListener systemPropertiesListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + shownOption = USE_SYSTEM_PROPERTIES_OPTION; + populateFields(); + } + }; + useSystemProperties.addActionListener(systemPropertiesListener); + + useSpecifiedValues = new JRadioButton("Use specified values"); + useSpecifiedValues.setAlignmentX(LEFT_ALIGNMENT); + gbc.gridx = 0; + gbc.gridy = 3; + this.add(useSpecifiedValues, gbc); + ActionListener specifiedValuesListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + shownOption = USE_SPECIFIED_VALUES_OPTION; + populateFields(); + } + }; + useSpecifiedValues.addActionListener(specifiedValuesListener); + + ButtonGroup bg = new ButtonGroup(); + bg.add(useSystemProperties); + bg.add(useSpecifiedValues); + bg.add(useNoProxy); + + /** + * Create the fields to show the HTTP proxy property values. These + * become editable if the shown option is to use specified values. + */ + proxyHostField = new JTextField(TEXTFIELD_SIZE); + gbc.gridx = 0; + gbc.gridy = 4; + gbc.gridwidth = 1; + gbc.fill = NONE; + gbc.insets = new Insets(10, 0, 0, 0); + this.add(new JLabel("Proxy host"), gbc); + gbc.gridx = 1; + gbc.gridy = 4; + gbc.gridwidth = 1; + gbc.fill = HORIZONTAL; + this.add(proxyHostField, gbc); + + proxyPortField = new JTextField(TEXTFIELD_SIZE); + gbc.gridx = 0; + gbc.gridy = 5; + gbc.gridwidth = 1; + gbc.fill = NONE; + gbc.insets = new Insets(0, 0, 0, 0); + this.add(new JLabel("Proxy port"), gbc); + gbc.gridx = 1; + gbc.gridy = 5; + gbc.gridwidth = 1; + gbc.fill = HORIZONTAL; + this.add(proxyPortField, gbc); + + proxyUserField = new JTextField(TEXTFIELD_SIZE); + gbc.gridx = 0; + gbc.gridy = 6; + gbc.gridwidth = 1; + gbc.fill = NONE; + this.add(new JLabel("Proxy user"), gbc); + gbc.gridx = 1; + gbc.gridy = 6; + gbc.gridwidth = 1; + gbc.fill = HORIZONTAL; + this.add(proxyUserField, gbc); + + proxyPasswordField = new JTextField(TEXTFIELD_SIZE); + gbc.gridx = 0; + gbc.gridy = 7; + gbc.gridwidth = 1; + gbc.fill = NONE; + this.add(new JLabel("Proxy password"), gbc); + gbc.gridx = 1; + gbc.gridy = 7; + gbc.gridwidth = 1; + gbc.fill = HORIZONTAL; + this.add(proxyPasswordField, gbc); + + nonProxyHostsArea = new DialogTextArea(10, 40); + nonProxyScrollPane = new JScrollPane(nonProxyHostsArea); + nonProxyScrollPane + .setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED); + nonProxyScrollPane + .setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_AS_NEEDED); + // nonProxyScrollPane.setPreferredSize(new Dimension(300, 500)); + gbc.gridx = 0; + gbc.gridy = 8; + gbc.gridwidth = 2; + gbc.fill = NONE; + gbc.insets = new Insets(10, 0, 0, 0); + this.add(new JLabel("Non-proxy hosts"), gbc); + gbc.gridx = 0; + gbc.gridy = 9; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + gbc.gridwidth = 2; + gbc.insets = new Insets(0, 0, 0, 0); + gbc.fill = BOTH; + this.add(nonProxyScrollPane, gbc); + + // Add buttons panel + gbc.gridx = 0; + gbc.gridy = 10; + gbc.weightx = 0.0; + gbc.weighty = 0.0; + gbc.gridwidth = 2; + gbc.fill = HORIZONTAL; + gbc.anchor = CENTER; + gbc.insets = new Insets(10, 0, 0, 0); + this.add(createButtonPanel(), gbc); + + setFields(); + } + + /** + * Populate the fields in the property panel according to which option is + * being shown and the stored values within the + * {@link HttpProxyConfiguration}. + */ + private void populateFields() { + /** + * Editing of the property fields is only available when the option is + * to use the specified values. + */ + boolean editingEnabled = shownOption + .equals(USE_SPECIFIED_VALUES_OPTION); + + if (shownOption.equals(USE_SYSTEM_PROPERTIES_OPTION)) { + proxyHostField.setText(httpProxyConfiguration + .getProperty(SYSTEM_PROXY_HOST)); + proxyPortField.setText(httpProxyConfiguration + .getProperty(SYSTEM_PROXY_PORT)); + proxyUserField.setText(httpProxyConfiguration + .getProperty(SYSTEM_PROXY_USER)); + proxyPasswordField.setText(httpProxyConfiguration + .getProperty(SYSTEM_PROXY_PASSWORD)); + nonProxyHostsArea.setText(httpProxyConfiguration + .getProperty(SYSTEM_NON_PROXY_HOSTS)); + } else if (shownOption.equals(USE_SPECIFIED_VALUES_OPTION)) { + proxyHostField.setText(httpProxyConfiguration + .getProperty(TAVERNA_PROXY_HOST)); + proxyPortField.setText(httpProxyConfiguration + .getProperty(TAVERNA_PROXY_PORT)); + proxyUserField.setText(httpProxyConfiguration + .getProperty(TAVERNA_PROXY_USER)); + proxyPasswordField.setText(httpProxyConfiguration + .getProperty(TAVERNA_PROXY_PASSWORD)); + nonProxyHostsArea.setText(httpProxyConfiguration + .getProperty(TAVERNA_NON_PROXY_HOSTS)); + } else { + proxyHostField.setText(null); + proxyPortField.setText(null); + proxyUserField.setText(null); + proxyPasswordField.setText(null); + nonProxyHostsArea.setText(null); + } + + proxyHostField.setEnabled(editingEnabled); + proxyPortField.setEnabled(editingEnabled); + proxyUserField.setEnabled(editingEnabled); + proxyPasswordField.setEnabled(editingEnabled); + nonProxyHostsArea.setEnabled(editingEnabled); + nonProxyHostsArea.setEditable(editingEnabled); + nonProxyScrollPane.setEnabled(editingEnabled); + } + + /** + * Create the panel to contain the buttons + * + * @return + */ + @SuppressWarnings("serial") + private JPanel createButtonPanel() { + final JPanel panel = new JPanel(); + + /** + * The helpButton shows help about the current component + */ + JButton helpButton = new JButton(new AbstractAction("Help") { + @Override + public void actionPerformed(ActionEvent arg0) { + showHelp(panel); + } + }); + panel.add(helpButton); + + /** + * The resetButton changes the property values shown to those + * corresponding to the configuration currently applied. + */ + JButton resetButton = new JButton(new AbstractAction("Reset") { + @Override + public void actionPerformed(ActionEvent arg0) { + setFields(); + } + }); + panel.add(resetButton); + + /** + * The applyButton applies the shown field values to the + * {@link HttpProxyConfiguration} and saves them for future. + */ + JButton applyButton = new JButton(new AbstractAction("Apply") { + @Override + public void actionPerformed(ActionEvent arg0) { + applySettings(); + setFields(); + } + }); + panel.add(applyButton); + + return panel; + } + + /** + * Checks that the specified values for the HTTP properties are a valid + * combination and, if so, saves them for future use. It does not apply them + * to the currently executing Taverna. + */ + private void saveSettings() { + if (useSystemProperties.isSelected()) { + httpProxyConfiguration.setProperty(PROXY_USE_OPTION, + USE_SYSTEM_PROPERTIES_OPTION); + } else if (useNoProxy.isSelected()) { + httpProxyConfiguration.setProperty(PROXY_USE_OPTION, + USE_NO_PROXY_OPTION); + } else { + if (validateFields()) { + httpProxyConfiguration.setProperty(PROXY_USE_OPTION, + USE_SPECIFIED_VALUES_OPTION); + httpProxyConfiguration.setProperty(TAVERNA_PROXY_HOST, + proxyHostField.getText()); + httpProxyConfiguration.setProperty(TAVERNA_PROXY_PORT, + proxyPortField.getText()); + httpProxyConfiguration.setProperty(TAVERNA_PROXY_USER, + proxyUserField.getText()); + httpProxyConfiguration.setProperty(TAVERNA_PROXY_PASSWORD, + proxyPasswordField.getText()); + httpProxyConfiguration.setProperty(TAVERNA_NON_PROXY_HOSTS, + nonProxyHostsArea.getText()); + } + } + } + + /** + * Validates and, where appropriate formats, the properties values specified + * for HTTP Proxy configuration. + * + * @return + */ + private boolean validateFields() { + boolean result = true; + result = result && validateHostField(); + result = result && validatePortField(); + result = result && validateUserField(); + result = result && validatePasswordField(); + result = result && validateNonProxyHostsArea(); + return result; + } + + /** + * Checks that, if a value is specified for non-proxy hosts then a proxy + * host has also been specified. Formats the non-proxy hosts string so that + * if the user has entered the hosts on separate lines, then the stored + * values are separated by bars. + * + * @return + */ + private boolean validateNonProxyHostsArea() { + boolean result = true; + String value = nonProxyHostsArea.getText(); + if ((value != null) && (!value.equals(""))) { + value = value.replaceAll("\\n", "|"); + nonProxyHostsArea.setText(value); + result = result + && dependsUpon("non-proxy host", "host", + proxyHostField.getText()); + } + return result; + } + + /** + * Checks that, if a password has been specified, then a user has also been + * specified. + * + * @return + */ + private boolean validatePasswordField() { + boolean result = true; + String value = proxyPasswordField.getText(); + if ((value != null) && !value.isEmpty()) + result = result + && dependsUpon("password", "user", proxyHostField.getText()); + return result; + } + + /** + * Checks that if a user has been specified, then a host has also been + * specified. + * + * @return + */ + private boolean validateUserField() { + boolean result = true; + String value = proxyUserField.getText(); + if ((value != null) && !value.isEmpty()) + result = result + && dependsUpon("user", "host", proxyHostField.getText()); + return result; + } + + /** + * Checks that if a port has been specified then a host has also been + * specified. Checks that the port number is a non-negative integer. If the + * port has not been specified, then if a host has been specified, the + * default value 80 is used. + * + * @return + */ + private boolean validatePortField() { + boolean result = true; + String value = proxyPortField.getText(); + if ((value != null) && (!value.equals(""))) { + result = result + && dependsUpon("port", "host", proxyHostField.getText()); + try { + int parsedNumber = Integer.parseInt(value); + if (parsedNumber <= 0) { + showMessageDialog(this, "The port must be non-negative"); + result = false; + } + } catch (NumberFormatException e) { + showMessageDialog(this, "The port must be an integer"); + result = false; + } + } else { + String hostField = proxyHostField.getText(); + if ((hostField != null) && !hostField.isEmpty()) + proxyPortField.setText("80"); + } + return result; + } + + /** + * Checks if the targetValue has been specified. If not then a message is + * displayed indicating that the dependent cannot be specified with the + * target. + * + * @param dependent + * @param target + * @param targetValue + * @return + */ + private boolean dependsUpon(String dependent, String target, + String targetValue) { + boolean result = true; + if ((targetValue == null) || target.equals("")) { + showMessageDialog(this, "A " + dependent + + " cannot be specified without a " + target); + result = false; + } + return result; + } + + /** + * Could validate the host field e.g. by establishing a connection. + * Currently no validation is done. + * + * @return + */ + private boolean validateHostField() { + boolean result = true; + // String value = proxyHostField.getText(); + return result; + } + + /** + * Save the currently set field values (if valid) to the + * {@link HttpProxyConfiguration}. Also applies those values to the + * currently running Taverna. + */ + private void applySettings() { + if (validateFields()) { + saveSettings(); + httpProxyConfiguration.changeProxySettings(); + } + } + + /** + * Set the shown field values to those currently in use (i.e. last saved + * configuration). + */ + private void setFields() { + shownOption = httpProxyConfiguration.getProperty(PROXY_USE_OPTION); + useSystemProperties.setSelected(shownOption + .equals(USE_SYSTEM_PROPERTIES_OPTION)); + useSpecifiedValues.setSelected(shownOption + .equals(USE_SPECIFIED_VALUES_OPTION)); + useNoProxy.setSelected(shownOption.equals(USE_NO_PROXY_OPTION)); + populateFields(); + } +}