blob: 691b27839eca77bd13e5bdf67de00446a33a1a53 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package net.sf.taverna.t2.workbench.file.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.sf.taverna.t2.lang.observer.Observable;
import net.sf.taverna.t2.lang.observer.Observer;
import net.sf.taverna.t2.workbench.edits.Edit;
import net.sf.taverna.t2.workbench.edits.EditManager;
import net.sf.taverna.t2.workbench.edits.impl.EditManagerImpl;
import net.sf.taverna.t2.workbench.file.DataflowInfo;
import net.sf.taverna.t2.workbench.file.DataflowPersistenceHandler;
import net.sf.taverna.t2.workbench.file.FileManager;
import net.sf.taverna.t2.workbench.file.events.FileManagerEvent;
import net.sf.taverna.t2.workbench.file.events.SetCurrentDataflowEvent;
import net.sf.taverna.t2.workbench.file.exceptions.OpenException;
import net.sf.taverna.t2.workbench.file.exceptions.OverwriteException;
import net.sf.taverna.t2.workflow.edits.AddProcessorEdit;
import net.sf.taverna.t2.workflow.edits.RenameEdit;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import uk.org.taverna.scufl2.api.container.WorkflowBundle;
import uk.org.taverna.scufl2.api.core.Processor;
import uk.org.taverna.scufl2.api.core.Workflow;
import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
import uk.org.taverna.scufl2.api.io.WorkflowBundleReader;
import uk.org.taverna.scufl2.api.io.WorkflowBundleWriter;
import uk.org.taverna.scufl2.rdfxml.RDFXMLReader;
import uk.org.taverna.scufl2.rdfxml.RDFXMLWriter;
import uk.org.taverna.scufl2.translator.t2flow.T2FlowReader;
public class FileManagerTest {
private static final WorkflowBundleFileType WF_BUNDLE_FILE_TYPE = new WorkflowBundleFileType();
private static final T2FlowFileType T2_FLOW_FILE_TYPE = new T2FlowFileType();
private static final String DUMMY_WORKFLOW_T2FLOW = "dummy-workflow.t2flow";
private FileManagerImpl fileManager;
private EditManager editManager;
private FileManagerObserver fileManagerObserver= new FileManagerObserver();;
@Test
public void close() throws Exception {
assertTrue("Non-empty set of open dataflows", fileManager
.getOpenDataflows().isEmpty());
WorkflowBundle dataflow = openDataflow();
assertEquals("Unexpected list of open dataflows", Arrays
.asList(dataflow), fileManager.getOpenDataflows());
fileManager.closeDataflow(dataflow, true);
assertNotSame(dataflow, fileManager.getOpenDataflows().get(0));
assertTrue("Did not insert empty dataflow after close", fileManager
.getOpenDataflows().get(0).getMainWorkflow().getProcessors().isEmpty());
}
@Test
public void openRemovesEmptyDataflow() throws Exception {
WorkflowBundle newDataflow = fileManager.newDataflow();
assertEquals("Unexpected list of open dataflows", Arrays
.asList(newDataflow), fileManager.getOpenDataflows());
WorkflowBundle dataflow = openDataflow();
// Should have removed newDataflow
assertEquals("Unexpected list of open dataflows", Arrays
.asList(dataflow), fileManager.getOpenDataflows());
}
@Test
public void isChanged() throws Exception {
WorkflowBundle dataflow = openDataflow();
assertFalse("Dataflow should not have changed", fileManager
.isDataflowChanged(dataflow));
// Do a change
Processor emptyProcessor = new Processor();
Edit<Workflow> addProcessorEdit = new AddProcessorEdit(dataflow.getMainWorkflow(),
emptyProcessor);
editManager.doDataflowEdit(dataflow, addProcessorEdit);
assertTrue("Dataflow should have changed", fileManager
.isDataflowChanged(dataflow));
// Save it with the change
File dataflowFile = File.createTempFile("test", ".t2flow");
dataflowFile.deleteOnExit();
dataflowFile.delete();
fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false);
assertFalse("Dataflow should no longer be marked as changed",
fileManager.isDataflowChanged(dataflow));
}
@Ignore("Undo support for ischanged not yet implemented")
@Test
public void isChangedWithUndo() throws Exception {
WorkflowBundle dataflow = openDataflow();
// Do a change
Processor emptyProcessor = new Processor();
Edit<Workflow> addProcessorEdit = new AddProcessorEdit(dataflow.getMainWorkflow(),
emptyProcessor);
editManager.doDataflowEdit(dataflow, addProcessorEdit);
assertTrue("Dataflow should have changed", fileManager
.isDataflowChanged(dataflow));
editManager.undoDataflowEdit(dataflow);
assertFalse(
"Dataflow should no longer be marked as changed after undo",
fileManager.isDataflowChanged(dataflow));
editManager.redoDataflowEdit(dataflow);
assertTrue("Dataflow should have changed after redo before save",
fileManager.isDataflowChanged(dataflow));
// Save it with the change
File dataflowFile = File.createTempFile("test", ".t2flow");
dataflowFile.deleteOnExit();
dataflowFile.delete();
fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false);
assertFalse("Dataflow should no longer be marked as changed",
fileManager.isDataflowChanged(dataflow));
editManager.undoDataflowEdit(dataflow);
assertTrue("Dataflow should have changed after undo", fileManager
.isDataflowChanged(dataflow));
fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false);
editManager.redoDataflowEdit(dataflow);
assertTrue("Dataflow should have changed after redo after save",
fileManager.isDataflowChanged(dataflow));
}
@Test
public void isListed() throws Exception {
assertTrue("Non-empty set of open data flows", fileManager
.getOpenDataflows().isEmpty());
WorkflowBundle dataflow = openDataflow();
assertEquals("Unexpected list of open dataflows", Arrays
.asList(dataflow), fileManager.getOpenDataflows());
}
/**
* Always uses a <strong>new</strong> file manager instead of the instance
* one from {@link FileManager#getInstance()}.
*
* @see #getFileManagerInstance()
*
*/
@Before
public void makeFileManager() {
System.setProperty("java.awt.headless", "true");
editManager = new EditManagerImpl();
fileManager = new FileManagerImpl(editManager);
fileManagerObserver = new FileManagerObserver();
fileManager.addObserver(fileManagerObserver);
WorkflowBundleIO workflowBundleIO = new WorkflowBundleIO();
workflowBundleIO.setReaders(Arrays.<WorkflowBundleReader>asList(new RDFXMLReader(), new T2FlowReader()));
workflowBundleIO.setWriters(Arrays.<WorkflowBundleWriter>asList(new RDFXMLWriter()));
T2DataflowOpener t2DataflowOpener = new T2DataflowOpener();
t2DataflowOpener.setWorkflowBundleIO(workflowBundleIO);
WorkflowBundleOpener workflowBundleOpener = new WorkflowBundleOpener();
workflowBundleOpener.setWorkflowBundleIO(workflowBundleIO);
WorkflowBundleSaver workflowBundleSaver = new WorkflowBundleSaver();
workflowBundleSaver.setWorkflowBundleIO(workflowBundleIO);
DataflowPersistenceHandlerRegistry dataflowPersistenceHandlerRegistry = new DataflowPersistenceHandlerRegistry();
dataflowPersistenceHandlerRegistry.setDataflowPersistenceHandlers(Arrays.asList(
new DataflowPersistenceHandler[] {t2DataflowOpener, workflowBundleOpener, workflowBundleSaver}));
dataflowPersistenceHandlerRegistry.updateColletions();
fileManager.setDataflowPersistenceHandlerRegistry(dataflowPersistenceHandlerRegistry);
}
@Test
public void open() throws Exception {
assertTrue("ModelMapObserver already contained messages",
fileManagerObserver.messages.isEmpty());
WorkflowBundle dataflow = openDataflow();
assertNotNull("Dataflow was not loaded", dataflow);
assertEquals("Loaded dataflow was not set as current dataflow",
dataflow, fileManager.getCurrentDataflow());
assertFalse("ModelMapObserver did not contain message",
fileManagerObserver.messages.isEmpty());
assertEquals("ModelMapObserver contained unexpected messages", 2,
fileManagerObserver.messages.size());
FileManagerEvent event = fileManagerObserver.messages.get(0);
assertTrue(event instanceof SetCurrentDataflowEvent);
assertEquals(dataflow, ((SetCurrentDataflowEvent) event).getDataflow());
}
@Test
public void openSilently() throws Exception {
assertTrue("ModelMapObserver already contained messages",
fileManagerObserver.messages.isEmpty());
URL url = getClass().getResource(DUMMY_WORKFLOW_T2FLOW);
DataflowInfo info = fileManager.openDataflowSilently(T2_FLOW_FILE_TYPE, url);
WorkflowBundle dataflow = info.getDataflow();
assertNotNull("Dataflow was not loaded", dataflow);
assertNotSame("Loaded dataflow was set as current dataflow",
dataflow, fileManager.getCurrentDataflow());
assertTrue("ModelMapObserver contained unexpected messages",
fileManagerObserver.messages.isEmpty());
}
@Test
public void canSaveDataflow() throws Exception {
WorkflowBundle savedDataflow = openDataflow();
File dataflowFile = File.createTempFile("test", ".t2flow");
dataflowFile.deleteOnExit();
dataflowFile.delete();
fileManager.saveDataflow(savedDataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true);
assertTrue(fileManager.canSaveWithoutDestination(savedDataflow));
fileManager.saveDataflow(savedDataflow, true);
fileManager.closeDataflow(savedDataflow, true);
WorkflowBundle otherFlow = fileManager.openDataflow(WF_BUNDLE_FILE_TYPE, dataflowFile.toURI()
.toURL());
assertTrue(fileManager.canSaveWithoutDestination(otherFlow));
}
@Test
public void save() throws Exception {
WorkflowBundle savedDataflow = openDataflow();
File dataflowFile = File.createTempFile("test", ".t2flow");
dataflowFile.deleteOnExit();
dataflowFile.delete();
assertFalse("File should not exist", dataflowFile.isFile());
fileManager.saveDataflow(savedDataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false);
assertTrue("File should exist", dataflowFile.isFile());
WorkflowBundle loadedDataflow = fileManager.openDataflow(WF_BUNDLE_FILE_TYPE, dataflowFile.toURI()
.toURL());
assertNotSame("Dataflow was not reopened", savedDataflow,
loadedDataflow);
assertEquals("Unexpected number of processors in saved dataflow", 1,
savedDataflow.getMainWorkflow().getProcessors().size());
assertEquals("Unexpected number of processors in loaded dataflow", 1,
loadedDataflow.getMainWorkflow().getProcessors().size());
Processor savedProcessor = savedDataflow.getMainWorkflow().getProcessors().first();
Processor loadedProcessor = loadedDataflow.getMainWorkflow().getProcessors().first();
assertEquals("Loaded processor had wrong name", savedProcessor
.getName(), loadedProcessor.getName());
// TODO convert to scufl2
// BeanshellActivity savedActivity = (BeanshellActivity) savedProcessor
// .getActivityList().get(0);
// BeanshellActivity loadedActivity = (BeanshellActivity) loadedProcessor
// .getActivityList().get(0);
// String savedScript = savedActivity.getConfiguration().getScript();
// String loadedScript = loadedActivity.getConfiguration().getScript();
// assertEquals("Unexpected saved script",
// "String output = input + \"XXX\";", savedScript);
// assertEquals("Loaded script did not matched saved script", savedScript,
// loadedScript);
}
@Test
public void saveSilent() throws Exception {
assertTrue("ModelMapObserver contained unexpected messages",
fileManagerObserver.messages.isEmpty());
URL url = getClass().getResource(DUMMY_WORKFLOW_T2FLOW);
DataflowInfo info = fileManager.openDataflowSilently(T2_FLOW_FILE_TYPE, url);
WorkflowBundle dataflow = info.getDataflow();
assertTrue("ModelMapObserver contained unexpected messages",
fileManagerObserver.messages.isEmpty());
File dataflowFile = File.createTempFile("test", ".t2flow");
dataflowFile.deleteOnExit();
dataflowFile.delete();
assertFalse("File should not exist", dataflowFile.isFile());
fileManager.saveDataflowSilently(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, false);
assertTrue("File should exist", dataflowFile.isFile());
assertTrue("ModelMapObserver contained unexpected messages",
fileManagerObserver.messages.isEmpty());
}
@Test
public void saveOverwriteAgain() throws Exception {
WorkflowBundle dataflow = openDataflow();
File dataflowFile = File.createTempFile("test", ".t2flow");
dataflowFile.delete();
dataflowFile.deleteOnExit();
// File did NOT exist, should not fail
fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true);
Processor processor = dataflow.getMainWorkflow().getProcessors().first();
Edit<Processor> renameEdit = new RenameEdit<Processor>(processor,
processor.getName() + "-changed");
editManager.doDataflowEdit(dataflow, renameEdit);
// Last save was OURs, so should *not* fail - even if we now use
// the specific saveDataflow() method
fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true);
//Thread.sleep(1500);
WorkflowBundle otherFlow = openDataflow();
// Saving another flow to same file should still fail
try {
fileManager.saveDataflow(otherFlow,WF_BUNDLE_FILE_TYPE, dataflowFile, true);
fail("Should have thrown OverwriteException");
} catch (OverwriteException ex) {
// Expected
}
}
@Test(expected = OverwriteException.class)
public void saveOverwriteWarningFails() throws Exception {
WorkflowBundle dataflow = openDataflow();
File dataflowFile = File.createTempFile("test", ".t2flow");
dataflowFile.deleteOnExit();
// Should fail as file already exists
fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true);
}
@Test
public void saveOverwriteWarningWorks() throws Exception {
WorkflowBundle dataflow = openDataflow();
File dataflowFile = File.createTempFile("test", ".t2flow");
dataflowFile.delete();
dataflowFile.deleteOnExit();
// File did NOT exist, should not fail
fileManager.saveDataflow(dataflow, WF_BUNDLE_FILE_TYPE, dataflowFile, true);
}
@After
public void stopListeningToModelMap() {
fileManager.removeObserver(fileManagerObserver);
}
protected WorkflowBundle openDataflow() throws OpenException {
URL url = getClass().getResource(DUMMY_WORKFLOW_T2FLOW);
assertNotNull(url);
WorkflowBundle dataflow = fileManager.openDataflow(T2_FLOW_FILE_TYPE, url);
assertNotNull(dataflow);
return dataflow;
}
private final class FileManagerObserver implements Observer<FileManagerEvent> {
protected List<FileManagerEvent> messages = new ArrayList<FileManagerEvent>();
@Override
public void notify(Observable<FileManagerEvent> sender, FileManagerEvent message) throws Exception {
messages.add(message);
if (message instanceof SetCurrentDataflowEvent) {
assertTrue("Dataflow was not listed as open when set current",
fileManager.getOpenDataflows().contains(
((SetCurrentDataflowEvent) message).getDataflow()));
}
}
}
}