You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/03/20 15:22:50 UTC

[36/51] [abbrv] [partial] incubator-taverna-workbench git commit: taverna-workbench-* -> taverna-*

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent b/taverna-edits-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
new file mode 100644
index 0000000..6938308
--- /dev/null
+++ b/taverna-edits-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
@@ -0,0 +1,6 @@
+net.sf.taverna.t2.workbench.edits.impl.menu.UndoMenuSection
+net.sf.taverna.t2.workbench.edits.impl.menu.UndoMenuAction
+net.sf.taverna.t2.workbench.edits.impl.menu.RedoMenuAction
+net.sf.taverna.t2.workbench.edits.impl.toolbar.EditToolbarSection
+net.sf.taverna.t2.workbench.edits.impl.toolbar.UndoToolbarAction
+net.sf.taverna.t2.workbench.edits.impl.toolbar.RedoToolbarAction

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.edits.EditManager
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.edits.EditManager b/taverna-edits-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.edits.EditManager
new file mode 100644
index 0000000..92ee088
--- /dev/null
+++ b/taverna-edits-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.edits.EditManager
@@ -0,0 +1 @@
+net.sf.taverna.t2.workbench.edits.impl.EditManagerImpl

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/resources/META-INF/spring/edits-impl-context-osgi.xml
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/resources/META-INF/spring/edits-impl-context-osgi.xml b/taverna-edits-impl/src/main/resources/META-INF/spring/edits-impl-context-osgi.xml
new file mode 100644
index 0000000..8eb7041
--- /dev/null
+++ b/taverna-edits-impl/src/main/resources/META-INF/spring/edits-impl-context-osgi.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/osgi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd
+                      http://www.springframework.org/schema/osgi
+                      http://www.springframework.org/schema/osgi/spring-osgi.xsd">
+
+	<service ref="UndoMenuSection" auto-export="interfaces" />
+	<service ref="UndoMenuAction" auto-export="interfaces" />
+	<service ref="RedoMenuAction" auto-export="interfaces" />
+	<service ref="EditToolbarSection" auto-export="interfaces" />
+	<service ref="UndoToolbarAction" auto-export="interfaces" />
+	<service ref="RedoToolbarAction" auto-export="interfaces" />
+
+	<service ref="EditManagerImpl" interface="net.sf.taverna.t2.workbench.edits.EditManager" />
+
+	<reference id="selectionManager" interface="net.sf.taverna.t2.workbench.selection.SelectionManager" cardinality="0..1" />
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/resources/META-INF/spring/edits-impl-context.xml
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/resources/META-INF/spring/edits-impl-context.xml b/taverna-edits-impl/src/main/resources/META-INF/spring/edits-impl-context.xml
new file mode 100644
index 0000000..33f0b7b
--- /dev/null
+++ b/taverna-edits-impl/src/main/resources/META-INF/spring/edits-impl-context.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<bean id="UndoMenuSection" class="net.sf.taverna.t2.workbench.edits.impl.menu.UndoMenuSection" />
+	<bean id="UndoMenuAction" class="net.sf.taverna.t2.workbench.edits.impl.menu.UndoMenuAction">
+		<constructor-arg name="editManager">
+			<ref local="EditManagerImpl" />
+		</constructor-arg>
+		<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="RedoMenuAction" class="net.sf.taverna.t2.workbench.edits.impl.menu.RedoMenuAction">
+		<constructor-arg name="editManager">
+			<ref local="EditManagerImpl" />
+		</constructor-arg>
+		<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="EditToolbarSection" class="net.sf.taverna.t2.workbench.edits.impl.toolbar.EditToolbarSection" />
+	<bean id="UndoToolbarAction" class="net.sf.taverna.t2.workbench.edits.impl.toolbar.UndoToolbarAction">
+		<constructor-arg>
+			<ref local="UndoMenuAction" />
+		</constructor-arg>
+	</bean>
+	<bean id="RedoToolbarAction" class="net.sf.taverna.t2.workbench.edits.impl.toolbar.RedoToolbarAction">
+		<constructor-arg>
+			<ref local="RedoMenuAction" />
+		</constructor-arg>
+	</bean>
+
+	<bean id="EditManagerImpl" class="net.sf.taverna.t2.workbench.edits.impl.EditManagerImpl" />
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/test/java/net/sf/taverna/t2/workbench/edits/impl/TestEditManagerImpl.java
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/test/java/net/sf/taverna/t2/workbench/edits/impl/TestEditManagerImpl.java b/taverna-edits-impl/src/test/java/net/sf/taverna/t2/workbench/edits/impl/TestEditManagerImpl.java
new file mode 100644
index 0000000..9123671
--- /dev/null
+++ b/taverna-edits-impl/src/test/java/net/sf/taverna/t2/workbench/edits/impl/TestEditManagerImpl.java
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * 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.edits.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.workbench.edits.Edit;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.edits.EditManager.DataFlowRedoEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.DataFlowUndoEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.DataflowEditEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.EditManagerEvent;
+import net.sf.taverna.t2.workflow.edits.AddProcessorEdit;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.core.Workflow;
+
+public class TestEditManagerImpl {
+
+	private Workflow dataflow;
+
+	private EditManagerObserver editManagerObserver = new EditManagerObserver();
+
+	private Processor processor;
+
+	@Test
+	public void addProcessor() throws Exception {
+		EditManager editManager = new EditManagerImpl();
+		editManager.addObserver(editManagerObserver);
+
+		Edit<Workflow> edit = new AddProcessorEdit(dataflow, processor);
+		assertFalse("Edit was already applied", edit.isApplied());
+		assertTrue("Did already add processor", dataflow.getProcessors()
+				.isEmpty());
+
+		editManager.doDataflowEdit(dataflow.getParent(), edit);
+		assertTrue("Edit was not applied", edit.isApplied());
+		assertEquals("Did not add processor", processor, dataflow.getProcessors().first());
+
+		// Should have received the edit event
+		assertEquals("Incorrect number of events", 1,
+				editManagerObserver.events.size());
+		EditManagerEvent event = editManagerObserver.events.get(0);
+		assertTrue("Event was not a DataflowEditEvent",
+				event instanceof DataflowEditEvent);
+		DataflowEditEvent dataEditEvent = (DataflowEditEvent) event;
+		assertEquals("Event did not have correct workflow", dataflow,
+				dataEditEvent.getDataFlow().getWorkflows().first());
+		assertEquals("Event did not have correct edit", edit, dataEditEvent
+				.getEdit());
+
+	}
+
+	@Test
+	public void undoAddProcessor() throws Exception {
+		EditManager editManager = new EditManagerImpl();
+		editManager.addObserver(editManagerObserver);
+
+		Edit<Workflow> edit = new AddProcessorEdit(dataflow, processor);
+		editManager.doDataflowEdit(dataflow.getParent(), edit);
+
+		assertFalse("Did not add processor", dataflow.getProcessors().isEmpty());
+		editManager.undoDataflowEdit(dataflow.getParent());
+		assertTrue("Did not undo add processor", dataflow.getProcessors()
+				.isEmpty());
+
+		// Should have received the undo event
+		assertEquals("Incorrect number of events", 2,
+				editManagerObserver.events.size());
+		EditManagerEvent event = editManagerObserver.events.get(1);
+		assertTrue("Event was not a DataflowEditEvent",
+				event instanceof DataFlowUndoEvent);
+		DataFlowUndoEvent dataEditEvent = (DataFlowUndoEvent) event;
+		assertEquals("Event did not have correct workflow", dataflow,
+				dataEditEvent.getDataFlow().getWorkflows().first());
+		assertEquals("Event did not have correct edit", edit, dataEditEvent
+				.getEdit());
+		assertFalse("Edit was still applied", edit.isApplied());
+	}
+
+	@Test
+	public void multipleUndoesRedoes() throws Exception {
+		EditManager editManager = new EditManagerImpl();
+		editManager.addObserver(editManagerObserver);
+
+		Workflow dataflowA = createDataflow();
+		Workflow dataflowB = createDataflow();
+		Workflow dataflowC = createDataflow();
+
+		Processor processorA1 = createProcessor();
+		Processor processorA2 = createProcessor();
+		Processor processorA3 = createProcessor();
+		Processor processorB1 = createProcessor();
+		Processor processorC1 = createProcessor();
+
+		Edit<Workflow> edit = new AddProcessorEdit(dataflowA, processorA1);
+		editManager.doDataflowEdit(dataflowA.getParent(), edit);
+
+		edit = new AddProcessorEdit(dataflowB, processorB1);
+		editManager.doDataflowEdit(dataflowB.getParent(), edit);
+
+		edit = new AddProcessorEdit(dataflowA, processorA2);
+		editManager.doDataflowEdit(dataflowA.getParent(), edit);
+
+		edit = new AddProcessorEdit(dataflowC, processorC1);
+		editManager.doDataflowEdit(dataflowC.getParent(), edit);
+
+		edit = new AddProcessorEdit(dataflowA, processorA3);
+		editManager.doDataflowEdit(dataflowA.getParent(), edit);
+
+
+
+		assertFalse("Did not add processors", dataflowA.getProcessors().isEmpty());
+		assertEquals(3, dataflowA.getProcessors().size());
+		editManager.undoDataflowEdit(dataflowA.getParent());
+		assertEquals(2, dataflowA.getProcessors().size());
+		editManager.undoDataflowEdit(dataflowA.getParent());
+		assertEquals(1, dataflowA.getProcessors().size());
+		editManager.undoDataflowEdit(dataflowA.getParent());
+		assertEquals(0, dataflowA.getProcessors().size());
+
+		assertEquals(1, dataflowB.getProcessors().size());
+		assertEquals(1, dataflowC.getProcessors().size());
+
+		assertTrue(editManager.canUndoDataflowEdit(dataflowC.getParent()));
+		editManager.undoDataflowEdit(dataflowC.getParent());
+		assertFalse(editManager.canUndoDataflowEdit(dataflowC.getParent()));
+		editManager.undoDataflowEdit(dataflowC.getParent()); // extra one
+		assertFalse(editManager.canUndoDataflowEdit(dataflowC.getParent()));
+
+
+		assertEquals(1, dataflowB.getProcessors().size());
+		assertEquals(0, dataflowC.getProcessors().size());
+
+		editManager.undoDataflowEdit(dataflowB.getParent());
+		assertEquals(0, dataflowA.getProcessors().size());
+		assertEquals(0, dataflowB.getProcessors().size());
+		assertEquals(0, dataflowC.getProcessors().size());
+
+		editManager.redoDataflowEdit(dataflowA.getParent());
+		assertEquals(1, dataflowA.getProcessors().size());
+
+		editManager.redoDataflowEdit(dataflowA.getParent());
+		assertEquals(2, dataflowA.getProcessors().size());
+
+		editManager.redoDataflowEdit(dataflowA.getParent());
+		assertEquals(3, dataflowA.getProcessors().size());
+
+		// does not affect it
+		editManager.redoDataflowEdit(dataflowA.getParent());
+		assertEquals(3, dataflowA.getProcessors().size());
+		assertEquals(0, dataflowB.getProcessors().size());
+		assertEquals(0, dataflowC.getProcessors().size());
+	}
+
+	@Test
+	public void emptyUndoDoesNotFail() throws Exception {
+		EditManager editManager = new EditManagerImpl();
+		editManager.addObserver(editManagerObserver);
+		editManager.undoDataflowEdit(dataflow.getParent());
+	}
+
+	@Test
+	public void extraUndoesDoesNotFail() throws Exception {
+		EditManager editManager = new EditManagerImpl();
+		editManager.addObserver(editManagerObserver);
+
+		Edit<Workflow> edit = new AddProcessorEdit(dataflow, processor);
+		editManager.doDataflowEdit(dataflow.getParent(), edit);
+
+		assertFalse("Did not add processor", dataflow.getProcessors().isEmpty());
+		editManager.undoDataflowEdit(dataflow.getParent());
+		assertTrue("Did not undo add processor", dataflow.getProcessors()
+				.isEmpty());
+		editManager.undoDataflowEdit(dataflow.getParent());
+	}
+
+	@Before
+	public void makeDataflow() {
+		dataflow = createDataflow();
+	}
+
+	protected Workflow createDataflow() {
+		WorkflowBundle workflowBundle = new WorkflowBundle();
+		Workflow workflow = new Workflow();
+		workflow.setParent(workflowBundle);
+		return workflow;
+	}
+
+	protected Processor createProcessor() {
+		Processor processor = new Processor();
+		processor.setName("proc-" + UUID.randomUUID());
+		return processor;
+	}
+
+	@Before
+	public void makeProcessor() {
+		processor = createProcessor();
+	}
+
+	private class EditManagerObserver implements Observer<EditManagerEvent> {
+
+		public List<EditManagerEvent> events = new ArrayList<>();
+
+		@Override
+		public void notify(Observable<EditManagerEvent> sender,
+				EditManagerEvent message) throws Exception {
+			events.add(message);
+			if (message instanceof DataflowEditEvent) {
+				DataflowEditEvent dataflowEdit = (DataflowEditEvent) message;
+				assertTrue("Edit was not applied on edit event", dataflowEdit
+						.getEdit().isApplied());
+			} else if (message instanceof DataFlowUndoEvent) {
+				DataFlowUndoEvent dataflowUndo = (DataFlowUndoEvent) message;
+				assertFalse("Edit was applied on undo event", dataflowUndo
+						.getEdit().isApplied());
+			} else if (message instanceof DataFlowRedoEvent) {
+				DataFlowRedoEvent dataflowEdit = (DataFlowRedoEvent) message;
+				assertTrue("Edit was not applied on edit event", dataflowEdit
+						.getEdit().isApplied());
+			} else {
+				fail("Unknown event: " + message);
+			}
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-file-api/pom.xml b/taverna-file-api/pom.xml
new file mode 100644
index 0000000..a70ca9f
--- /dev/null
+++ b/taverna-file-api/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.taverna.workbench</groupId>
+		<artifactId>taverna-workbench</artifactId>
+		<version>3.1.0-incubating-SNAPSHOT</version>
+	</parent>
+	<artifactId>taverna-file-api</artifactId>
+	<packaging>bundle</packaging>
+	<name>Apache Taverna File opening API</name>
+	<description>
+		API for doing file (ie. workflow) open/save in the workbench.
+	</description>
+
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId.version}</groupId>
+			<artifactId>taverna-ui</artifactId>
+			<version>${project.version.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.engine</groupId>
+			<artifactId>taverna-observer</artifactId>
+			<version>${taverna.engine.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.language</groupId>
+			<artifactId>taverna-scufl2-api</artifactId>
+		</dependency>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/AbstractDataflowPersistenceHandler.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/AbstractDataflowPersistenceHandler.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/AbstractDataflowPersistenceHandler.java
new file mode 100644
index 0000000..8dc34e8
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/AbstractDataflowPersistenceHandler.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.Collections;
+import java.util.List;
+
+import net.sf.taverna.t2.workbench.file.exceptions.OpenException;
+import net.sf.taverna.t2.workbench.file.exceptions.SaveException;
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+public abstract class AbstractDataflowPersistenceHandler implements
+		DataflowPersistenceHandler {
+	@Override
+	public List<FileType> getOpenFileTypes() {
+		return Collections.emptyList();
+	}
+
+	@Override
+	public List<FileType> getSaveFileTypes() {
+		return Collections.emptyList();
+	}
+
+	@Override
+	public List<Class<?>> getOpenSourceTypes() {
+		return Collections.emptyList();
+	}
+
+	@Override
+	public List<Class<?>> getSaveDestinationTypes() {
+		return Collections.emptyList();
+	}
+
+	@Override
+	public DataflowInfo openDataflow(FileType fileType, Object source)
+			throws OpenException {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public DataflowInfo saveDataflow(WorkflowBundle workflowBundle, FileType fileType,
+			Object destination) throws SaveException {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public boolean wouldOverwriteDataflow(WorkflowBundle workflowBundle, FileType fileType,
+			Object destination, DataflowInfo lastDataflowInfo) {
+		throw new UnsupportedOperationException();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/DataflowInfo.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/DataflowInfo.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/DataflowInfo.java
new file mode 100644
index 0000000..c5eaa26
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/DataflowInfo.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.Date;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * Information about a WorkflowBundle that has been opened by the
+ * {@link FileManager}.
+ * <p>
+ * This class, or a subclass of it, is used by
+ * {@link DataflowPersistenceHandler}s to keep information about where a
+ * {@link WorkflowBundle} came from or where it was saved to.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class DataflowInfo {
+	private final FileType fileType;
+	private final WorkflowBundle worflowBundle;
+	private final Date lastModified;
+	private final Object canonicalSource;
+
+	public DataflowInfo(FileType fileType, Object canonicalSource,
+			WorkflowBundle worflowBundle, Date lastModified) {
+		this.fileType = fileType;
+		this.canonicalSource = canonicalSource;
+		this.worflowBundle = worflowBundle;
+		this.lastModified = lastModified;
+	}
+
+	public DataflowInfo(FileType fileType, Object canonicalSource,
+			WorkflowBundle worflowBundle) {
+		this(fileType, canonicalSource, worflowBundle, null);
+	}
+
+	/**
+	 * Return the canonical source of where the WorkflowBundle was opened from
+	 * or saved to.
+	 * <p>
+	 * This is not necessarily the source provided to
+	 * {@link FileManager#openDataflow(FileType, Object)} or
+	 * {@link FileManager#saveDataflow(WorkflowBundle, FileType, Object, boolean)}
+	 * , but it's canonical version.
+	 * <p>
+	 * For instance, if a WorkflowBundle was opened from a
+	 * File("relative/something.wfbundle) this canonical source would resolve
+	 * the relative path.
+	 * 
+	 * @return
+	 */
+	public Object getCanonicalSource() {
+		return canonicalSource;
+	}
+
+	/**
+	 * Return the WorkflowBundle that is open.
+	 * 
+	 * @return The open WorkflowBundle
+	 */
+	public WorkflowBundle getDataflow() {
+		return worflowBundle;
+	}
+
+	/**
+	 * Get the last modified {@link Date} of the source at the time when it was
+	 * opened/saved.
+	 * <p>
+	 * It is important that this value is checked on creation time, and not on
+	 * demand.
+	 * 
+	 * @return The {@link Date} of the source/destination's last modified
+	 *         timestamp, or <code>null</code> if unknown.
+	 */
+	public Date getLastModified() {
+		return lastModified;
+	}
+
+	/**
+	 * The {@link FileType} of this {@link WorkflowBundle} serialisation used
+	 * for opening/saving.
+	 * 
+	 * @return The {@link FileType}, for instance
+	 *         {@link net.sf.taverna.t2.workbench.file.impl.WorkflowBundleFileType}
+	 */
+	public FileType getFileType() {
+		return fileType;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/DataflowPersistenceHandler.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/DataflowPersistenceHandler.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/DataflowPersistenceHandler.java
new file mode 100644
index 0000000..f8d2ddb
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/DataflowPersistenceHandler.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Collection;
+
+import net.sf.taverna.t2.workbench.file.exceptions.OpenException;
+import net.sf.taverna.t2.workbench.file.exceptions.SaveException;
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * A handler for opening or saving {@link WorkflowBundle} from the
+ * {@link FileManager}.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public interface DataflowPersistenceHandler {
+	/**
+	 * A collection of supported file types for
+	 * {@link #openDataflow(FileType, Object)}, or an empty collection if
+	 * opening is not supported by this handler.
+	 * 
+	 * @return A collection of supported {@link FileType}s for opening.
+	 */
+	Collection<FileType> getOpenFileTypes();
+
+	/**
+	 * A collection of supported source classes for
+	 * {@link #openDataflow(FileType, Object)}, or an empty collection if
+	 * opening is not supported by this handler.
+	 * <p>
+	 * For example, a handler that supports sources opened from a {@link File}
+	 * and {@link URL} could return
+	 * <code>Arrays.asList(File.class, URL.class)</code>
+	 * 
+	 * @return A collection of supported {@link Class}es of the open source
+	 *         types.
+	 */
+	Collection<Class<?>> getOpenSourceTypes();
+
+	/**
+	 * A collection of supported destination classes for
+	 * {@link #saveDataflow(Dataflow, FileType, Object)}, or an empty collection
+	 * if saving is not supported by this handler.
+	 * <p>
+	 * For example, a handler that supports saving to destinations that are
+	 * instances of a {@link File} could return
+	 * <code>Arrays.asList(File.class)</code>
+	 * 
+	 * @return A collection of supported {{@link Class}es of the save
+	 *         destination types.
+	 */
+	Collection<Class<?>> getSaveDestinationTypes();
+
+	/**
+	 * A collection of supported file types for
+	 * {@link #saveDataflow(WorkflowBundle, FileType, Object)}, or an empty
+	 * collection if saving is not supported by this handler.
+	 * 
+	 * @return A collection of supported {@link FileType}s for saving.
+	 */
+	Collection<FileType> getSaveFileTypes();
+
+	/**
+	 * Open a dataflow from a source containing a dataflow of the given
+	 * {@link FileType}.
+	 * <p>
+	 * The {@link FileType} will be equal to one of the types from
+	 * {@link #getOpenFileTypes()}, and the source class will be one that is
+	 * assignable to one of the classes from {@link #getOpenSourceTypes()}.
+	 * 
+	 * @param fileType
+	 *            {@link FileType} determining which serialisation method has
+	 *            been used
+	 * @param source
+	 *            Source for reading the WorkflowBundle
+	 * @return {@link DataflowInfo} describing the opened WorkflowBundle,
+	 *         including the WorkflowBundle itself
+	 * @throws OpenException
+	 *             If the WorkflowBundle could not be read, parsed or opened for
+	 *             any reason.
+	 */
+	DataflowInfo openDataflow(FileType fileType, Object source)
+			throws OpenException;
+
+	/**
+	 * Save a WorkflowBundle to a destination of the given {@link FileType}.
+	 * <p>
+	 * The {@link FileType} will be equal to one of the types from
+	 * {@link #getSaveFileTypes()}, and the destination class will be one that
+	 * is assignable to one of the classes from
+	 * {@link #getSaveDestinationTypes()}.
+	 * 
+	 * @param dataflow
+	 *            {@link WorkflowBundle} to be saved
+	 * @param fileType
+	 *            {@link FileType} determining which serialisation method to use
+	 * @param destination
+	 *            Destination for writing the WorkflowBundle
+	 * @return {@link DataflowInfo} describing the saved WorkflowBundle,
+	 *         including the WorkflowBundle itself
+	 * @throws OpenException
+	 *             If the WorkflowBundle could not be read, parsed or opened for
+	 *             any reason.
+	 */
+	DataflowInfo saveDataflow(WorkflowBundle dataflow, FileType fileType,
+			Object destination) throws SaveException;
+
+	/**
+	 * Return <code>true</code> if a call to
+	 * {@link #saveDataflow(WorkflowBundle, FileType, Object)} would overwrite
+	 * the destination, and the destination is different from last
+	 * {@link #openDataflow(FileType, Object)} or
+	 * {@link #saveDataflow(WorkflowBundle, FileType, Object)} of the given
+	 * dataflow.
+	 * 
+	 * @param dataflow
+	 *            {@link WorkflowBundle} that is to be saved
+	 * @param fileType
+	 *            {@link FileType} for saving WorkflowBundle
+	 * @param destination
+	 *            destination for writing WorkflowBundle
+	 * @param lastDataflowInfo
+	 *            last provided {@link DataflowInfo} returned by
+	 *            {@link #openDataflow(FileType, Object)} or
+	 *            {@link #saveDataflow(WorkflowBundle, FileType, Object)}. (but
+	 *            not necessarily from this handler)
+	 * @return <code>true</code> if the save would overwrite
+	 */
+	boolean wouldOverwriteDataflow(WorkflowBundle dataflow, FileType fileType,
+			Object destination, DataflowInfo lastDataflowInfo);
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/FileManager.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/FileManager.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/FileManager.java
new file mode 100644
index 0000000..f449bb5
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/FileManager.java
@@ -0,0 +1,573 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import javax.swing.filechooser.FileFilter;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.workbench.file.events.ClosedDataflowEvent;
+import net.sf.taverna.t2.workbench.file.events.FileManagerEvent;
+import net.sf.taverna.t2.workbench.file.events.OpenedDataflowEvent;
+import net.sf.taverna.t2.workbench.file.events.SavedDataflowEvent;
+import net.sf.taverna.t2.workbench.file.exceptions.OpenException;
+import net.sf.taverna.t2.workbench.file.exceptions.OverwriteException;
+import net.sf.taverna.t2.workbench.file.exceptions.SaveException;
+import net.sf.taverna.t2.workbench.file.exceptions.UnsavedException;
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * Manager of open files (WorkflowBundleBundles) in the workbench.
+ * <p>
+ * A {@link WorkflowBundle} can be opened for the workbench using
+ * {@link #openDataflow(FileType, Object)} or {@link #openDataflow(WorkflowBundle)}.
+ * {@link Observer}s of the FileManager gets notified with an
+ * {@link OpenedDataflowEvent}. The opened workflow is also
+ * {@link #setCurrentDataflow(WorkflowBundle) made the current dataflow}, available
+ * through {@link #getCurrentDataflow()} or by observing the
+ * {@link net.sf.taverna.t2.lang.ui.ModelMap} for the model name
+ * {@link net.sf.taverna.t2.workbench.ModelMapConstants#CURRENT_DATAFLOW}.
+ * <p>
+ * A dataflow can be saved using
+ * {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)}. Observers will be
+ * presented a {@link SavedDataflowEvent}.
+ * <p>
+ * If a dataflow was previously opened from a saveable destination or previously
+ * saved using {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)},
+ * {@link #saveDataflow(WorkflowBundle, boolean)} can be used to resave to that
+ * destination.
+ * <p>
+ * You can get the last opened/saved source and type using
+ * {@link #getDataflowSource(WorkflowBundle)} and {@link #getDataflowType(WorkflowBundle)}.
+ * <p>
+ * If the save methods are used with failOnOverwrite=true, an
+ * {@link OverwriteException} will be thrown if the destination file already
+ * exists and was not last written by a previous save on that dataflow. (This is
+ * typically checked using timestamps on the file).
+ * <p>
+ * A dataflow can be closed using {@link #closeDataflow(WorkflowBundle, boolean)}. A
+ * closed dataflow is no longer monitored for changes and can no longer be used
+ * with the other operations, except {@link #openDataflow(WorkflowBundle)}.
+ * <p>
+ * If a dataflow has been changed using the {@link EditManager},
+ * {@link #isDataflowChanged(WorkflowBundle)} will return true until the next save. If
+ * the close methods are used with failOnUnsaved=true, an
+ * {@link UnsavedException} will be thrown if the dataflow has been changed.
+ * <p>
+ * The implementation of this interface is an OSGi Service.
+ *
+ * @author Stian Soiland-Reyes
+ */
+public interface FileManager extends Observable<FileManagerEvent> {
+	/**
+	 * True if {@link #saveDataflow(WorkflowBundle, boolean)} can save the
+	 * workflow, i.e., that there exists an SPI implementation of
+	 * {@link DataflowPersistenceHandler} that can save to
+	 * {@link #getDataflowSource(WorkflowBundle)} using
+	 * {@link #getDataflowType(WorkflowBundle)}.
+	 * 
+	 * @see #saveDataflow(WorkflowBundle, boolean)
+	 * @param dataflow
+	 *            The dataflow to check
+	 * @return <code>true</code> if the given dataflow can be saved without
+	 *         providing a destination and filetype
+	 */
+	boolean canSaveWithoutDestination(WorkflowBundle dataflow);
+
+	/**
+	 * Close the specified dataflow.
+	 * <p>
+	 * A closed dataflow can no longer be used with the save methods, and will
+	 * disappear from the UI's list of open dataflows.
+	 * <p>
+	 * If no more dataflows would be open after the close, a new empty dataflow
+	 * is opened as through {@link #newDataflow()}.
+	 * <p>
+	 * If the failOnUnsaved parameters is <code>true</code>, and
+	 * {@link #isDataflowChanged(WorkflowBundle)} is <code>true</code>, an
+	 * {@link UnsavedException} will be thrown, typically because the workflow
+	 * has been changed using the {@link EditManager} since the last change.
+	 * <p>
+	 * Listeners registered using {@link Observable#addObserver(Observer)} will
+	 * be notified with an {@link ClosedDataflowEvent}.
+	 *
+	 * @param dataflow
+	 *            {@link WorkflowBundle} to close
+	 * @param failOnUnsaved
+	 *            If <code>true</code>, fail on unsaved changes
+	 * @throws UnsavedException
+	 *             If failOnUnsaved was <code>true</code> and there has been
+	 *             changes to the dataflow since the last save
+	 */
+	boolean closeDataflow(WorkflowBundle dataflow, boolean failOnUnsaved)
+			throws UnsavedException;
+
+	/**
+	 * Get the current dataflow.
+	 * <p>
+	 * The current workflow is typically the one currently showed on the screen,
+	 * and is also in {@link #getOpenDataflows()}.
+	 * <p>
+	 * The current dataflow is set through {@link #setCurrentDataflow(WorkflowBundle)}
+	 * or the {@link net.sf.taverna.t2.lang.ui.ModelMap} using the key
+	 * {@link net.sf.taverna.t2.workbench.ModelMapConstants#CURRENT_DATAFLOW}.
+	 *
+	 * @return The current dataflow, or <code>null</code> if no dataflow is
+	 *         current
+	 */
+	WorkflowBundle getCurrentDataflow();
+
+	/**
+	 * Get the dataflow that was opened from or last saved to the given source.
+	 *
+	 * @param source
+	 *            The source as opened with or saved to
+	 *            {@link #openDataflow(FileType, Object)}
+	 * @return The opened {@link WorkflowBundle} or <code>null</code> if no matching
+	 *         dataflow found.
+	 */
+	WorkflowBundle getDataflowBySource(Object source);
+
+	/**
+	 * Get a name to represent this dataflow.
+	 * <p>
+	 * The name will primarily be deduced from the source of where the workflow
+	 * is opened from, unless {@link Object#toString()} is not overridden (for
+	 * instance opened from an InputStream) or if the source is unknown, in
+	 * which case the dataflow's internal name {@link WorkflowBundle#getName()}
+	 * is returned.
+	 * <p>
+	 * The returned name can be used in listings like the WorkflowBundles menu, but is
+	 * not guaranteed to be unique. (For instance a workflow could be opened
+	 * twice from the same source).
+	 *
+	 * @param dataflow
+	 *            WorkflowBundle to get the name for
+	 * @return The deduced workflow name
+	 */
+	String getDataflowName(WorkflowBundle dataflow);
+
+	/**
+	 * Returns the default name to use when creating new workflows.
+	 *
+	 * @return the default name to use when creating new workflows
+	 */
+	String getDefaultWorkflowName();
+
+	/**
+	 * Get the last opened/saved source/destination for the given dataflow.
+	 * <p>
+	 * The source is the last source used with
+	 * {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)} for the given
+	 * dataflow, or {@link #openDataflow(FileType, Object)} if it has not yet
+	 * been saved.
+	 * <p>
+	 * If the given dataflow's last opened/saved location was unknown (opened
+	 * with {@link #newDataflow()} or {@link #openDataflow(WorkflowBundle)}), return
+	 * <code>null</code>.
+	 *
+	 * @param dataflow
+	 *            {@link WorkflowBundle} which file is to be returned
+	 * @return The last opened/saved source for the given dataflow, or
+	 *         <code>null</code> if unknown.
+	 */
+	Object getDataflowSource(WorkflowBundle dataflow);
+
+	/**
+	 * Get the last opened/saved source/destination FileType for the given
+	 * dataflow.
+	 * <p>
+	 * The type is the last {@link FileType} used with
+	 * {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)} for the given
+	 * dataflow, or {@link #openDataflow(FileType, Object)} if it has not yet
+	 * been saved.
+	 * <p>
+	 * If the given dataflow's last opened/saved file type was unknown (opened
+	 * with {@link #newDataflow()} or {@link #openDataflow(WorkflowBundle)}), return
+	 * <code>null</code>.
+	 *
+	 * @param dataflow
+	 *            {@link WorkflowBundle} which file is to be returned
+	 * @return The last opened/saved {@link FileType} for the given dataflow, or
+	 *         <code>null</code> if unknown.
+	 */
+	FileType getDataflowType(WorkflowBundle dataflow);
+
+	/**
+	 * Get the list of currently open dataflows. This list of dataflows are
+	 * typically displayed in the UI in the "WorkflowBundles" menu to allow switching
+	 * the {@link #getCurrentDataflow() current dataflow}.
+	 *
+	 * @return A copy of the {@link List} of open {@link WorkflowBundle}s
+	 */
+	List<WorkflowBundle> getOpenDataflows();
+
+	/**
+	 * Get a list of {@link FileFilter}s for supported {@link FileType}s that
+	 * can be opened with any source class.
+	 *
+	 * @return A {@link List} of {@link FileFilter}s supported by
+	 *         {@link #openDataflow(FileType, Object)}
+	 */
+	List<FileFilter> getOpenFileFilters();
+
+	/**
+	 * Get a list of {@link FileFilter}s for supported {@link FileType}s that
+	 * can be opened with given source class.
+	 *
+	 * @param sourceClass
+	 *            Source class that can be opened from
+	 * @return A {@link List} of {@link FileFilter}s supported by
+	 *         {@link #openDataflow(FileType, Object)}
+	 */
+	List<FileFilter> getOpenFileFilters(Class<?> sourceClass);
+
+	/**
+	 * Get a list of {@link FileFilter}s for supported {@link FileType}s that
+	 * can be saved to any destination class.
+	 *
+	 * @return A {@link List} of {@link FileFilter}s supported by
+	 *         {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)}
+	 */
+	List<FileFilter> getSaveFileFilters();
+
+	/**
+	 * Get a list of {@link FileFilter}s for supported {@link FileType}s that
+	 * can be saved to the given destination class.
+	 *
+	 * @param destinationClass
+	 *            Destination class that can be saved to
+	 * @return A {@link List} of {@link FileFilter}s supported by
+	 *         {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)}
+	 */
+	List<FileFilter> getSaveFileFilters(Class<?> destinationClass);
+
+	/**
+	 * Return <code>true</code> if the dataflow has been changed (through the
+	 * {@link EditManager} or {@link #setDataflowChanged(WorkflowBundle, boolean)})
+	 * since last save.
+	 *
+	 * @param dataflow
+	 *            WorkflowBundle which changed status is to be checked
+	 * @return <code>true</code> if the dataflow has been changed since last
+	 *         save.
+	 */
+	boolean isDataflowChanged(WorkflowBundle dataflow);
+
+	/**
+	 * True if the given dataflow has been opened and is in
+	 * {@link #getOpenDataflows()}.
+	 *
+	 * @param dataflow
+	 *            Dataflow to check
+	 * @return <code>true</code> if dataflow is open
+	 */
+	boolean isDataflowOpen(WorkflowBundle dataflow);
+
+	/**
+	 * Create and open a new, blank dataflow. The dataflow will not initially be
+	 * marked as changed.
+	 * <p>
+	 * Listeners registered using {@link Observable#addObserver(Observer)} will
+	 * be notified with an {@link OpenedDataflowEvent}.
+	 * <p>
+	 * Note, if the dataflow is later changed, it will not be possible to save
+	 * it to any original location using
+	 * {@link #saveDataflow(WorkflowBundle, boolean)}, only
+	 * {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)}.
+	 *
+	 * @return The newly opened blank {@link WorkflowBundle}
+	 */
+	WorkflowBundle newDataflow();
+
+	/**
+	 * Open a {@link WorkflowBundle} instance that has been created outside the
+	 * {@link FileManager}. The dataflow will not initially be marked as
+	 * changed.
+	 * <p>
+	 * Listeners registered using {@link Observable#addObserver(Observer)} will
+	 * be notified with an {@link OpenedDataflowEvent}.
+	 * <p>
+	 * Note, if the dataflow is later changed, it will not be possible to save
+	 * it to its original location using
+	 * {@link #saveDataflow(WorkflowBundle, boolean)}, only
+	 * {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)}.
+	 * <p>
+	 * Instead of using this option it is recommended to create your own
+	 * {@link FileType} and/or source type and a
+	 * {@link DataflowPersistenceHandler} to implement save and/or reopen
+	 * (revert).
+	 * <p>
+	 * If there is only one workflow open before opening this workflow, and it
+	 * is an unchanged blank workflow, the blank workflow will be closed.
+	 *
+	 * @param dataflow
+	 *            {@link WorkflowBundle} instance that is to be added as an open
+	 *            dataflow
+	 */
+	void openDataflow(WorkflowBundle dataflow);
+
+	/**
+	 * Open a dataflow from a source. The dataflow will not initially be marked
+	 * as changed, and will be set as the new current workflow.
+	 * <p>
+	 * The file manager will find implementations of the SPI
+	 * {@link DataflowPersistenceHandler} to perform the opening for the given file
+	 * type and destination class.
+	 * <p>
+	 * Listeners registered using {@link Observable#addObserver(Observer)} will
+	 * be notified with an {@link OpenedDataflowEvent}.
+	 * <p>
+	 * If there is only one workflow open before opening this workflow, and it
+	 * is an unchanged blank workflow, the blank workflow will be closed.
+	 *
+	 * @param fileType
+	 *            The filetype, for instance
+	 *            {@link net.sf.taverna.t2.workbench.file.impl.T2FlowFileType}.
+	 *            The file type must be supported by an implementation of the
+	 *            SPI DataflowPersistenceHandler.
+	 * @param source
+	 *            The source, for instance a {@link File} or {@link URL}. The
+	 *            source type must be supported by an implementation of
+	 *            DataflowPersistenceHandler.
+	 * @return The opened {@link WorkflowBundle}.
+	 * @throws OpenException
+	 *             If there was no matching DataflowPersistenceHandler found or
+	 *             the source could not be opened for any other reason, such as
+	 *             IO errors or syntax errors.
+	 */
+	WorkflowBundle openDataflow(FileType fileType, Object source)
+			throws OpenException;
+
+	/**
+	 * Open a dataflow from a source silently. The dataflow will not be listed
+	 * as open, and will not be made the current workflow.
+	 * <p>
+	 * The file manager will find implementations of the SPI
+	 * {@link DataflowPersistenceHandler} to perform the opening for the given file
+	 * type and destination class.
+	 * <p>
+	 * Listeners will <strong>not</strong> be notified.
+	 *
+	 * @param fileType
+	 *            The filetype, for instance
+	 *            {@link net.sf.taverna.t2.workbench.file.impl.T2FlowFileType}.
+	 *            The file type must be supported by an implementation of the
+	 *            SPI DataflowPersistenceHandler.
+	 * @param source
+	 *            The source, for instance a {@link File} or {@link URL}. The
+	 *            source type must be supported by an implementation of
+	 *            DataflowPersistenceHandler.
+	 * @return The {@link DataflowInfo} describing the opened dataflow.
+	 * @throws OpenException
+	 *             If there was no matching DataflowPersistenceHandler found or
+	 *             the source could not be opened for any other reason, such as
+	 *             IO errors or syntax errors.
+	 */
+	DataflowInfo openDataflowSilently(FileType fileType, Object source)
+			throws OpenException;
+
+	/**
+	 * Save the dataflow to the last saved destination and FileType from
+	 * {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)} or the last
+	 * opened source and FileType from {@link #openDataflow(FileType, Object)}.
+	 * <p>
+	 * Listeners registered using {@link Observable#addObserver(Observer)} will
+	 * be notified with an {@link SavedDataflowEvent}.
+	 *
+	 * @param dataflow
+	 *            Dataflow to save. Dataflow must have been opened with
+	 *            {@link #openDataflow(FileType, Object)} or saved using
+	 *            {@link #saveDataflow(WorkflowBundle, FileType, Object, boolean)}.
+	 * @param failOnOverwrite
+	 *            If <code>true</code>, an {@link OverwriteException} is thrown
+	 *            if a save would overwrite the destination because it has been
+	 *            changed since last open/save.
+	 * @throws OverwriteException
+	 *             if failOnOverwrite was true, and a save would overwrite the
+	 *             destination because it has been changed since last open/save.
+	 *             The save was not performed.
+	 * @throws SaveException
+	 *             If any other error occurs during saving, including the case
+	 *             that a dataflow is not connected to a source or destination,
+	 *             that there are no handlers (some source types can't be saved
+	 *             to, such as HTTP URLs), or any other IO error occurring while
+	 *             saving.
+	 */
+	void saveDataflow(WorkflowBundle dataflow, boolean failOnOverwrite)
+			throws SaveException, OverwriteException;
+
+	/**
+	 * Save the dataflow to the given destination using the given filetype.
+	 * <p>
+	 * The file manager will find implementations of the SPI
+	 * {@link DataflowPersistenceHandler} to perform the save for the given file
+	 * type and destination class.
+	 * <p>
+	 * Listeners registered using {@link Observable#addObserver(Observer)} will
+	 * be notified with an {@link SavedDataflowEvent}.
+	 *
+	 * @param dataflow
+	 *            {@link Dataflow} to be saved
+	 * @param fileType
+	 *            {@link FileType} to save dataflow as, for instance
+	 *            {@link net.sf.taverna.t2.workbench.file.impl.T2FlowFileType}.
+	 *            The file type must be supported by an SPI implementation of
+	 *            {@link DataflowPersistenceHandler}.
+	 * @param destination
+	 *            Destination to save dataflow to, for instance a {@link File}
+	 * @param failOnOverwrite
+	 *            If <code>true</code>, an {@link OverwriteException} is thrown
+	 *            if a save would overwrite the destination because it already
+	 *            exists, but was not opened or save to using the file manager
+	 *            for the given dataflow. (ie. a repeated call to this function
+	 *            should not throw an OverwriteException unless someone outside
+	 *            has modified the file)
+	 * @throws OverwriteException
+	 *             if failOnOverwrite was true, and a save would overwrite the
+	 *             destination because it already existed, and was not last
+	 *             written to by a previous save. The save was not performed.
+	 * @throws SaveException
+	 *             If any other error occurs during saving, including the case
+	 *             that a dataflow is not connected to a source or destination,
+	 *             that there are no handlers (some source types can't be saved
+	 *             to, such as HTTP URLs), or any other IO error occurring while
+	 *             saving.
+	 */
+	void saveDataflow(WorkflowBundle dataflow, FileType fileType,
+			Object destination, boolean failOnOverwrite) throws SaveException,
+			OverwriteException;
+
+	/**
+	 * Silently save the dataflow to the given destination using the given
+	 * filetype.
+	 * <p>
+	 * The file manager will find implementations of the SPI
+	 * {@link DataflowPersistenceHandler} to perform the save for the given file
+	 * type and destination class.
+	 * <p>
+	 * Listeners will <strong>not</strong> be notified, and the dataflow does
+	 * not previously have to be opened. getDataflowSource(),
+	 * isDataflowChanged() etc will not be affected - as if the silent save
+	 * never happened.
+	 * 
+	 * @param dataflow
+	 *            {@link WorkflowBundle} to be saved
+	 * @param fileType
+	 *            {@link FileType} to save dataflow as, for instance
+	 *            {@link net.sf.taverna.t2.workbench.file.impl.T2FlowFileType}.
+	 *            The file type must be supported by an SPI implementation of
+	 *            {@link DataflowPersistenceHandler}.
+	 * @param destination
+	 *            Destination to save dataflow to, for instance a {@link File}
+	 * @param failOnOverwrite
+	 *            If <code>true</code>, an {@link OverwriteException} is thrown
+	 *            if a save would overwrite the destination because it already
+	 *            exists, but was not opened or save to using the file manager
+	 *            for the given dataflow. (ie. a repeated call to this function
+	 *            should not throw an OverwriteException unless someone outside
+	 *            has modified the file)
+	 * @return The {@link DataflowInfo} describing where the workflow was saved
+	 * @throws OverwriteException
+	 *             if failOnOverwrite was true, and a save would overwrite the
+	 *             destination because it already existed, and was not last
+	 *             written to by a previous save. The save was not performed.
+	 * @throws SaveException
+	 *             If any other error occurs during saving, including the case
+	 *             that a dataflow is not connected to a source or destination,
+	 *             that there are no handlers (some source types can't be saved
+	 *             to, such as HTTP URLs), or any other IO error occurring while
+	 *             saving.
+	 */
+	DataflowInfo saveDataflowSilently(WorkflowBundle dataflow, FileType fileType,
+			Object destination, boolean failOnOverwrite) throws SaveException,
+			OverwriteException;
+
+	/**
+	 * Set the current dataflow to the one provided.
+	 * <p>
+	 * The current dataflow can be retrieved using {@link #getCurrentDataflow()}
+	 * . Note that opening a dataflow will normally also set it as the current
+	 * dataflow.
+	 * <p>
+	 * Listeners registered using {@link Observable#addObserver(Observer)} will
+	 * be notified with an {@link SetCurrentDataflowEvent}.
+	 * <p>
+	 * Note, the dataflow must already be open. If this is not the case, use one
+	 * of the openDataflow() methods or
+	 * {@link #setCurrentDataflow(WorkflowBundle, boolean)}.
+	 *
+	 * @see #setCurrentDataflow(WorkflowBundle, boolean)
+	 * @param dataflow
+	 *            {@link WorkflowBundle} to be made current
+	 */
+	void setCurrentDataflow(WorkflowBundle dataflow);
+
+	/**
+	 * Set the current dataflow to the one provided.
+	 * <p>
+	 * The current dataflow can be retrieved using {@link #getCurrentDataflow()}
+	 * . Note that opening a dataflow will normally also set it as the current
+	 * dataflow.
+	 * <p>
+	 * Listeners registered using {@link Observable#addObserver(Observer)} will
+	 * be notified with an {@link SetCurrentDataflowEvent}.
+	 * <p>
+	 * Unless <code>openIfNeeded</code> is <code>true</code>, the dataflow must
+	 * already be open.
+	 *
+	 * @see #setCurrentDataflow(WorkflowBundle, boolean)
+	 * @param dataflow
+	 *            {@link WorkflowBundle} to be made current
+	 * @param openIfNeeded
+	 *            If <code>true</code>, open the dataflow if needed
+	 */
+	void setCurrentDataflow(WorkflowBundle dataflow, boolean openIfNeeded);
+
+	/**
+	 * Set a dataflow as changed or not. This changes the value returned by
+	 * {@link #isDataflowChanged(WorkflowBundle)}.
+	 * <p>
+	 * This method can be used if the dataflow has been changed outside the
+	 * {@link EditManager}.
+	 *
+	 * @param dataflow
+	 *            Dataflow which is to be marked
+	 * @param isChanged
+	 *            <code>true</code> if the dataflow is to be marked as changed,
+	 *            <code>false</code> if it is to be marked as not changed.
+	 */
+	void setDataflowChanged(WorkflowBundle dataflow, boolean isChanged);
+
+	/**
+	 * Returns the canonical form of the source where the dataflow was opened
+	 * from or saved to. The code for this method was devised based on
+	 * {@link net.sf.taverna.t2.workbench.file.impl.T2DataflowOpener#openDataflow(FileType fileType, Object source)}.
+	 */
+	Object getCanonical(Object source) throws IllegalArgumentException,
+			URISyntaxException, IOException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/FileType.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/FileType.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/FileType.java
new file mode 100644
index 0000000..001d82c
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/FileType.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * A filetype to identify a way to (de)serialise a {@link WorkflowBundle} with
+ * the {@link FileManager}.
+ * <p>
+ * Two filetypes are considered equal if they share an extension or mime type or
+ * are the same instance.
+ * 
+ * @see net.sf.taverna.t2.workbench.file.impl.WorkflowBundleFileType
+ * @author Stian Soiland-Reyes
+ */
+public abstract class FileType {
+	public abstract String getExtension();
+
+	public abstract String getMimeType();
+
+	public abstract String getDescription();
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (obj == this)
+			return true;
+		if (!(obj instanceof FileType))
+			return false;
+		FileType other = (FileType) obj;
+		if (getMimeType() != null && other.getMimeType() != null)
+			return getMimeType().equalsIgnoreCase(other.getMimeType());
+		if (getExtension() != null && other.getExtension() != null)
+			return getExtension().equalsIgnoreCase(other.getExtension());
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		int hash = 7;
+		hash = 31 * hash + getExtension().hashCode();
+		hash = 31 * hash + getMimeType().hashCode();
+		return hash;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/AbstractDataflowEvent.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/AbstractDataflowEvent.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/AbstractDataflowEvent.java
new file mode 100644
index 0000000..942e097
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/AbstractDataflowEvent.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.events;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * Abstract FileManagerEvent that relates to a {@link WorkflowBundle}
+ * 
+ * @see AbstractDataflowEvent
+ * @see ClosedDataflowEvent
+ * @see OpenedDataflowEvent
+ * @see SavedDataflowEvent
+ * @see SetCurrentDataflowEvent
+ * @author Stian Soiland-Reyes
+ */
+public abstract class AbstractDataflowEvent extends FileManagerEvent {
+	private final WorkflowBundle workflowBundle;
+
+	public AbstractDataflowEvent(WorkflowBundle workflowBundle) {
+		this.workflowBundle = workflowBundle;
+	}
+
+	public WorkflowBundle getDataflow() {
+		return workflowBundle;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/ClosedDataflowEvent.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/ClosedDataflowEvent.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/ClosedDataflowEvent.java
new file mode 100644
index 0000000..5e7e884
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/ClosedDataflowEvent.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.events;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * {@link FileManagerEvent} that means a {@link WorkflowBundle} has been closed.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class ClosedDataflowEvent extends AbstractDataflowEvent {
+	public ClosedDataflowEvent(WorkflowBundle workflowBundle) {
+		super(workflowBundle);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/ClosingDataflowEvent.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/ClosingDataflowEvent.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/ClosingDataflowEvent.java
new file mode 100644
index 0000000..094ea10
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/ClosingDataflowEvent.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.events;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * {@link FileManagerEvent} that means a {@link WorkflowBundle} is being closed.
+ * <i>This event is abortable;</i> if aborted, the close will not occur.
+ * 
+ * @author Alan R Williams
+ */
+public class ClosingDataflowEvent extends AbstractDataflowEvent {
+	private boolean abortClose = false;
+
+	public boolean isAbortClose() {
+		return abortClose;
+	}
+
+	public void setAbortClose(boolean abortClose) {
+		this.abortClose = abortClose;
+	}
+
+	public ClosingDataflowEvent(WorkflowBundle workflowBundle) {
+		super(workflowBundle);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/FileManagerEvent.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/FileManagerEvent.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/FileManagerEvent.java
new file mode 100644
index 0000000..84c3886
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/FileManagerEvent.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.events;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.workbench.file.FileManager;
+
+/**
+ * An event given to {@link FileManager} observers registered using
+ * {@link Observable#addObserver(net.sf.taverna.t2.lang.observer.Observer)}.
+ * 
+ * @see AbstractDataflowEvent
+ * @see ClosedDataflowEvent
+ * @see OpenedDataflowEvent
+ * @see SavedDataflowEvent
+ * @see SetCurrentDataflowEvent
+ * @author Stian Soiland-Reyes
+ */
+public class FileManagerEvent {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/OpenedDataflowEvent.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/OpenedDataflowEvent.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/OpenedDataflowEvent.java
new file mode 100644
index 0000000..b479a83
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/OpenedDataflowEvent.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.events;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * {@link FileManagerEvent} that means a dataflow has been opened
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class OpenedDataflowEvent extends AbstractDataflowEvent {
+	public OpenedDataflowEvent(WorkflowBundle workflowBundle) {
+		super(workflowBundle);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/SavedDataflowEvent.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/SavedDataflowEvent.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/SavedDataflowEvent.java
new file mode 100644
index 0000000..f0f22ae
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/SavedDataflowEvent.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.events;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * {@link FileManagerEvent} that means a {@link WorkflowBundle} has been saved.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class SavedDataflowEvent extends AbstractDataflowEvent {
+	public SavedDataflowEvent(WorkflowBundle workflowBundle) {
+		super(workflowBundle);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/SetCurrentDataflowEvent.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/SetCurrentDataflowEvent.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/SetCurrentDataflowEvent.java
new file mode 100644
index 0000000..ff44cf2
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/events/SetCurrentDataflowEvent.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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.events;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * {@link FileManagerEvent} that means a {@link WorkflowBundle} has been made
+ * current.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class SetCurrentDataflowEvent extends AbstractDataflowEvent {
+	public SetCurrentDataflowEvent(WorkflowBundle workflowBundle) {
+		super(workflowBundle);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/FileException.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/FileException.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/FileException.java
new file mode 100644
index 0000000..a2cb9ce
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/FileException.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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.exceptions;
+
+import net.sf.taverna.t2.workbench.file.FileManager;
+
+/**
+ * Superclass of exceptions thrown by the {@link FileManager}.
+ */
+@SuppressWarnings("serial")
+public class FileException extends Exception {
+	public FileException() {
+	}
+
+	public FileException(String message) {
+		super(message);
+	}
+
+	public FileException(Throwable cause) {
+		super(cause);
+	}
+
+	public FileException(String message, Throwable cause) {
+		super(message, cause);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/OpenException.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/OpenException.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/OpenException.java
new file mode 100644
index 0000000..057679b
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/OpenException.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.exceptions;
+
+/** Indicate that something went wrong during opening a file */
+@SuppressWarnings("serial")
+public class OpenException extends FileException {
+	public OpenException() {
+	}
+
+	public OpenException(String message) {
+		super(message);
+	}
+
+	public OpenException(Throwable cause) {
+		super(cause);
+	}
+
+	public OpenException(String message, Throwable cause) {
+		super(message, cause);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/OverwriteException.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/OverwriteException.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/OverwriteException.java
new file mode 100644
index 0000000..6d410a3
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/OverwriteException.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.file.exceptions;
+
+/** Indicate that something could not be overwritten. */
+@SuppressWarnings("serial")
+public class OverwriteException extends SaveException {
+	private final Object destination;
+
+	public OverwriteException(Object destination) {
+		super("Save would overwrite existing destination " + destination);
+		this.destination = destination;
+	}
+
+	public Object getDestination() {
+		return destination;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/SaveException.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/SaveException.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/SaveException.java
new file mode 100644
index 0000000..8c4266f
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/SaveException.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.exceptions;
+
+/** Indicate that a workflow could not be saved. */
+@SuppressWarnings("serial")
+public class SaveException extends FileException {
+	public SaveException() {
+	}
+
+	public SaveException(String message) {
+		super(message);
+	}
+
+	public SaveException(Throwable cause) {
+		super(cause);
+	}
+
+	public SaveException(String message, Throwable cause) {
+		super(message, cause);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/UnsavedException.java
----------------------------------------------------------------------
diff --git a/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/UnsavedException.java b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/UnsavedException.java
new file mode 100644
index 0000000..41c01f8
--- /dev/null
+++ b/taverna-file-api/src/main/java/net/sf/taverna/t2/workbench/file/exceptions/UnsavedException.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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.exceptions;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/** Indicate that a workflow bundle is not saved. */
+@SuppressWarnings("serial")
+public class UnsavedException extends FileException {
+	private final WorkflowBundle workflowBundle;
+
+	public UnsavedException(WorkflowBundle workflowBundle) {
+		super("WorkflowBundle was not saved: " + workflowBundle);
+		this.workflowBundle = workflowBundle;
+	}
+
+	public WorkflowBundle getDataflow() {
+		return workflowBundle;
+	}
+}