http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuAction.java
 
b/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuAction.java
deleted file mode 100644
index cb7462e..0000000
--- 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuAction.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.ui.menu.AbstractMenuAction;
-import org.apache.taverna.workbench.edits.EditManager;
-import org.apache.taverna.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/bf8a7ea2/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuSection.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuSection.java
 
b/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuSection.java
deleted file mode 100644
index 7d63a68..0000000
--- 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/FileSaveMenuSection.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.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/bf8a7ea2/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/WorkflowsMenu.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/WorkflowsMenu.java
 
b/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/WorkflowsMenu.java
deleted file mode 100644
index 1ba6f45..0000000
--- 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/menu/WorkflowsMenu.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.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 org.apache.taverna.lang.observer.Observable;
-import org.apache.taverna.lang.observer.Observer;
-import org.apache.taverna.ui.menu.AbstractMenuCustom;
-import org.apache.taverna.workbench.edits.EditManager;
-import 
org.apache.taverna.workbench.edits.EditManager.AbstractDataflowEditEvent;
-import org.apache.taverna.workbench.edits.EditManager.EditManagerEvent;
-import org.apache.taverna.workbench.file.FileManager;
-import org.apache.taverna.workbench.file.events.AbstractDataflowEvent;
-import org.apache.taverna.workbench.file.events.FileManagerEvent;
-import org.apache.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/bf8a7ea2/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/CloseToolbarAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/CloseToolbarAction.java
 
b/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/CloseToolbarAction.java
deleted file mode 100644
index 19f3f59..0000000
--- 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/CloseToolbarAction.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.ui.menu.AbstractMenuAction;
-import org.apache.taverna.workbench.edits.EditManager;
-import org.apache.taverna.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/bf8a7ea2/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/FileToolbarMenuSection.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/FileToolbarMenuSection.java
 
b/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/FileToolbarMenuSection.java
deleted file mode 100644
index 26bb7bb..0000000
--- 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/FileToolbarMenuSection.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.ui.menu.DefaultToolBar.DEFAULT_TOOL_BAR;
-
-import java.net.URI;
-
-import org.apache.taverna.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/bf8a7ea2/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/NewToolbarAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/NewToolbarAction.java
 
b/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/NewToolbarAction.java
deleted file mode 100644
index b316459..0000000
--- 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/NewToolbarAction.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.ui.menu.AbstractMenuAction;
-import org.apache.taverna.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/bf8a7ea2/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenToolbarAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenToolbarAction.java
 
b/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenToolbarAction.java
deleted file mode 100644
index 0605e47..0000000
--- 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenToolbarAction.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.ui.menu.AbstractMenuAction;
-import org.apache.taverna.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/bf8a7ea2/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenWorkflowFromURLToolbarAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenWorkflowFromURLToolbarAction.java
 
b/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenWorkflowFromURLToolbarAction.java
deleted file mode 100644
index df7415e..0000000
--- 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/OpenWorkflowFromURLToolbarAction.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.ui.menu.AbstractMenuAction;
-import org.apache.taverna.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/bf8a7ea2/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/SaveToolbarAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/SaveToolbarAction.java
 
b/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/SaveToolbarAction.java
deleted file mode 100644
index df3046d..0000000
--- 
a/taverna-file-impl/src/main/java/net/sf/taverna/t2/workbench/file/impl/toolbar/SaveToolbarAction.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.ui.menu.AbstractMenuAction;
-import org.apache.taverna.workbench.edits.EditManager;
-import org.apache.taverna.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/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/DataflowFromDataflowPersistenceHandler.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/DataflowFromDataflowPersistenceHandler.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/DataflowFromDataflowPersistenceHandler.java
new file mode 100644
index 0000000..89f308f
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/DataflowFromDataflowPersistenceHandler.java
@@ -0,0 +1,65 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.taverna.workbench.file.AbstractDataflowPersistenceHandler;
+import org.apache.taverna.workbench.file.DataflowInfo;
+import org.apache.taverna.workbench.file.DataflowPersistenceHandler;
+import org.apache.taverna.workbench.file.FileType;
+import org.apache.taverna.workbench.file.exceptions.OpenException;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.Workflow;
+
+/**
+ * @author alanrw
+ */
+public class DataflowFromDataflowPersistenceHandler extends
+               AbstractDataflowPersistenceHandler implements
+               DataflowPersistenceHandler {
+       private static final WorkflowBundleFileType WORKFLOW_BUNDLE_FILE_TYPE = 
new WorkflowBundleFileType();
+
+       @Override
+       public DataflowInfo openDataflow(FileType fileType, Object source)
+                       throws OpenException {
+               if (!getOpenFileTypes().contains(fileType))
+                       throw new IllegalArgumentException("Unsupported file 
type "
+                                       + fileType);
+
+               WorkflowBundle workflowBundle = (WorkflowBundle) source;
+               Date lastModified = null;
+               Object canonicalSource = null;
+               return new DataflowInfo(WORKFLOW_BUNDLE_FILE_TYPE, 
canonicalSource,
+                               workflowBundle, lastModified);
+       }
+
+       @Override
+       public List<FileType> getOpenFileTypes() {
+               return Arrays.<FileType> asList(WORKFLOW_BUNDLE_FILE_TYPE);
+       }
+
+       @Override
+       public List<Class<?>> getOpenSourceTypes() {
+               return Arrays.<Class<?>> asList(Workflow.class);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/DataflowPersistenceHandlerRegistry.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/DataflowPersistenceHandlerRegistry.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/DataflowPersistenceHandlerRegistry.java
new file mode 100644
index 0000000..0026154
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/DataflowPersistenceHandlerRegistry.java
@@ -0,0 +1,237 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import static org.apache.commons.collections.map.LazyMap.decorate;
+import static org.apache.commons.lang.ClassUtils.getAllInterfaces;
+import static org.apache.commons.lang.ClassUtils.getAllSuperclasses;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.taverna.workbench.file.DataflowPersistenceHandler;
+import org.apache.taverna.workbench.file.FileType;
+
+import org.apache.commons.collections.Factory;
+
+// TODO: Cache lookups / build one massive structure
+public class DataflowPersistenceHandlerRegistry {
+       private static final MapFactory MAP_FACTORY = new MapFactory();
+       private static final SetFactory SET_FACTORY = new SetFactory();
+
+       @SuppressWarnings("unchecked")
+       protected static List<Class<?>> findAllParentClasses(
+                       final Class<?> sourceClass) {
+               List<Class<?>> superClasses = new ArrayList<>();
+               superClasses.add(sourceClass);
+               superClasses.addAll(getAllSuperclasses(sourceClass));
+               superClasses.addAll(getAllInterfaces(sourceClass));
+               return superClasses;
+       }
+
+       private Map<Class<?>, Set<DataflowPersistenceHandler>> 
openClassToHandlers;
+       private Map<Class<?>, Set<FileType>> openClassToTypes;
+       private Map<FileType, Map<Class<?>, Set<DataflowPersistenceHandler>>> 
openFileClassToHandler;
+       private Map<FileType, Set<DataflowPersistenceHandler>> 
openFileToHandler;
+       private Map<Class<?>, Set<DataflowPersistenceHandler>> 
saveClassToHandlers;
+       private Map<Class<?>, Set<FileType>> saveClassToTypes;
+       private Map<FileType, Map<Class<?>, Set<DataflowPersistenceHandler>>> 
saveFileClassToHandler;
+       private Map<FileType, Set<DataflowPersistenceHandler>> 
saveFileToHandler;
+
+       private List<DataflowPersistenceHandler> dataflowPersistenceHandlers;
+
+       public DataflowPersistenceHandlerRegistry() {
+       }
+
+       public Set<FileType> getOpenFileTypes() {
+               return getOpenFileClassToHandler().keySet();
+       }
+
+       public Set<FileType> getOpenFileTypesFor(Class<?> sourceClass) {
+               Set<FileType> fileTypes = new LinkedHashSet<>();
+               for (Class<?> candidateClass : 
findAllParentClasses(sourceClass))
+                       
fileTypes.addAll(getOpenClassToTypes().get(candidateClass));
+               return fileTypes;
+       }
+
+       public Set<DataflowPersistenceHandler> getOpenHandlersFor(
+                       Class<? extends Object> sourceClass) {
+               Set<DataflowPersistenceHandler> handlers = new 
LinkedHashSet<>();
+               for (Class<?> candidateClass : 
findAllParentClasses(sourceClass))
+                       
handlers.addAll(getOpenClassToHandlers().get(candidateClass));
+               return handlers;
+       }
+
+       public Set<DataflowPersistenceHandler> getOpenHandlersFor(
+                       FileType fileType, Class<? extends Object> sourceClass) 
{
+               Set<DataflowPersistenceHandler> handlers = new 
LinkedHashSet<>();
+               for (Class<?> candidateClass : 
findAllParentClasses(sourceClass))
+                       
handlers.addAll(getOpenFileClassToHandler().get(fileType).get(
+                                       candidateClass));
+               return handlers;
+       }
+
+       public Set<DataflowPersistenceHandler> getOpenHandlersForType(
+                       FileType fileType) {
+               return getOpenFileToHandler().get(fileType);
+       }
+
+       public synchronized Set<DataflowPersistenceHandler> 
getOpenHandlersForType(
+                       FileType fileType, Class<?> sourceClass) {
+               Set<DataflowPersistenceHandler> handlers = new 
LinkedHashSet<>();
+               for (Class<?> candidateClass : 
findAllParentClasses(sourceClass))
+                       
handlers.addAll(getOpenFileClassToHandler().get(fileType).get(
+                                       candidateClass));
+               return handlers;
+       }
+
+       public Set<FileType> getSaveFileTypes() {
+               return getSaveFileClassToHandler().keySet();
+       }
+
+       public Set<FileType> getSaveFileTypesFor(Class<?> destinationClass) {
+               Set<FileType> fileTypes = new LinkedHashSet<>();
+               for (Class<?> candidateClass : 
findAllParentClasses(destinationClass))
+                       
fileTypes.addAll(getSaveClassToTypes().get(candidateClass));
+               return fileTypes;
+       }
+
+       public Set<DataflowPersistenceHandler> getSaveHandlersFor(
+                       Class<? extends Object> destinationClass) {
+               Set<DataflowPersistenceHandler> handlers = new 
LinkedHashSet<>();
+               for (Class<?> candidateClass : 
findAllParentClasses(destinationClass))
+                       
handlers.addAll(getSaveClassToHandlers().get(candidateClass));
+               return handlers;
+       }
+
+       public Set<DataflowPersistenceHandler> getSaveHandlersForType(
+                       FileType fileType, Class<?> destinationClass) {
+               Set<DataflowPersistenceHandler> handlers = new 
LinkedHashSet<>();
+               for (Class<?> candidateClass : 
findAllParentClasses(destinationClass))
+                       
handlers.addAll(getSaveFileClassToHandler().get(fileType).get(
+                                       candidateClass));
+               return handlers;
+       }
+
+       @SuppressWarnings({ "unchecked", "rawtypes" })
+       private synchronized void createCollections() {
+               openFileClassToHandler = decorate(new HashMap(), MAP_FACTORY);
+               openFileToHandler = decorate(new HashMap(), SET_FACTORY);
+               openClassToTypes = decorate(new HashMap(), SET_FACTORY);
+               openClassToHandlers = decorate(new HashMap(), SET_FACTORY);
+
+               saveFileClassToHandler = decorate(new HashMap(), MAP_FACTORY);
+               saveFileToHandler = decorate(new HashMap(), SET_FACTORY);
+               saveClassToTypes = decorate(new HashMap(), SET_FACTORY);
+               saveClassToHandlers = decorate(new HashMap(), SET_FACTORY);
+       }
+
+       private Map<Class<?>, Set<DataflowPersistenceHandler>> 
getOpenClassToHandlers() {
+               return openClassToHandlers;
+       }
+
+       private synchronized Map<Class<?>, Set<FileType>> getOpenClassToTypes() 
{
+               return openClassToTypes;
+       }
+
+       private synchronized Map<FileType, Map<Class<?>, 
Set<DataflowPersistenceHandler>>> getOpenFileClassToHandler() {
+               return openFileClassToHandler;
+       }
+
+       private Map<FileType, Set<DataflowPersistenceHandler>> 
getOpenFileToHandler() {
+               return openFileToHandler;
+       }
+
+       private Map<Class<?>, Set<DataflowPersistenceHandler>> 
getSaveClassToHandlers() {
+               return saveClassToHandlers;
+       }
+
+       private synchronized Map<Class<?>, Set<FileType>> getSaveClassToTypes() 
{
+               return saveClassToTypes;
+       }
+
+       private synchronized Map<FileType, Map<Class<?>, 
Set<DataflowPersistenceHandler>>> getSaveFileClassToHandler() {
+               return saveFileClassToHandler;
+       }
+
+       /**
+        * Bind method for SpringDM.
+        * 
+        * @param service
+        * @param properties
+        */
+       public void update(Object service, Map<?, ?> properties) {
+               if (dataflowPersistenceHandlers != null)
+                       updateColletions();
+       }
+
+       public synchronized void updateColletions() {
+               createCollections();
+               for (DataflowPersistenceHandler handler : 
dataflowPersistenceHandlers) {
+                       for (FileType openFileType : 
handler.getOpenFileTypes()) {
+                               Set<DataflowPersistenceHandler> set = 
openFileToHandler
+                                               .get(openFileType);
+                               set.add(handler);
+                               for (Class<?> openClass : 
handler.getOpenSourceTypes()) {
+                                       
openFileClassToHandler.get(openFileType).get(openClass)
+                                                       .add(handler);
+                                       
openClassToTypes.get(openClass).add(openFileType);
+                               }
+                       }
+                       for (Class<?> openClass : handler.getOpenSourceTypes())
+                               openClassToHandlers.get(openClass).add(handler);
+
+                       for (FileType saveFileType : 
handler.getSaveFileTypes()) {
+                               
saveFileToHandler.get(saveFileType).add(handler);
+                               for (Class<?> saveClass : 
handler.getSaveDestinationTypes()) {
+                                       
saveFileClassToHandler.get(saveFileType).get(saveClass)
+                                                       .add(handler);
+                                       
saveClassToTypes.get(saveClass).add(saveFileType);
+                               }
+                       }
+                       for (Class<?> openClass : 
handler.getSaveDestinationTypes())
+                               saveClassToHandlers.get(openClass).add(handler);
+               }
+       }
+
+       public void setDataflowPersistenceHandlers(
+                       List<DataflowPersistenceHandler> 
dataflowPersistenceHandlers) {
+               this.dataflowPersistenceHandlers = dataflowPersistenceHandlers;
+       }
+
+       private static class MapFactory implements Factory {
+               @Override
+               @SuppressWarnings("rawtypes")
+               public Object create() {
+                       return decorate(new HashMap(), SET_FACTORY);
+               }
+       }
+
+       private static class SetFactory implements Factory {
+               @Override
+               public Object create() {
+                       return new LinkedHashSet<Object>();
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileDataflowInfo.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileDataflowInfo.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileDataflowInfo.java
new file mode 100644
index 0000000..c9e7ae5
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileDataflowInfo.java
@@ -0,0 +1,66 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+
+import org.apache.taverna.workbench.file.DataflowInfo;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.file.FileType;
+
+import org.apache.log4j.Logger;
+
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * Information about an open dataflow that was opened from or saved to a
+ * {@link File}.
+ * 
+ * @see DataflowInfo
+ * @see FileManager
+ * @author Stian Soiland-Reyes
+ */
+public class FileDataflowInfo extends DataflowInfo {
+       private static Logger logger = Logger.getLogger(FileDataflowInfo.class);
+
+       public FileDataflowInfo(FileType fileType, File source,
+                       WorkflowBundle workflowBundle) {
+               super(fileType, canonicalFile(source), workflowBundle,
+                               lastModifiedFile(source));
+       }
+
+       protected static Date lastModifiedFile(File file) {
+               long lastModifiedLong = file.lastModified();
+               if (lastModifiedLong == 0)
+                       return null;
+               return new Date(lastModifiedLong);
+       }
+
+       public static File canonicalFile(File file) {
+               try {
+                       return file.getCanonicalFile();
+               } catch (IOException e) {
+                       logger.warn("Could not find canonical file for " + 
file);
+                       return file;
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileManagerImpl.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileManagerImpl.java
new file mode 100644
index 0000000..c22341e
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileManagerImpl.java
@@ -0,0 +1,600 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import static java.awt.GraphicsEnvironment.isHeadless;
+import static java.util.Collections.singleton;
+import static javax.swing.SwingUtilities.invokeAndWait;
+import static javax.swing.SwingUtilities.isEventDispatchThread;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.swing.filechooser.FileFilter;
+
+import org.apache.taverna.lang.observer.MultiCaster;
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.workbench.edits.EditManager;
+import 
org.apache.taverna.workbench.edits.EditManager.AbstractDataflowEditEvent;
+import org.apache.taverna.workbench.edits.EditManager.EditManagerEvent;
+import org.apache.taverna.workbench.file.DataflowInfo;
+import org.apache.taverna.workbench.file.DataflowPersistenceHandler;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.file.FileType;
+import org.apache.taverna.workbench.file.events.ClosedDataflowEvent;
+import org.apache.taverna.workbench.file.events.ClosingDataflowEvent;
+import org.apache.taverna.workbench.file.events.FileManagerEvent;
+import org.apache.taverna.workbench.file.events.OpenedDataflowEvent;
+import org.apache.taverna.workbench.file.events.SavedDataflowEvent;
+import org.apache.taverna.workbench.file.events.SetCurrentDataflowEvent;
+import org.apache.taverna.workbench.file.exceptions.OpenException;
+import org.apache.taverna.workbench.file.exceptions.OverwriteException;
+import org.apache.taverna.workbench.file.exceptions.SaveException;
+import org.apache.taverna.workbench.file.exceptions.UnsavedException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.taverna.scufl2.api.common.Scufl2Tools;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+
+/**
+ * Implementation of {@link FileManager}
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class FileManagerImpl implements FileManager {
+       private static Logger logger = Logger.getLogger(FileManagerImpl.class);
+       private static int nameIndex = 1;
+
+       /**
+        * The last blank workflowBundle created using #newDataflow() until it 
has
+        * been changed - when this variable will be set to null again. Used to
+        * automatically close unmodified blank workflowBundles on open.
+        */
+       private WorkflowBundle blankWorkflowBundle = null;
+       @SuppressWarnings("unused")
+       private EditManager editManager;
+       private EditManagerObserver editManagerObserver = new 
EditManagerObserver();
+       protected MultiCaster<FileManagerEvent> observers = new 
MultiCaster<>(this);
+       /**
+        * Ordered list of open WorkflowBundle
+        */
+       private LinkedHashMap<WorkflowBundle, OpenDataflowInfo> 
openDataflowInfos = new LinkedHashMap<>();
+       private DataflowPersistenceHandlerRegistry 
dataflowPersistenceHandlerRegistry;
+       private Scufl2Tools scufl2Tools = new Scufl2Tools();
+       private WorkflowBundle currentWorkflowBundle;
+
+       public DataflowPersistenceHandlerRegistry 
getPersistanceHandlerRegistry() {
+               return dataflowPersistenceHandlerRegistry;
+       }
+
+       public FileManagerImpl(EditManager editManager) {
+               this.editManager = editManager;
+               editManager.addObserver(editManagerObserver);
+       }
+
+       /**
+        * Add an observer to be notified of {@link FileManagerEvent}s, such as
+        * {@link OpenedDataflowEvent} and {@link SavedDataflowEvent}.
+        * 
+        * {@inheritDoc}
+        */
+       @Override
+       public void addObserver(Observer<FileManagerEvent> observer) {
+               observers.addObserver(observer);
+       }
+
+       @Override
+       public boolean canSaveWithoutDestination(WorkflowBundle workflowBundle) 
{
+               OpenDataflowInfo dataflowInfo = 
getOpenDataflowInfo(workflowBundle);
+               if (dataflowInfo.getSource() == null)
+                       return false;
+               Set<?> handlers = getPersistanceHandlerRegistry()
+                               .getSaveHandlersForType(
+                                               dataflowInfo.getFileType(),
+                                               
dataflowInfo.getDataflowInfo().getCanonicalSource()
+                                                               .getClass());
+               return !handlers.isEmpty();
+       }
+
+       @Override
+       public boolean closeDataflow(WorkflowBundle workflowBundle,
+                       boolean failOnUnsaved) throws UnsavedException {
+               if (workflowBundle == null)
+                       throw new NullPointerException("Dataflow can't be 
null");
+               ClosingDataflowEvent message = new 
ClosingDataflowEvent(workflowBundle);
+               observers.notify(message);
+               if (message.isAbortClose())
+                       return false;
+               if ((failOnUnsaved && 
getOpenDataflowInfo(workflowBundle).isChanged()))
+                       throw new UnsavedException(workflowBundle);
+               if (workflowBundle.equals(getCurrentDataflow())) {
+                       // We'll need to change current workflowBundle
+                       // Find best candidate to the left or right
+                       List<WorkflowBundle> workflowBundles = 
getOpenDataflows();
+                       int openIndex = workflowBundles.indexOf(workflowBundle);
+                       if (openIndex == -1)
+                               throw new IllegalArgumentException("Workflow 
was not opened "
+                                               + workflowBundle);
+
+                       if (openIndex > 0)
+                               
setCurrentDataflow(workflowBundles.get(openIndex - 1));
+                       else if (openIndex == 0 && workflowBundles.size() > 1)
+                               setCurrentDataflow(workflowBundles.get(1));
+                       else
+                               // If it was the last one, start a new, empty 
workflowBundle
+                               newDataflow();
+               }
+               if (workflowBundle == blankWorkflowBundle)
+                       blankWorkflowBundle = null;
+               openDataflowInfos.remove(workflowBundle);
+               observers.notify(new ClosedDataflowEvent(workflowBundle));
+               return true;
+       }
+
+       @Override
+       public WorkflowBundle getCurrentDataflow() {
+               return currentWorkflowBundle;
+       }
+
+       @Override
+       public WorkflowBundle getDataflowBySource(Object source) {
+               for (Entry<WorkflowBundle, OpenDataflowInfo> infoEntry : 
openDataflowInfos
+                               .entrySet()) {
+                       OpenDataflowInfo info = infoEntry.getValue();
+                       if (source.equals(info.getSource()))
+                               return infoEntry.getKey();
+               }
+               // Not found
+               return null;
+       }
+
+       @Override
+       public String getDataflowName(WorkflowBundle workflowBundle) {
+               Object source = null;
+               if (isDataflowOpen(workflowBundle))
+                       source = getDataflowSource(workflowBundle);
+               // Fallback
+               String name;
+               Workflow workflow = workflowBundle.getMainWorkflow();
+               if (workflow != null)
+                       name = workflow.getName();
+               else
+                       name = workflowBundle.getName();
+               if (source == null)
+                       return name;
+               if (source instanceof File)
+                       return ((File) source).getAbsolutePath();
+               else if (source instanceof URL)
+                       return source.toString();
+
+               // Check if it has implemented a toString() method
+               Method toStringMethod = null;
+               Method toStringMethodFromObject = null;
+               try {
+                       toStringMethod = 
source.getClass().getMethod("toString");
+                       toStringMethodFromObject = 
Object.class.getMethod("toString");
+               } catch (Exception e) {
+                       throw new IllegalStateException(
+                                       "Source did not implement 
Object.toString() " + source);
+               }
+               if (!toStringMethod.equals(toStringMethodFromObject))
+                       return source.toString();
+               return name;
+       }
+
+       @Override
+       public String getDefaultWorkflowName() {
+               return "Workflow" + (nameIndex++);
+       }
+
+       @Override
+       public Object getDataflowSource(WorkflowBundle workflowBundle) {
+               return getOpenDataflowInfo(workflowBundle).getSource();
+       }
+
+       @Override
+       public FileType getDataflowType(WorkflowBundle workflowBundle) {
+               return getOpenDataflowInfo(workflowBundle).getFileType();
+       }
+
+       @Override
+       public List<Observer<FileManagerEvent>> getObservers() {
+               return observers.getObservers();
+       }
+
+       /**
+        * Get the {@link OpenDataflowInfo} for the given WorkflowBundle
+        * 
+        * @throws NullPointerException
+        *             if the WorkflowBundle was <code>null</code>
+        * @throws IllegalArgumentException
+        *             if the WorkflowBundle was not open.
+        * @param workflowBundle
+        *            WorkflowBundle which information is to be found
+        * @return The {@link OpenDataflowInfo} describing the WorkflowBundle
+        */
+       protected synchronized OpenDataflowInfo getOpenDataflowInfo(
+                       WorkflowBundle workflowBundle) {
+               if (workflowBundle == null)
+                       throw new NullPointerException("Dataflow can't be 
null");
+               OpenDataflowInfo info = openDataflowInfos.get(workflowBundle);
+               if (info == null)
+                       throw new IllegalArgumentException("Workflow was not 
opened "
+                                       + workflowBundle);
+               return info;
+       }
+
+       @Override
+       public List<WorkflowBundle> getOpenDataflows() {
+               return new ArrayList<>(openDataflowInfos.keySet());
+       }
+
+       @Override
+       public List<FileFilter> getOpenFileFilters() {
+               List<FileFilter> fileFilters = new ArrayList<>();
+
+               Set<FileType> fileTypes = getPersistanceHandlerRegistry()
+                               .getOpenFileTypes();
+               if (!fileTypes.isEmpty())
+                       fileFilters.add(new MultipleFileTypes(fileTypes,
+                                       "All supported workflows"));
+               for (FileType fileType : fileTypes)
+                       fileFilters.add(new FileTypeFileFilter(fileType));
+               return fileFilters;
+       }
+
+       @Override
+       public List<FileFilter> getOpenFileFilters(Class<?> sourceClass) {
+               List<FileFilter> fileFilters = new ArrayList<>();
+               for (FileType fileType : getPersistanceHandlerRegistry()
+                               .getOpenFileTypesFor(sourceClass))
+                       fileFilters.add(new FileTypeFileFilter(fileType));
+               return fileFilters;
+       }
+
+       @Override
+       public List<FileFilter> getSaveFileFilters() {
+               List<FileFilter> fileFilters = new ArrayList<>();
+               for (FileType fileType : getPersistanceHandlerRegistry()
+                               .getSaveFileTypes())
+                       fileFilters.add(new FileTypeFileFilter(fileType));
+               return fileFilters;
+       }
+
+       @Override
+       public List<FileFilter> getSaveFileFilters(Class<?> destinationClass) {
+               List<FileFilter> fileFilters = new ArrayList<>();
+               for (FileType fileType : getPersistanceHandlerRegistry()
+                               .getSaveFileTypesFor(destinationClass))
+                       fileFilters.add(new FileTypeFileFilter(fileType));
+               return fileFilters;
+       }
+
+       @Override
+       public boolean isDataflowChanged(WorkflowBundle workflowBundle) {
+               return getOpenDataflowInfo(workflowBundle).isChanged();
+       }
+
+       @Override
+       public boolean isDataflowOpen(WorkflowBundle workflowBundle) {
+               return openDataflowInfos.containsKey(workflowBundle);
+       }
+
+       @Override
+       public WorkflowBundle newDataflow() {
+               WorkflowBundle workflowBundle = new WorkflowBundle();
+               workflowBundle.setMainWorkflow(new Workflow());
+               
workflowBundle.getMainWorkflow().setName(getDefaultWorkflowName());
+               workflowBundle.setMainProfile(new Profile());
+               scufl2Tools.setParents(workflowBundle);
+               blankWorkflowBundle = null;
+               openDataflowInternal(workflowBundle);
+               blankWorkflowBundle = workflowBundle;
+               observers.notify(new OpenedDataflowEvent(workflowBundle));
+               return workflowBundle;
+       }
+
+       @Override
+       public void openDataflow(WorkflowBundle workflowBundle) {
+               openDataflowInternal(workflowBundle);
+               observers.notify(new OpenedDataflowEvent(workflowBundle));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public WorkflowBundle openDataflow(FileType fileType, Object source)
+                       throws OpenException {
+               if (isHeadless())
+                       return performOpenDataflow(fileType, source);
+
+               OpenDataflowRunnable r = new OpenDataflowRunnable(this, 
fileType,
+                               source);
+               if (isEventDispatchThread()) {
+                       r.run();
+               } else
+                       try {
+                               invokeAndWait(r);
+                       } catch (InterruptedException | 
InvocationTargetException e) {
+                               throw new OpenException("Opening was 
interrupted", e);
+                       }
+               OpenException thrownException = r.getException();
+               if (thrownException != null)
+                       throw thrownException;
+               return r.getDataflow();
+       }
+
+       public WorkflowBundle performOpenDataflow(FileType fileType, Object 
source)
+                       throws OpenException {
+               DataflowInfo dataflowInfo;
+               WorkflowBundle workflowBundle;
+               dataflowInfo = openDataflowSilently(fileType, source);
+               workflowBundle = dataflowInfo.getDataflow();
+               openDataflowInternal(workflowBundle);
+               getOpenDataflowInfo(workflowBundle).setOpenedFrom(dataflowInfo);
+               observers.notify(new OpenedDataflowEvent(workflowBundle));
+               return workflowBundle;
+       }
+
+       @Override
+       public DataflowInfo openDataflowSilently(FileType fileType, Object 
source)
+                       throws OpenException {
+               Set<DataflowPersistenceHandler> handlers;
+               Class<? extends Object> sourceClass = source.getClass();
+
+               boolean unknownFileType = (fileType == null);
+               if (unknownFileType)
+                       handlers = 
getPersistanceHandlerRegistry().getOpenHandlersFor(
+                                       sourceClass);
+               else
+                       handlers = 
getPersistanceHandlerRegistry().getOpenHandlersFor(
+                                       fileType, sourceClass);
+               if (handlers.isEmpty())
+                       throw new OpenException("Unsupported file type or class 
"
+                                       + fileType + " " + sourceClass);
+
+               Throwable lastException = null;
+               for (DataflowPersistenceHandler handler : handlers) {
+                       Collection<FileType> fileTypes;
+                       if (unknownFileType)
+                               fileTypes = handler.getOpenFileTypes();
+                       else
+                               fileTypes = singleton(fileType);
+                       for (FileType candidateFileType : fileTypes) {
+                               if (unknownFileType && (source instanceof File))
+                                       /*
+                                        * If source is file but fileType was 
not explicitly set
+                                        * from the open workflow dialog - 
check the file extension
+                                        * and decide which handler to use 
based on that (so that we
+                                        * do not loop though all handlers)
+                                        */
+                                       if (!((File) source).getPath().endsWith(
+                                                       
candidateFileType.getExtension()))
+                                               continue;
+
+                               try {
+                                       DataflowInfo openDataflow = 
handler.openDataflow(
+                                                       candidateFileType, 
source);
+                                       WorkflowBundle workflowBundle = 
openDataflow.getDataflow();
+                                       logger.info("Loaded workflow: " + 
workflowBundle.getName()
+                                                       + " " + 
workflowBundle.getGlobalBaseURI()
+                                                       + " from " + source + " 
using " + handler);
+                                       return openDataflow;
+                               } catch (OpenException ex) {
+                                       logger.warn("Could not open workflow " 
+ source + " using "
+                                                       + handler + " of type " 
+ candidateFileType);
+                                       lastException = ex;
+                               }
+                       }
+               }
+               throw new OpenException("Could not open workflow " + source + 
"\n",
+                               lastException);
+       }
+
+       /**
+        * Mark the WorkflowBundle as opened, and close the blank 
WorkflowBundle if
+        * needed.
+        * 
+        * @param workflowBundle
+        *            WorkflowBundle that has been opened
+        */
+       protected void openDataflowInternal(WorkflowBundle workflowBundle) {
+               if (workflowBundle == null)
+                       throw new NullPointerException("Dataflow can't be 
null");
+               if (isDataflowOpen(workflowBundle))
+                       throw new IllegalArgumentException("Workflow is already 
open: "
+                                       + workflowBundle);
+
+               openDataflowInfos.put(workflowBundle, new OpenDataflowInfo());
+               setCurrentDataflow(workflowBundle);
+               if (openDataflowInfos.size() == 2 && blankWorkflowBundle != 
null)
+                       /*
+                        * Behave like a word processor and close the blank 
WorkflowBundle
+                        * when another workflow has been opened
+                        */
+                       try {
+                               closeDataflow(blankWorkflowBundle, true);
+                       } catch (UnsavedException e) {
+                               logger.error("Blank workflow was modified "
+                                               + "and could not be closed");
+                       }
+       }
+
+       @Override
+       public void removeObserver(Observer<FileManagerEvent> observer) {
+               observers.removeObserver(observer);
+       }
+
+       @Override
+       public void saveDataflow(WorkflowBundle workflowBundle,
+                       boolean failOnOverwrite) throws SaveException {
+               if (workflowBundle == null)
+                       throw new NullPointerException("Dataflow can't be 
null");
+               OpenDataflowInfo lastSave = getOpenDataflowInfo(workflowBundle);
+               if (lastSave.getSource() == null)
+                       throw new SaveException("Can't save without source "
+                                       + workflowBundle);
+               saveDataflow(workflowBundle, lastSave.getFileType(),
+                               lastSave.getSource(), failOnOverwrite);
+       }
+
+       @Override
+       public void saveDataflow(WorkflowBundle workflowBundle, FileType 
fileType,
+                       Object destination, boolean failOnOverwrite) throws 
SaveException {
+               DataflowInfo savedDataflow = 
saveDataflowSilently(workflowBundle,
+                               fileType, destination, failOnOverwrite);
+               getOpenDataflowInfo(workflowBundle).setSavedTo(savedDataflow);
+               observers.notify(new SavedDataflowEvent(workflowBundle));
+       }
+
+       @Override
+       public DataflowInfo saveDataflowSilently(WorkflowBundle workflowBundle,
+                       FileType fileType, Object destination, boolean 
failOnOverwrite)
+                       throws SaveException, OverwriteException {
+               Set<DataflowPersistenceHandler> handlers;
+
+               Class<? extends Object> destinationClass = 
destination.getClass();
+               if (fileType != null)
+                       handlers = 
getPersistanceHandlerRegistry().getSaveHandlersForType(
+                                       fileType, destinationClass);
+               else
+                       handlers = 
getPersistanceHandlerRegistry().getSaveHandlersFor(
+                                       destinationClass);
+
+               SaveException lastException = null;
+               for (DataflowPersistenceHandler handler : handlers) {
+                       if (failOnOverwrite) {
+                               OpenDataflowInfo openDataflowInfo = 
getOpenDataflowInfo(workflowBundle);
+                               if 
(handler.wouldOverwriteDataflow(workflowBundle, fileType,
+                                               destination, 
openDataflowInfo.getDataflowInfo()))
+                                       throw new 
OverwriteException(destination);
+                       }
+                       try {
+                               DataflowInfo savedDataflow = 
handler.saveDataflow(
+                                               workflowBundle, fileType, 
destination);
+                               savedDataflow.getDataflow();
+                               logger.info("Saved workflow: " + 
workflowBundle.getName() + " "
+                                               + 
workflowBundle.getGlobalBaseURI() + " to "
+                                               + 
savedDataflow.getCanonicalSource() + " using "
+                                               + handler);
+                               return savedDataflow;
+                       } catch (SaveException ex) {
+                               logger.warn("Could not save to " + destination 
+ " using "
+                                               + handler);
+                               lastException = ex;
+                       }
+               }
+
+               if (lastException == null)
+                       throw new SaveException("Unsupported file type or class 
"
+                                       + fileType + " " + destinationClass);
+               throw new SaveException("Could not save to " + destination + 
":\n"
+                               + lastException.getLocalizedMessage(), 
lastException);
+       }
+
+       @Override
+       public void setCurrentDataflow(WorkflowBundle workflowBundle) {
+               setCurrentDataflow(workflowBundle, false);
+       }
+
+       @Override
+       public void setCurrentDataflow(WorkflowBundle workflowBundle,
+                       boolean openIfNeeded) {
+               currentWorkflowBundle = workflowBundle;
+               if (!isDataflowOpen(workflowBundle)) {
+                       if (!openIfNeeded)
+                               throw new IllegalArgumentException("Workflow is 
not open: "
+                                               + workflowBundle);
+                       openDataflow(workflowBundle);
+                       return;
+               }
+               observers.notify(new SetCurrentDataflowEvent(workflowBundle));
+       }
+
+       @Override
+       public void setDataflowChanged(WorkflowBundle workflowBundle,
+                       boolean isChanged) {
+               getOpenDataflowInfo(workflowBundle).setIsChanged(isChanged);
+               if (blankWorkflowBundle == workflowBundle)
+                       blankWorkflowBundle = null;
+       }
+
+       @Override
+       public Object getCanonical(Object source) throws 
IllegalArgumentException,
+                       URISyntaxException, IOException {
+               Object canonicalSource = source;
+
+               if (source instanceof URL) {
+                       URL url = ((URL) source);
+                       if (url.getProtocol().equalsIgnoreCase("file"))
+                               canonicalSource = new File(url.toURI());
+               }
+
+               if (canonicalSource instanceof File)
+                       canonicalSource = ((File) 
canonicalSource).getCanonicalFile();
+               return canonicalSource;
+       }
+
+       public void setDataflowPersistenceHandlerRegistry(
+                       DataflowPersistenceHandlerRegistry 
dataflowPersistenceHandlerRegistry) {
+               this.dataflowPersistenceHandlerRegistry = 
dataflowPersistenceHandlerRegistry;
+       }
+
+       /**
+        * Observe the {@link EditManager} for changes to open workflowBundles. 
A
+        * change of an open workflow would set it as changed using
+        * {@link FileManagerImpl#setDataflowChanged(Dataflow, boolean)}.
+        * 
+        * @author Stian Soiland-Reyes
+        * 
+        */
+       private final class EditManagerObserver implements
+                       Observer<EditManagerEvent> {
+               @Override
+               public void notify(Observable<EditManagerEvent> sender,
+                               EditManagerEvent message) throws Exception {
+                       if (message instanceof AbstractDataflowEditEvent) {
+                               AbstractDataflowEditEvent dataflowEdit = 
(AbstractDataflowEditEvent) message;
+                               WorkflowBundle workflowBundle = 
dataflowEdit.getDataFlow();
+                               /**
+                                * TODO: on undo/redo - keep last event or 
similar to determine
+                                * if workflow was saved before. See
+                                * FileManagerTest#isChangedWithUndo().
+                                */
+                               setDataflowChanged(workflowBundle, true);
+                       }
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileTypeFileFilter.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileTypeFileFilter.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileTypeFileFilter.java
new file mode 100644
index 0000000..0d87dc1
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/FileTypeFileFilter.java
@@ -0,0 +1,54 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+import org.apache.taverna.workbench.file.FileType;
+
+public class FileTypeFileFilter extends FileFilter {
+       private final FileType fileType;
+
+       public FileTypeFileFilter(FileType fileType) {
+               this.fileType = fileType;
+       }
+
+       @Override
+       public String getDescription() {
+               return fileType.getDescription();
+       }
+
+       @Override
+       public boolean accept(File file) {
+               if (file.isDirectory())
+                       // Don't grey out directories
+                       return true;
+               if (fileType.getExtension() == null)
+                       return false;
+               return file.getName().toLowerCase()
+                               .endsWith("." + fileType.getExtension());
+       }
+
+       public FileType getFileType() {
+               return fileType;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/MultipleFileTypes.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/MultipleFileTypes.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/MultipleFileTypes.java
new file mode 100644
index 0000000..410b600
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/MultipleFileTypes.java
@@ -0,0 +1,57 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import java.io.File;
+import java.util.Set;
+
+import javax.swing.filechooser.FileFilter;
+
+import org.apache.taverna.workbench.file.FileType;
+
+public class MultipleFileTypes extends FileFilter {
+       private String description;
+       private final Set<FileType> fileTypes;
+
+       public MultipleFileTypes(Set<FileType> fileTypes, String description) {
+               this.fileTypes = fileTypes;
+               this.description = description;
+       }
+
+       @Override
+       public String getDescription() {
+               return description;
+       }
+
+       @Override
+       public boolean accept(File file) {
+               if (file.isDirectory())
+                       return true;
+
+               String lowerFileName = file.getName().toLowerCase();
+               for (FileType fileType : fileTypes) {
+                       if (fileType.getExtension() == null)
+                               continue;
+                       if (lowerFileName.endsWith(fileType.getExtension()))
+                               return true;
+               }
+               return false;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowInProgressDialog.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowInProgressDialog.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowInProgressDialog.java
new file mode 100644
index 0000000..6a30517
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowInProgressDialog.java
@@ -0,0 +1,86 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import static java.awt.BorderLayout.CENTER;
+import static org.apache.taverna.workbench.MainWindow.getMainWindow;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.workingIcon;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.taverna.workbench.helper.HelpEnabledDialog;
+
+/**
+ * Dialog that is popped up while we are opening a workflow.
+ * 
+ * @author Alex Nenadic
+ * @author Alan R Williams
+ */
+@SuppressWarnings("serial")
+public class OpenDataflowInProgressDialog extends HelpEnabledDialog {
+       private boolean userCancelled = false;
+
+       public OpenDataflowInProgressDialog() {
+               super(getMainWindow(), "Opening workflow", true);
+               setResizable(false);
+               setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+               
+               JPanel panel = new JPanel(new BorderLayout());
+               panel.setBorder(new EmptyBorder(10,10,10,10));
+               
+               JPanel textPanel = new JPanel();
+               JLabel text = new JLabel(workingIcon);
+               text.setText("Opening workflow...");
+               text.setBorder(new EmptyBorder(10,0,10,0));
+               textPanel.add(text);
+               panel.add(textPanel, CENTER);
+               
+/*
+ * Cancellation does not work when opening
+ 
+               // Cancel button
+               JButton cancelButton = new JButton("Cancel");
+               cancelButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               userCancelled = true;
+                               setVisible(false);
+                               dispose();
+                       }
+               });
+               JPanel cancelButtonPanel = new JPanel();
+               cancelButtonPanel.add(cancelButton);
+               panel.add(cancelButtonPanel, BorderLayout.SOUTH);
+*/
+               setContentPane(panel);
+               setPreferredSize(new Dimension(300, 100));
+
+               pack();         
+       }
+
+       public boolean hasUserCancelled() {
+               return userCancelled;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowInfo.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowInfo.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowInfo.java
new file mode 100644
index 0000000..f3e722d
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowInfo.java
@@ -0,0 +1,92 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import java.util.Date;
+
+import org.apache.taverna.workbench.file.DataflowInfo;
+import org.apache.taverna.workbench.file.FileType;
+
+/**
+ * Information about an open dataflow.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class OpenDataflowInfo {
+       private DataflowInfo dataflowInfo;
+       private boolean isChanged;
+       private Date openedAt;
+
+       public OpenDataflowInfo() {
+       }
+
+       public FileType getFileType() {
+               if (dataflowInfo == null)
+                       return null;
+               return dataflowInfo.getFileType();
+       }
+
+       public Date getLastModified() {
+               if (dataflowInfo == null)
+                       return null;
+               return dataflowInfo.getLastModified();
+       }
+
+       public Date getOpenedAtDate() {
+               return openedAt;
+       }
+
+       public Object getSource() {
+               if (dataflowInfo == null)
+                       return null;
+               return dataflowInfo.getCanonicalSource();
+       }
+
+       public boolean isChanged() {
+               return isChanged;
+       }
+
+       public void setIsChanged(boolean isChanged) {
+               this.isChanged = isChanged;
+       }
+
+       public synchronized void setOpenedFrom(DataflowInfo dataflowInfo) {
+               setDataflowInfo(dataflowInfo);
+               setOpenedAt(new Date());
+               setIsChanged(false);
+       }
+
+       public synchronized void setSavedTo(DataflowInfo dataflowInfo) {
+               setDataflowInfo(dataflowInfo);
+               setIsChanged(false);
+       }
+
+       private void setDataflowInfo(DataflowInfo dataflowInfo) {
+               this.dataflowInfo = dataflowInfo;
+       }
+
+       private void setOpenedAt(Date openedAt) {
+               this.openedAt = openedAt;
+       }
+
+       public DataflowInfo getDataflowInfo() {
+               return dataflowInfo;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowRunnable.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowRunnable.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowRunnable.java
new file mode 100644
index 0000000..fabd953
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowRunnable.java
@@ -0,0 +1,87 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import static java.lang.Thread.sleep;
+import org.apache.taverna.workbench.file.FileType;
+import org.apache.taverna.workbench.file.exceptions.OpenException;
+import org.apache.taverna.workbench.ui.SwingWorkerCompletionWaiter;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * @author alanrw
+ */
+public class OpenDataflowRunnable implements Runnable {
+       private final FileManagerImpl fileManager;
+       private final FileType fileType;
+       private final Object source;
+       private WorkflowBundle dataflow;
+       private OpenException e;
+
+       public OpenDataflowRunnable(FileManagerImpl fileManager, FileType 
fileType,
+                       Object source) {
+               this.fileManager = fileManager;
+               this.fileType = fileType;
+               this.source = source;
+       }
+
+       @Override
+       public void run() {
+               OpenDataflowSwingWorker openDataflowSwingWorker = new 
OpenDataflowSwingWorker(
+                               fileType, source, fileManager);
+               OpenDataflowInProgressDialog dialog = new 
OpenDataflowInProgressDialog();
+               openDataflowSwingWorker
+                               .addPropertyChangeListener(new 
SwingWorkerCompletionWaiter(
+                                               dialog));
+               openDataflowSwingWorker.execute();
+
+               /*
+                * Give a chance to the SwingWorker to finish so we do not have 
to
+                * display the dialog
+                */
+               try {
+                       sleep(500);
+               } catch (InterruptedException e) {
+                   this.e = new OpenException("Opening was interrupted");
+               }
+               if (!openDataflowSwingWorker.isDone())
+                       dialog.setVisible(true); // this will block the GUI
+               boolean userCancelled = dialog.hasUserCancelled(); // see if 
user cancelled the dialog
+
+               if (userCancelled) {
+                       // Stop the OpenDataflowSwingWorker if it is still 
working
+                       openDataflowSwingWorker.cancel(true);
+                       dataflow = null;
+                       this.e = new OpenException("Opening was cancelled");
+                       // exit
+                       return;
+               }
+               dataflow = openDataflowSwingWorker.getDataflow();
+               this.e = openDataflowSwingWorker.getException();
+       }
+
+       public WorkflowBundle getDataflow() {
+               return dataflow;
+       }
+
+       public OpenException getException() {
+               return this.e;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowSwingWorker.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowSwingWorker.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowSwingWorker.java
new file mode 100644
index 0000000..c458f16
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/OpenDataflowSwingWorker.java
@@ -0,0 +1,66 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import javax.swing.SwingWorker;
+
+import org.apache.taverna.workbench.file.FileType;
+import org.apache.taverna.workbench.file.exceptions.OpenException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+
+public class OpenDataflowSwingWorker extends
+               SwingWorker<WorkflowBundle, Object> {
+       @SuppressWarnings("unused")
+       private Logger logger = Logger.getLogger(OpenDataflowSwingWorker.class);
+       private FileType fileType;
+       private Object source;
+       private FileManagerImpl fileManagerImpl;
+       private WorkflowBundle workflowBundle;
+       private OpenException e = null;
+
+       public OpenDataflowSwingWorker(FileType fileType, Object source,
+                       FileManagerImpl fileManagerImpl) {
+               this.fileType = fileType;
+               this.source = source;
+               this.fileManagerImpl = fileManagerImpl;
+       }
+
+       @Override
+       protected WorkflowBundle doInBackground() throws Exception {
+               try {
+                       workflowBundle = 
fileManagerImpl.performOpenDataflow(fileType,
+                                       source);
+               } catch (OpenException e) {
+                       this.e = e;
+               }
+               return workflowBundle;
+       }
+
+       public WorkflowBundle getDataflow() {
+               return workflowBundle;
+       }
+
+       public OpenException getException() {
+               return e;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/T2DataflowOpener.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/T2DataflowOpener.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/T2DataflowOpener.java
new file mode 100644
index 0000000..6923443
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/T2DataflowOpener.java
@@ -0,0 +1,143 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.taverna.workbench.file.AbstractDataflowPersistenceHandler;
+import org.apache.taverna.workbench.file.DataflowInfo;
+import org.apache.taverna.workbench.file.DataflowPersistenceHandler;
+import org.apache.taverna.workbench.file.FileType;
+import org.apache.taverna.workbench.file.exceptions.OpenException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.io.ReaderException;
+import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
+
+public class T2DataflowOpener extends AbstractDataflowPersistenceHandler
+               implements DataflowPersistenceHandler {
+       private static final T2FlowFileType T2_FLOW_FILE_TYPE = new 
T2FlowFileType();
+       private static Logger logger = Logger.getLogger(T2DataflowOpener.class);
+
+       private WorkflowBundleIO workflowBundleIO;
+
+       @SuppressWarnings("resource")
+       @Override
+       public DataflowInfo openDataflow(FileType fileType, Object source)
+                       throws OpenException {
+               if (!getOpenFileTypes().contains(fileType))
+                       throw new OpenException("Unsupported file type "
+                                       + fileType);
+               InputStream inputStream;
+               Date lastModified = null;
+               Object canonicalSource = source;
+               if (source instanceof InputStream)
+                       inputStream = (InputStream) source;
+               else if (source instanceof File)
+                       try {
+                               inputStream = new FileInputStream((File) 
source);
+                       } catch (FileNotFoundException e) {
+                               throw new OpenException("Could not open file " 
+ source + ":\n" + e.getLocalizedMessage(), e);
+                       }
+               else if (source instanceof URL) {
+                       URL url = ((URL) source);
+                       try {
+                               URLConnection connection = url.openConnection();
+                               connection.setRequestProperty("Accept", 
"text/xml");
+                               inputStream = connection.getInputStream();
+                               if (connection.getLastModified() != 0)
+                                       lastModified = new 
Date(connection.getLastModified());
+                       } catch (IOException e) {
+                               throw new OpenException("Could not open 
connection to URL "
+                                               + source+ ":\n" + 
e.getLocalizedMessage(), e);
+                       }
+                       try {
+                               if (url.getProtocol().equalsIgnoreCase("file"))
+                                       canonicalSource = new File(url.toURI());
+                       } catch (URISyntaxException e) {
+                               logger.warn("Invalid file URI created from " + 
url);
+                       }
+               } else {
+                       throw new OpenException("Unsupported source type "
+                                       + source.getClass());
+               }
+
+               final WorkflowBundle workflowBundle;
+               try {
+                       workflowBundle = openDataflowStream(inputStream);
+               } finally {
+                       try {
+                               if (!(source instanceof InputStream))
+                                       // We created the stream, we'll close it
+                                       inputStream.close();
+                       } catch (IOException ex) {
+                               logger.warn("Could not close inputstream " + 
inputStream, ex);
+                       }
+               }
+               if (canonicalSource instanceof File)
+                       return new FileDataflowInfo(T2_FLOW_FILE_TYPE,
+                                       (File) canonicalSource, workflowBundle);
+               return new DataflowInfo(T2_FLOW_FILE_TYPE, canonicalSource,
+                               workflowBundle, lastModified);
+       }
+
+       protected WorkflowBundle openDataflowStream(InputStream 
workflowXMLstream)
+                       throws OpenException {
+               WorkflowBundle workflowBundle;
+               try {
+                       workflowBundle = 
workflowBundleIO.readBundle(workflowXMLstream, null);
+               } catch (ReaderException e) {
+                       throw new OpenException("Could not read the workflow", 
e);
+               } catch (IOException e) {
+                       throw new OpenException("Could not open the workflow 
file for parsing", e);
+               } catch (Exception e) {
+                       throw new OpenException("Error while opening workflow", 
e);
+               }
+
+               return workflowBundle;
+       }
+
+       @Override
+       public List<FileType> getOpenFileTypes() {
+               return Arrays.<FileType> asList(new T2FlowFileType());
+       }
+
+       @Override
+       public List<Class<?>> getOpenSourceTypes() {
+               return Arrays.<Class<?>> asList(InputStream.class, URL.class,
+                               File.class);
+       }
+
+       public void setWorkflowBundleIO(WorkflowBundleIO workflowBundleIO) {
+               this.workflowBundleIO = workflowBundleIO;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/T2FileFilter.java
----------------------------------------------------------------------
diff --git 
a/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/T2FileFilter.java
 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/T2FileFilter.java
new file mode 100644
index 0000000..5d379f2
--- /dev/null
+++ 
b/taverna-file-impl/src/main/java/org/apache/taverna/workbench/file/impl/T2FileFilter.java
@@ -0,0 +1,36 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.file.impl;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+public class T2FileFilter extends FileFilter {
+       @Override
+       public boolean accept(final File file) {
+               return file.getName().toLowerCase().endsWith(".t2flow");
+       }
+
+       @Override
+       public String getDescription() {
+               return "Taverna 2 workflows";
+       }
+}

Reply via email to