You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by re...@apache.org on 2015/03/27 16:33:36 UTC

[08/11] incubator-taverna-workbench git commit:

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";
+	}
+}