Revert "taverna-observer moved to taverna-engine (!)"

This reverts commit 7db92d5b4817762fc1a07c9bd396840920fffd46.
diff --git a/taverna-observer/pom.xml b/taverna-observer/pom.xml
new file mode 100644
index 0000000..5bf4236
--- /dev/null
+++ b/taverna-observer/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>net.sf.taverna.t2.lang</groupId>
+	<artifactId>observer</artifactId>
+	<name>Observer pattern</name>
+	<parent>
+		<groupId>net.sf.taverna.t2</groupId>
+		<artifactId>lang</artifactId>
+		<version>1.6-SNAPSHOT</version>
+	</parent>
+	<description>Implementation of the Observer pattern.</description>
+	<dependencies>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/MultiCaster.java b/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/MultiCaster.java
new file mode 100644
index 0000000..d563e39
--- /dev/null
+++ b/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/MultiCaster.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.lang.observer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Send notifications to registered observers about changes to models
+ * 
+ * @author Ian Dunlop
+ * @author Stian Soiland
+ * 
+ * @param <Message>
+ */
+public class MultiCaster<Message> implements Observable<Message> {
+
+	private static Logger logger = Logger.getLogger(MultiCaster.class);
+
+	private Observable<Message> observable;
+
+	protected List<Observer<Message>> observers = new ArrayList<Observer<Message>>();
+
+	/**
+	 * Set the {@link #observable} ie. the class that changes are happening to
+	 * and it's Message for this {@link MultiCaster}
+	 * 
+	 * @param observable
+	 */
+	public MultiCaster(Observable<Message> observable) {
+		this.observable = observable;
+	}
+
+	/**
+	 * Tell all the registered observers about the change to the model
+	 * 
+	 * @param message
+	 */
+	@SuppressWarnings("unchecked")
+	public void notify(Message message) {
+		// Use a copy that can be iterated even if register/remove is called
+		for (Observer<Message> observer : getObservers()) {
+			try {
+				observer.notify(observable, message);
+			} catch (Exception ex) {
+				logger.warn("Could not notify " + observer, ex);
+			}
+		}
+	}
+
+	/**
+	 * Register an observer ie. someone who wants informed about changes
+	 */
+	public synchronized void addObserver(Observer<Message> observer) {
+		observers.add(observer);
+	}
+
+	/**
+	 * Remove the observer and no longer send out any notifications about it
+	 */
+	public synchronized void removeObserver(Observer<Message> observer) {
+		observers.remove(observer);
+	}
+
+	/**
+	 * A list of all the classes currently registered with this
+	 * {@link MultiCaster}
+	 */
+	public synchronized List<Observer<Message>> getObservers() {
+		return new ArrayList<Observer<Message>>(observers);
+	}
+
+}
diff --git a/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/Observable.java b/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/Observable.java
new file mode 100644
index 0000000..1fa7425
--- /dev/null
+++ b/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/Observable.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.lang.observer;
+
+import java.util.List;
+
+/**
+ * Implements this if you want to notify other classes about changes
+ * 
+ * @author Ian Dunlop
+ * @author Stian Soiland
+ * 
+ * @param <Message>
+ */
+public interface Observable<Message> {
+	/**
+	 * Register an {@link Observer}
+	 * 
+	 * @param observer
+	 *            the class who wants notified of changes
+	 */
+	public void addObserver(Observer<Message> observer);
+
+	/**
+	 * Remove a class who is currently observing
+	 * 
+	 * @param observer
+	 *            the class who no longer wants notified
+	 */
+	public void removeObserver(Observer<Message> observer);
+
+	/**
+	 * A list of all the currently registered {@link Observer}s
+	 * 
+	 * @return
+	 */
+	public List<Observer<Message>> getObservers();
+}
diff --git a/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/Observer.java b/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/Observer.java
new file mode 100644
index 0000000..81b7c85
--- /dev/null
+++ b/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/Observer.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.lang.observer;
+
+/**
+ * Implement if you want to register with an {@link Observable}
+ * 
+ * @author Ian Dunlop
+ * @author Stian Soiland
+ * 
+ * @param <Message>
+ */
+public interface Observer<Message> {
+	/**
+	 * Called by the {@link Observable} to notify the implementing class of
+	 * changes
+	 * 
+	 * @param sender
+	 *            the class where the changes have happened
+	 * @param message
+	 *            what has changed
+	 * @throws Exception
+	 */
+	public void notify(Observable<Message> sender, Message message)
+			throws Exception;
+}
diff --git a/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/package-info.java b/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/package-info.java
new file mode 100644
index 0000000..e9d3ff2
--- /dev/null
+++ b/taverna-observer/src/main/java/net/sf/taverna/t2/lang/observer/package-info.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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
+ ******************************************************************************/
+/**
+ * Implementation of the observer pattern.  {@link Observer}s registers with an 
+ * {@link Observable} using {@link Observable#addObserver(Observer)}, and will receive 
+ * notifications as a call to {@link Observer#notify(Observable, Object)}. 
+ * <p>
+ * Typical implementations of {@link Observable} will be delegating to a 
+ * {@link MultiCaster} to do the boring observer registration and message 
+ * dispatching.
+ * </p>
+ * <p>
+ * Example of Observable:
+ * <pre>
+ * public class MyObservable implements Observable<MyEvent> {
+ * 	 public static class MyEvent {
+ * 		// ..
+ * 	 }
+ * 	 private MultiCaster&lt:MyEvent&gt; multiCaster = new MultiCaster&lt:MyEvent&gt;(this);
+ * 
+ *	 public void doStuff() {
+ *		multiCaster.notify(new MyEvent());
+ *	 }
+ * 
+ * 	 public void addObserver(Observer<MyEvent> observer) {
+ * 		multiCaster.addObserver(observer);
+ * 	 }
+ * 
+ * 	 public List<Observer<MyEvent>> getObservers() {
+ * 		return multiCaster.getObservers();
+ * 	 }
+ * 
+ * 	 public void removeObserver(Observer<MyEvent> observer) {
+ * 		multiCaster.removeObserver(observer);
+ * 	 }
+ * }
+ * </pre>
+ * And an observer that is notified when MyObservable.doStuff() is called:
+ * <pre>
+ * public class MyObserver implements Observer<MyEvent> {
+ *	 public void notify(Observable<MyEvent> sender, MyEvent message) {
+ *		System.out.println("Receieved " + message + " from " + sender);
+ * 	 }
+ * }
+ * </pre>
+ * Example of usage:
+ * <pre>
+ * 		MyObservable observable = new MyObservable();
+ *		MyObserver observer = new MyObserver();
+ *		observable.addObserver(observer);
+ *		observable.doStuff();
+ *	</pre>
+ */
+package net.sf.taverna.t2.lang.observer;
+
diff --git a/taverna-observer/src/test/java/net/sf/taverna/t2/lang/observer/ObserverTest.java b/taverna-observer/src/test/java/net/sf/taverna/t2/lang/observer/ObserverTest.java
new file mode 100644
index 0000000..661cbbc
--- /dev/null
+++ b/taverna-observer/src/test/java/net/sf/taverna/t2/lang/observer/ObserverTest.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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.lang.observer;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import net.sf.taverna.t2.lang.observer.MultiCaster;
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.Observer;
+
+import org.junit.Test;
+
+public class ObserverTest {
+
+	@Test
+	public void registerObserver() throws Exception {
+		MyObservable observable = new MyObservable();
+		MyObserver observer1 = new MyObserver();
+		MyObserver observer2 = new MyObserver();
+
+		observable.triggerEvent(); // don't notify, but increase count
+		assertNull(observer1.lastMessage);
+		observable.addObserver(observer1);
+		assertNull(observer1.lastMessage);
+		assertNull(observer2.lastMessage);
+		assertNull(observer1.lastSender);
+		assertNull(observer2.lastSender);
+		observable.triggerEvent();
+		assertEquals("This is message 1", observer1.lastMessage);
+		assertSame(observable, observer1.lastSender);
+		assertNull(observer2.lastSender);
+
+		observable.addObserver(observer2);
+		assertNull(observer2.lastMessage);
+		observable.triggerEvent();
+		assertEquals("This is message 2", observer1.lastMessage);
+		assertEquals("This is message 2", observer2.lastMessage);
+		assertSame(observable, observer1.lastSender);
+		assertSame(observable, observer2.lastSender);
+
+		MyObservable otherObservable = new MyObservable();
+		otherObservable.addObserver(observer2);
+		otherObservable.triggerEvent();
+		// New instance, should start from 0
+		assertEquals("This is message 0", observer2.lastMessage);
+		assertSame(otherObservable, observer2.lastSender);
+
+		// observer1 unchanged
+		assertEquals("This is message 2", observer1.lastMessage);
+		assertSame(observable, observer1.lastSender);
+
+	}
+
+	@Test
+	public void concurrencyTest() {
+		MyObservable observable = new MyObservable();
+		MyObserver dummyObserver = new MyObserver();
+		SelvRemovingObserver selfRemoving = new SelvRemovingObserver();
+		observable.addObserver(dummyObserver);
+		observable.addObserver(selfRemoving);
+		assertEquals(2, observable.getObservers().size());
+		observable.triggerEvent();
+		
+		
+	}
+	
+	public class MyObservable implements Observable<String> {
+
+		private int counter = 0;
+		MultiCaster<String> multiCaster = new MultiCaster<String>(this);
+
+		public void addObserver(Observer<String> observer) {
+			multiCaster.addObserver(observer);
+		}
+
+		public void removeObserver(Observer<String> observer) {
+			multiCaster.removeObserver(observer);
+		}
+
+		public void triggerEvent() {
+			multiCaster.notify("This is message " + counter++);
+		}
+
+		public List<Observer<String>> getObservers() {
+			return multiCaster.getObservers();
+		}
+	}
+
+	public class MyObserver implements Observer<String> {
+		String lastMessage = null;
+		Observable<String> lastSender = null;
+
+		public void notify(Observable<String> sender, String message) {
+			lastSender = sender;
+			lastMessage = message;
+		}
+	}
+	
+	public class SelvRemovingObserver implements Observer<String> {
+
+		public int called=0;
+		
+		public void notify(Observable<String> sender, String message) {
+			called++;
+			if (called > 1) {
+				fail("Did not remove itself");
+			}
+			sender.removeObserver(this);
+		}
+		
+	}
+
+}