http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/XMLTree.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/XMLTree.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/XMLTree.java
new file mode 100644
index 0000000..2d53218
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/XMLTree.java
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * 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.renderers.impl;
+
+import static java.util.prefs.Preferences.userNodeForPackage;
+import static javax.swing.JFileChooser.APPROVE_OPTION;
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION;
+import static org.jdom.output.Format.getPrettyFormat;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.Enumeration;
+import java.util.prefs.Preferences;
+
+import javax.swing.JFileChooser;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+
+import org.jdom.Attribute;
+import org.jdom.Content;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.Parent;
+import org.jdom.Text;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.XMLOutputter;
+
+/**
+ * An extension of the {@link JTree} class, constructed with a String of XML 
and
+ * used to display the XML structure as an interactive tree. Derived from <a
+ * 
href="http://www.devx.com/gethelpon/10MinuteSolution/16694/0/page/1";>original
+ * code by Kyle Gabhart</a> and then subsequently heavily rewritten to move to
+ * JDOM, and moved lots of the setup code to the renderer to cut down
+ * initialisation time. Added text node size limit as well. Displaying large
+ * gene sequences as base64 encoded text in a single node really, <i>really</i>
+ * hurts performance.
+ * 
+ * @author Kyle Gabhart
+ * @author Tom Oinn
+ * @author Kevin Glover
+ * @author Ian Dunlop
+ */
+@SuppressWarnings("serial")
+class XMLTree extends JTree {
+       private class XMLNode extends DefaultMutableTreeNode {
+               public XMLNode(Content userObject) {
+                       super(userObject);
+               }
+       }
+
+       int textSizeLimit = 1000;
+       final JFileChooser fc = new JFileChooser();
+       Element rootElement = null;
+
+       /**
+        * Build a new XMLTree from the supplied String containing XML.
+        * 
+        * @param text
+        * @throws IOException
+        * @throws JDOMException
+        */
+       public XMLTree(String text) throws IOException, JDOMException {
+               super();
+               Document document = new SAXBuilder(false).build(new 
StringReader(text));
+               init(document.getRootElement());
+               revalidate();
+       }
+
+       public String getText() {
+               if (rootElement == null)
+                       return "";
+               XMLOutputter xo = new XMLOutputter(getPrettyFormat());
+               return xo.outputString(rootElement);
+       }
+
+       public XMLTree(String text, boolean limit) throws IOException,
+                       JDOMException {
+               if (!limit)
+                       textSizeLimit = -1;
+               Document document = new SAXBuilder(false).build(new 
StringReader(text));
+               init(document.getRootElement());
+               revalidate();
+       }
+
+       public XMLTree(Document document) {
+               this(document.getRootElement());
+       }
+       
+       public XMLTree(Element element) {
+               super();
+               init(element);
+               revalidate();
+       }
+
+       private void init(Content content) {
+               rootElement = (Element) content;
+               /*
+                * Fix for platforms other than metal which can't otherwise 
cope with
+                * arbitrary size rows
+                */
+               setRowHeight(0);
+               getSelectionModel().setSelectionMode(SINGLE_TREE_SELECTION);
+               setShowsRootHandles(true);
+               setEditable(false);
+               setModel(new DefaultTreeModel(createTreeNode(content)));
+               setCellRenderer(new DefaultTreeCellRenderer() {
+                       @Override
+                       public Color getBackgroundNonSelectionColor() {
+                               return null;
+                       }
+
+                       @Override
+                       public Color getBackground() {
+                               return null;
+                       }
+
+                       @Override
+                       public Component getTreeCellRendererComponent(JTree 
tree,
+                                       Object value, boolean sel, boolean 
expanded, boolean leaf,
+                                       int row, boolean hasFocus) {
+                               super.getTreeCellRendererComponent(tree, value, 
sel, expanded,
+                                               leaf, row, hasFocus);
+                               setOpaque(false);
+                               if (value instanceof XMLNode) {
+                                       XMLNode node = (XMLNode) value;
+                                       if (node.getUserObject() instanceof 
Element)
+                                               renderElementNode((Element) 
node.getUserObject());
+                                       else if (node.getUserObject() 
instanceof Text)
+                                               renderTextNode((Text) 
node.getUserObject());
+                                       // TODO what about other node types?
+                               }
+                               setBackground(new Color(0, 0, 0, 0));
+                               return this;
+                       }
+
+                       private void renderElementNode(Element element) {
+                               // setIcon(TavernaIcons.xmlNodeIcon);
+                               StringBuilder nameBuffer = new 
StringBuilder("<html>")
+                                               
.append(element.getQualifiedName());
+                               /*
+                                * Bit of a quick and dirty hack here to try to 
ensure that the
+                                * element namespace is shown. There appears no 
way to get the
+                                * actual xmlns declarations that are part of 
an element through
+                                * jdom. Also, please note, there's no 
namespace handling at all
+                                * for attributes...
+                                */
+                               if (element.getParent() instanceof Element) {
+                                       Element parent = (Element) 
element.getParent();
+                                       if 
(parent.getNamespace(element.getNamespacePrefix()) == null)
+                                               nameBuffer
+                                                               .append(" <font 
color=\"purple\">xmlns:")
+                                                               
.append(element.getNamespacePrefix())
+                                                               
.append("</font>=\"<font color=\"green\">")
+                                                               
.append(element.getNamespaceURI() + "</font>\"");
+                               } else
+                                       nameBuffer.append(" <font 
color=\"purple\">xmlns:")
+                                                       
.append(element.getNamespacePrefix())
+                                                       
.append("</font>=\"<font color=\"green\">")
+                                                       
.append(element.getNamespaceURI() + "</font>\"");
+
+                               String sep = "";
+                               for (Object a : element.getAttributes()) {
+                                       Attribute attribute = (Attribute) a;
+                                       String name = 
attribute.getName().trim();
+                                       String value = 
attribute.getValue().trim();
+                                       if (value != null && value.length() > 
0) {
+                                               // TODO xml-quote name and value
+                                               nameBuffer.append(sep)
+                                                               .append(" <font 
color=\"purple\">")
+                                                               .append(name)
+                                                               
.append("</font>=\"<font color=\"green\">")
+                                                               
.append(value).append("</font>\"");
+                                               sep = ",";
+                                       }
+                               }
+
+                               nameBuffer.append("</html>");
+                               setText(nameBuffer.toString());
+                       }
+
+                       private void renderTextNode(Text text) {
+                               // setIcon(TavernaIcons.leafIcon);
+                               String name = text.getText();
+                               if (textSizeLimit > -1 && name.length() > 
textSizeLimit)
+                                       name = name.substring(0, textSizeLimit) 
+ "...";
+                               setText("<html><pre><font color=\"blue\">"
+                                               + name.replaceAll("<br>", 
"\n").replaceAll("<", "&lt;")
+                                               + "</font></pre></html>");
+                       }
+               });
+               setAllNodesExpanded();
+
+               // Add a listener to present the 'save as text' option
+               addMouseListener(new MouseAdapter() {
+                       @Override
+                       public void mousePressed(MouseEvent e) {
+                               if (e.isPopupTrigger())
+                                       doEvent(e);
+                       }
+
+                       @Override
+                       public void mouseReleased(MouseEvent e) {
+                               if (e.isPopupTrigger())
+                                       doEvent(e);
+                       }
+
+                       public void doEvent(MouseEvent e) {
+                               JPopupMenu menu = new JPopupMenu();
+                               JMenuItem item = new JMenuItem("Save as XML 
text");
+                               menu.add(item);
+                               item.addActionListener(new ActionListener() {
+                                       @Override
+                                       public void actionPerformed(ActionEvent 
ae) {
+                                               saveTreeXML();
+                                       }
+                               });
+                               menu.show(XMLTree.this, e.getX(), e.getY());
+                       }
+               });
+       }
+
+       private void saveTreeXML() {
+               try {
+                       Preferences prefs = userNodeForPackage(XMLTree.class);
+                       String curDir = prefs.get("currentDir",
+                                       System.getProperty("user.home"));
+                       fc.resetChoosableFileFilters();
+                       fc.setFileFilter(new ExtensionFileFilter(new String[] { 
"xml" }));
+                       fc.setCurrentDirectory(new File(curDir));
+                       if (fc.showSaveDialog(this) == APPROVE_OPTION) {
+                               prefs.put("currentDir", 
fc.getCurrentDirectory().toString());
+                               saveTreeXML(fc.getSelectedFile());
+                       }
+               } catch (Exception ex) {
+                       showMessageDialog(this, "Problem saving XML:\n" + 
ex.getMessage(),
+                                       "Error!", ERROR_MESSAGE);
+               }
+       }
+
+       private void saveTreeXML(File file) throws IOException {
+               try (PrintWriter out = new PrintWriter(new FileWriter(file))) {
+                       out.print(this.getText());
+               }
+       }
+
+       public void setAllNodesExpanded() {
+               synchronized (this.getModel()) {
+                       expandAll(this, new 
TreePath(this.getModel().getRoot()), true);
+               }
+       }
+
+       private void expandAll(JTree tree, TreePath parent, boolean expand) {
+               synchronized (this.getModel()) {
+                       /*
+                        * Traverse children
+                        * 
+                        * Ignores nodes who's userObject is a Processor type 
to avoid
+                        * overloading the UI with nodes at startup.
+                        */
+                       TreeNode node = (TreeNode) 
parent.getLastPathComponent();
+                       for (Enumeration<?> e = node.children(); 
e.hasMoreElements(); ) {
+                               TreeNode n = (TreeNode) e.nextElement();
+                               expandAll(tree, parent.pathByAddingChild(n), 
expand);
+                       }
+                       // Expansion or collapse must be done bottom-up
+                       if (expand)
+                               tree.expandPath(parent);
+                       else
+                               tree.collapsePath(parent);
+               }
+       }
+
+       public void setTextNodeSizeLimit(int sizeLimit) {
+               textSizeLimit = sizeLimit;
+       }
+
+       private XMLNode createTreeNode(Content content) {
+               XMLNode node = new XMLNode(content);
+               if (content instanceof Parent) {
+                       Parent parent = (Parent) content;
+                       for (Object child : parent.getContent()) {
+                               if (child instanceof Element)
+                                       node.add(createTreeNode((Content) 
child));
+                               else if (textSizeLimit != 0 && child instanceof 
Text) {
+                                       Text text = (Text) child;
+                                       if (!text.getTextNormalize().isEmpty())
+                                               node.add(createTreeNode(text));
+                               }
+                       }
+               }
+               return node;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.renderers.Renderer
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.renderers.Renderer
 
b/taverna-workbench-renderers-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.renderers.Renderer
new file mode 100644
index 0000000..044a396
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.renderers.Renderer
@@ -0,0 +1,7 @@
+net.sf.taverna.t2.renderers.impl.AdvancedImageRenderer
+net.sf.taverna.t2.renderers.impl.HexBinaryRenderer
+net.sf.taverna.t2.renderers.impl.TextRenderer
+net.sf.taverna.t2.renderers.impl.TextRtfRenderer
+net.sf.taverna.t2.renderers.impl.TextXMLRenderer
+
+

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/resources/META-INF/spring/renderers-impl-context-osgi.xml
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/resources/META-INF/spring/renderers-impl-context-osgi.xml
 
b/taverna-workbench-renderers-impl/src/main/resources/META-INF/spring/renderers-impl-context-osgi.xml
new file mode 100644
index 0000000..436426a
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/resources/META-INF/spring/renderers-impl-context-osgi.xml
@@ -0,0 +1,19 @@
+<?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="AdvancedImageRenderer" 
interface="net.sf.taverna.t2.renderers.Renderer" />
+       <service ref="HexBinaryRenderer" 
interface="net.sf.taverna.t2.renderers.Renderer" />
+       <service ref="TextRenderer" 
interface="net.sf.taverna.t2.renderers.Renderer" />
+       <service ref="TextRtfRenderer" 
interface="net.sf.taverna.t2.renderers.Renderer" />
+       <service ref="TextXMLRenderer" 
interface="net.sf.taverna.t2.renderers.Renderer" />
+
+       <service ref="RendererRegistry" 
interface="net.sf.taverna.t2.renderers.RendererRegistry" />
+
+       <list id="renderers" interface="net.sf.taverna.t2.renderers.Renderer" 
cardinality="0..N" />
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/resources/META-INF/spring/renderers-impl-context.xml
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/resources/META-INF/spring/renderers-impl-context.xml
 
b/taverna-workbench-renderers-impl/src/main/resources/META-INF/spring/renderers-impl-context.xml
new file mode 100644
index 0000000..a041c98
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/resources/META-INF/spring/renderers-impl-context.xml
@@ -0,0 +1,17 @@
+<?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="AdvancedImageRenderer" 
class="net.sf.taverna.t2.renderers.impl.AdvancedImageRenderer" />
+       <bean id="HexBinaryRenderer" 
class="net.sf.taverna.t2.renderers.impl.HexBinaryRenderer" />
+       <bean id="TextRenderer" 
class="net.sf.taverna.t2.renderers.impl.TextRenderer" />
+       <bean id="TextRtfRenderer" 
class="net.sf.taverna.t2.renderers.impl.TextRtfRenderer" />
+       <bean id="TextXMLRenderer" 
class="net.sf.taverna.t2.renderers.impl.TextXMLRenderer" />
+
+       <bean id="RendererRegistry" 
class="net.sf.taverna.t2.renderers.impl.RendererRegistryImpl">
+                       <property name="renderers" ref="renderers" />
+       </bean>
+
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/test/java/net/sf/taverna/t2/renderers/TestRendererSPI.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/test/java/net/sf/taverna/t2/renderers/TestRendererSPI.java
 
b/taverna-workbench-renderers-impl/src/test/java/net/sf/taverna/t2/renderers/TestRendererSPI.java
new file mode 100644
index 0000000..ece7cf5
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/test/java/net/sf/taverna/t2/renderers/TestRendererSPI.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * 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.renderers;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashSet;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+
+@SuppressWarnings("unused")
+public class TestRendererSPI {
+       
+       private static final String TEST_NS = "testNS";
+       
+       @Test
+       public void doNothing() {
+               //do nothing for the moment
+       }
+       
+//     @Test
+//     public void getAllRenderers() {
+//             RendererRegistry rendererRegistry = new RendererRegistry();
+//             assertEquals(rendererRegistry.getInstances().size(), 10);
+//     }
+//     
+//     @Test
+//     public void checkTextHtmlMimeType() throws EmptyListException, 
MalformedListException, UnsupportedObjectTypeException {
+//             String mimeType = "text/html";
+//             String html = "<HTML><HEAD></HEAD><BODY>hello</BODY></HTML>";
+//             EntityIdentifier entityIdentifier = facade.register(html, 
"utf-8");
+//             RendererRegistry rendererRegistry = new RendererRegistry();
+//             List<Renderer> renderersForMimeType = 
rendererRegistry.getRenderersForMimeType(facade, entityIdentifier, mimeType);
+//             assertEquals(renderersForMimeType.size(),2);
+//             
assertEquals(renderersForMimeType.get(0).getClass().getSimpleName(), 
"TextRenderer");
+//             
assertEquals(renderersForMimeType.get(1).getClass().getSimpleName(), 
"TextHtmlRenderer");
+//             assertTrue(renderersForMimeType.get(0).canHandle("text/html"));
+//     }
+//     
+//     @Test
+//     public void checkURLMimeType() throws EmptyListException, 
MalformedListException, UnsupportedObjectTypeException {
+//             String mimeType = "text/x-taverna-web-url.text";
+//             String url = "http://google.com";;
+//             EntityIdentifier entityIdentifier = facade.register(url);
+//             RendererRegistry rendererRegistry = new RendererRegistry();
+//             List<Renderer> renderersForMimeType = 
rendererRegistry.getRenderersForMimeType(facade, entityIdentifier, mimeType);
+//             assertEquals(renderersForMimeType.size(),2);
+//             
assertEquals(renderersForMimeType.get(0).getClass().getSimpleName(), 
"TextRenderer");
+//             
assertEquals(renderersForMimeType.get(1).getClass().getSimpleName(), 
"TextTavernaWebUrlRenderer");
+//             
assertTrue(renderersForMimeType.get(1).canHandle("text/x-taverna-web-url.text"));
+//     }
+//     
+//     @Test
+//     public void checkJMolMimeType() throws EmptyListException, 
MalformedListException, UnsupportedObjectTypeException {
+//             String mimeType ="chemical/x-pdb";
+//             String jmol = "jmol";
+//             EntityIdentifier entityIdentifier = facade.register(jmol);
+//             RendererRegistry rendererRegistry = new RendererRegistry();
+//             List<Renderer> renderersForMimeType = 
rendererRegistry.getRenderersForMimeType(facade, entityIdentifier, mimeType);
+//             assertEquals(renderersForMimeType.size(), 1);
+//             
assertEquals(renderersForMimeType.get(0).getClass().getSimpleName(), 
"JMolRenderer");
+//             
assertTrue(renderersForMimeType.get(0).canHandle("chemical/x-mdl-molfile"));
+//             
assertTrue(renderersForMimeType.get(0).canHandle("chemical/x-cml"));
+//     }
+//     
+//     @Test
+//     public void checkSeqVistaMimeType() throws EmptyListException, 
MalformedListException, UnsupportedObjectTypeException {
+//             String mimeType ="chemical/x-swissprot";
+//             String type = "seqvista";
+//             EntityIdentifier entityIdentifier = facade.register(type);
+//             RendererRegistry rendererRegistry = new RendererRegistry();
+//             List<Renderer> renderersForMimeType = 
rendererRegistry.getRenderersForMimeType(facade, entityIdentifier, mimeType);
+//             assertEquals(renderersForMimeType.size(), 1);
+//             
assertEquals(renderersForMimeType.get(0).getClass().getSimpleName(), 
"SeqVistaRenderer");
+//             
assertTrue(renderersForMimeType.get(0).canHandle("chemical/x-embl-dl-nucleotide"));
+//             
assertTrue(renderersForMimeType.get(0).canHandle("chemical/x-fasta"));
+//     }
+//     
+//     @Test
+//     public void checkSVGMimeType() throws EmptyListException, 
MalformedListException, UnsupportedObjectTypeException {
+//             String mimeType ="image/svg+xml";
+//             String type = "SVG";
+//             EntityIdentifier entityIdentifier = facade.register(type);
+//             RendererRegistry rendererRegistry = new RendererRegistry();
+//             List<Renderer> renderersForMimeType = 
rendererRegistry.getRenderersForMimeType(facade, entityIdentifier, mimeType);
+//             assertEquals(renderersForMimeType.size(), 2);
+//             
assertEquals(renderersForMimeType.get(1).getClass().getSimpleName(), 
"SVGRenderer");
+//     }
+//     
+//     @Test
+//     public void checkTextMimeType() throws EmptyListException, 
MalformedListException, UnsupportedObjectTypeException {
+//             String mimeType ="text/text";
+//             String type = "text";
+//             EntityIdentifier entityIdentifier = facade.register(type);
+//             RendererRegistry rendererRegistry = new RendererRegistry();
+//             List<Renderer> renderersForMimeType = 
rendererRegistry.getRenderersForMimeType(facade, entityIdentifier, mimeType);
+//             assertEquals(renderersForMimeType.size(), 1);
+//             
assertEquals(renderersForMimeType.get(0).getClass().getSimpleName(), 
"TextRenderer");
+//     }
+//     
+//     @Test
+//     public void checkTextRtfMimeType() throws EmptyListException, 
MalformedListException, UnsupportedObjectTypeException {
+//             String mimeType ="text/rtf";
+//             String type = "textRTF";
+//             EntityIdentifier entityIdentifier = facade.register(type);
+//             RendererRegistry rendererRegistry = new RendererRegistry();
+//             List<Renderer> renderersForMimeType = 
rendererRegistry.getRenderersForMimeType(facade, entityIdentifier, mimeType);
+//             assertEquals(renderersForMimeType.size(), 2);
+//             
assertEquals(renderersForMimeType.get(1).getClass().getSimpleName(), 
"TextRtfRenderer");
+//     }
+//     
+//     @Test
+//     public void checkTextXMLMimeType() throws EmptyListException, 
MalformedListException, UnsupportedObjectTypeException {
+//             String mimeType ="text/xml";
+//             String type = "textXML";
+//             EntityIdentifier entityIdentifier = facade.register(type);
+//             RendererRegistry rendererRegistry = new RendererRegistry();
+//             List<Renderer> renderersForMimeType = 
rendererRegistry.getRenderersForMimeType(facade, entityIdentifier, mimeType);
+//             assertEquals(renderersForMimeType.size(), 2);
+//             
assertEquals(renderersForMimeType.get(1).getClass().getSimpleName(), 
"TextXMLRenderer");
+//     }
+//     
+//     @Before
+//     public void setDataManager() {
+//             // dManager = new FileDataManager("testNS",
+//             // new HashSet<LocationalContext>(), new File("/tmp/fish"));
+//             dManager = new InMemoryDataManager(TEST_NS,
+//                             new HashSet<LocationalContext>());
+//             facade = new DataFacade(dManager);
+//     }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-report-impl/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-workbench-report-impl/pom.xml 
b/taverna-workbench-report-impl/pom.xml
new file mode 100644
index 0000000..c0e72bb
--- /dev/null
+++ b/taverna-workbench-report-impl/pom.xml
@@ -0,0 +1,40 @@
+<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/xsd/maven-4.0.0.xsd";>
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <artifactId>ui-impl</artifactId>
+               <groupId>net.sf.taverna.t2</groupId>
+               <version>2.0-SNAPSHOT</version>
+       </parent>
+       <groupId>net.sf.taverna.t2.ui-impl</groupId>
+       <artifactId>report-impl</artifactId>
+       <packaging>bundle</packaging>
+       <name>Reporting Implementation</name>
+       <dependencies>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.core</groupId>
+                       <artifactId>workflowmodel-api</artifactId>
+                       <version>${t2.core.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.ui-api</groupId>
+                       <artifactId>report-api</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.ui-api</groupId>
+                       <artifactId>file-api</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.ui-api</groupId>
+                       <artifactId>edits-api</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>uk.org.taverna.configuration</groupId>
+                       <artifactId>taverna-configuration-api</artifactId>
+                       <version>${taverna.configuration.version}</version>
+               </dependency>
+       </dependencies>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-report-impl/src/main/java/net/sf/taverna/t2/workbench/report/config/impl/ReportManagerConfigurationImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-report-impl/src/main/java/net/sf/taverna/t2/workbench/report/config/impl/ReportManagerConfigurationImpl.java
 
b/taverna-workbench-report-impl/src/main/java/net/sf/taverna/t2/workbench/report/config/impl/ReportManagerConfigurationImpl.java
new file mode 100644
index 0000000..b5986b5
--- /dev/null
+++ 
b/taverna-workbench-report-impl/src/main/java/net/sf/taverna/t2/workbench/report/config/impl/ReportManagerConfigurationImpl.java
@@ -0,0 +1,71 @@
+/**
+ *
+ */
+package net.sf.taverna.t2.workbench.report.config.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import uk.org.taverna.configuration.AbstractConfigurable;
+import uk.org.taverna.configuration.ConfigurationManager;
+
+import net.sf.taverna.t2.workbench.report.config.ReportManagerConfiguration;
+import net.sf.taverna.t2.workflowmodel.health.RemoteHealthChecker;
+
+/**
+ * @author alanrw
+ *
+ */
+public final class ReportManagerConfigurationImpl extends AbstractConfigurable 
implements ReportManagerConfiguration {
+
+       private static final int DEFAULT_TIMEOUT = 10;
+
+       private Map<String, String> defaultPropertyMap;
+
+       public ReportManagerConfigurationImpl(ConfigurationManager 
configurationManager) {
+               super(configurationManager);
+       }
+
+    public String getCategory() {
+        return "general";
+    }
+
+    public Map<String, String> getDefaultPropertyMap() {
+
+        if (defaultPropertyMap == null) {
+            defaultPropertyMap = new HashMap<String, String>();
+            defaultPropertyMap.put(TIMEOUT, Integer.toString(DEFAULT_TIMEOUT));
+            defaultPropertyMap.put(ON_EDIT, QUICK_CHECK);
+            defaultPropertyMap.put(ON_OPEN, QUICK_CHECK);
+            defaultPropertyMap.put(BEFORE_RUN, FULL_CHECK);
+            defaultPropertyMap.put(QUERY_BEFORE_RUN, ERRORS_OR_WARNINGS);
+            defaultPropertyMap.put(REPORT_EXPIRATION, 
Integer.toString(DEFAULT_REPORT_EXPIRATION));
+        }
+        return defaultPropertyMap;
+    }
+
+    public String getDisplayName() {
+        return "Validation report";
+    }
+
+    public String getFilePrefix() {
+        return "ReportManager";
+    }
+
+       public String getUUID() {
+               return "F86378E5-0EC4-4DE9-8A55-6098595413DC";
+       }
+
+       @Override
+       public void applySettings() {
+               
RemoteHealthChecker.setTimeoutInSeconds(Integer.parseInt(this.getProperty(TIMEOUT)));
+       }
+
+       public void setProperty(String key, String value) {
+               super.setProperty(key, value);
+               if (key.equals(TIMEOUT)) {
+                       applySettings();
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-report-impl/src/main/java/net/sf/taverna/t2/workbench/report/impl/ReportManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-report-impl/src/main/java/net/sf/taverna/t2/workbench/report/impl/ReportManagerImpl.java
 
b/taverna-workbench-report-impl/src/main/java/net/sf/taverna/t2/workbench/report/impl/ReportManagerImpl.java
new file mode 100644
index 0000000..825efee
--- /dev/null
+++ 
b/taverna-workbench-report-impl/src/main/java/net/sf/taverna/t2/workbench/report/impl/ReportManagerImpl.java
@@ -0,0 +1,564 @@
+/**
+ *
+ */
+package net.sf.taverna.t2.workbench.report.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+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 net.sf.taverna.t2.visit.HierarchyTraverser;
+import net.sf.taverna.t2.visit.VisitKind;
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+import net.sf.taverna.t2.visit.Visitor;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.edits.EditManager.AbstractDataflowEditEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.EditManagerEvent;
+import net.sf.taverna.t2.workbench.file.FileManager;
+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.SetCurrentDataflowEvent;
+import net.sf.taverna.t2.workbench.report.DataflowReportEvent;
+import net.sf.taverna.t2.workbench.report.FailedEntityKind;
+import net.sf.taverna.t2.workbench.report.IncompleteDataflowKind;
+import net.sf.taverna.t2.workbench.report.InvalidDataflowKind;
+import net.sf.taverna.t2.workbench.report.ReportManager;
+import net.sf.taverna.t2.workbench.report.ReportManagerEvent;
+import net.sf.taverna.t2.workbench.report.UnresolvedOutputKind;
+import net.sf.taverna.t2.workbench.report.UnsatisfiedEntityKind;
+import net.sf.taverna.t2.workbench.report.config.ReportManagerConfiguration;
+import net.sf.taverna.t2.workflowmodel.Dataflow;
+import net.sf.taverna.t2.workflowmodel.DataflowValidationReport;
+import net.sf.taverna.t2.workflowmodel.Processor;
+
+import org.apache.log4j.Logger;
+
+/**
+ * @author Alan R Williams
+ *
+ */
+public class ReportManagerImpl implements Observable<ReportManagerEvent>, 
ReportManager {
+
+       private static final long MAX_AGE_OUTDATED_MILLIS = 1 * 60 * 60 * 1000; 
// 1 hour
+       private static Logger logger = 
Logger.getLogger(ReportManagerImpl.class);
+
+       private ReportManagerConfiguration reportManagerConfiguration;
+       private HierarchyTraverser traverser = null;
+       private Map<Dataflow, Map<Object, Set<VisitReport>>> reportMap = 
Collections
+                       .synchronizedMap(new WeakHashMap<Dataflow, Map<Object, 
Set<VisitReport>>>());;
+       private Map<Dataflow, Map<Object, Status>> statusMap = Collections
+                       .synchronizedMap(new WeakHashMap<Dataflow, Map<Object, 
Status>>());
+       private Map<Dataflow, Map<Object, String>> summaryMap = Collections
+                       .synchronizedMap(new WeakHashMap<Dataflow, Map<Object, 
String>>());
+       private Map<Dataflow, Long> lastCheckedMap = Collections
+                       .synchronizedMap(new WeakHashMap<Dataflow, Long>());
+       private Map<Dataflow, Long> lastFullCheckedMap = Collections
+                       .synchronizedMap(new WeakHashMap<Dataflow, Long>());
+       private Map<Dataflow, String> lastFullCheckedDataflowIdMap = Collections
+                       .synchronizedMap(new WeakHashMap<Dataflow, String>());
+
+       private EditManager editManager;
+       private FileManager fileManager;
+
+       // private Set<Visitor<?>> visitors;
+
+       protected ReportManagerImpl(EditManager editManager, FileManager 
fileManager,
+                       Set<Visitor<?>> visitors, ReportManagerConfiguration 
reportManagerConfiguration)
+                       throws IllegalStateException {
+               this.editManager = editManager;
+               this.fileManager = fileManager;
+               this.reportManagerConfiguration = reportManagerConfiguration;
+               // this.visitors = visitors;
+               traverser = new HierarchyTraverser(visitors);
+               ReportManagerFileObserver fileObserver = new 
ReportManagerFileObserver();
+               fileManager.addObserver(fileObserver);
+               addEditObserver();
+               reportManagerConfiguration.applySettings();
+       }
+
+       private void addEditObserver() {
+               synchronized (editManager) {
+                       List<Observer<EditManagerEvent>> currentObservers = 
editManager.getObservers();
+                       for (Observer<EditManagerEvent> o : currentObservers) {
+                               editManager.removeObserver(o);
+                       }
+                       editManager.addObserver(new 
ReportManagerEditObserver());
+                       for (Observer<EditManagerEvent> o : currentObservers) {
+                               editManager.addObserver(o);
+                       }
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * 
net.sf.taverna.t2.workbench.report.ReportManagerI#updateReport(net.sf.taverna.t2.workflowmodel
+        * .Dataflow, boolean, boolean)
+        */
+       @Override
+       public void updateReport(Dataflow d, boolean includeTimeConsuming, 
boolean remember) {
+               Set<VisitReport> oldTimeConsumingReports = null;
+               long time = System.currentTimeMillis();
+               long expiration = Integer.parseInt(reportManagerConfiguration
+                               
.getProperty(ReportManagerConfiguration.REPORT_EXPIRATION)) * 60 * 1000;
+               if (remember && !includeTimeConsuming
+                               && ((expiration == 0) || ((time - 
getLastFullCheckedTime(d)) < expiration))) {
+                       oldTimeConsumingReports = getTimeConsumingReports(d);
+               }
+               Map<Object, Set<VisitReport>> reportsEntry = new 
HashMap<Object, Set<VisitReport>>();
+               Map<Object, Status> statusEntry = new HashMap<Object, Status>();
+               Map<Object, String> summaryEntry = new HashMap<Object, 
String>();
+               reportMap.put(d, reportsEntry);
+               statusMap.put(d, statusEntry);
+               summaryMap.put(d, summaryEntry);
+               validateDataflow(d, reportsEntry, statusEntry, summaryEntry);
+
+               Set<VisitReport> newReports = new HashSet<VisitReport>();
+               traverser.traverse(d, new ArrayList<Object>(), newReports, 
includeTimeConsuming);
+               for (VisitReport vr : newReports) {
+                       addReport(reportsEntry, statusEntry, summaryEntry, vr);
+               }
+               if (oldTimeConsumingReports != null) {
+                       for (VisitReport vr : oldTimeConsumingReports) {
+                               addReport(reportsEntry, statusEntry, 
summaryEntry, vr);
+                       }
+               }
+               time = System.currentTimeMillis();
+               lastCheckedMap.put(d, time);
+               if (includeTimeConsuming) {
+                       lastFullCheckedMap.put(d, time);
+                       lastFullCheckedDataflowIdMap.put(d, d.getIdentifier());
+               }
+               multiCaster.notify(new DataflowReportEvent(d));
+       }
+
+       private void updateObjectReportInternal(Dataflow d, Object o) {
+               Map<Object, Set<VisitReport>> reportsEntry = reportMap.get(d);
+               Map<Object, Status> statusEntry = statusMap.get(d);
+               Map<Object, String> summaryEntry = summaryMap.get(d);
+               if (reportsEntry == null) {
+                       logger.error("Attempt to update reports on an object in 
a dataflow that has not been checked");
+                       reportsEntry = new HashMap<Object, Set<VisitReport>>();
+                       statusEntry = new HashMap<Object, Status>();
+                       summaryEntry = new HashMap<Object, String>();
+                       reportMap.put(d, reportsEntry);
+                       statusMap.put(d, statusEntry);
+                       summaryMap.put(d, summaryEntry);
+               } else {
+                       reportsEntry.remove(o);
+                       statusEntry.remove(o);
+                       summaryEntry.remove(o);
+               }
+               // Assume o is directly inside d
+               List<Object> ancestry = new ArrayList<Object>();
+               ancestry.add(d);
+               Set<VisitReport> newReports = new HashSet<VisitReport>();
+               traverser.traverse(o, ancestry, newReports, true);
+               for (VisitReport vr : newReports) {
+                       addReport(reportsEntry, statusEntry, summaryEntry, vr);
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * 
net.sf.taverna.t2.workbench.report.ReportManagerI#updateObjectSetReport(net.sf.taverna.t2
+        * .workflowmodel.Dataflow, java.util.Set)
+        */
+       @Override
+       public void updateObjectSetReport(Dataflow d, Set<Object> objects) {
+               for (Object o : objects) {
+                       updateObjectReportInternal(d, o);
+               }
+               multiCaster.notify(new DataflowReportEvent(d));
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see 
net.sf.taverna.t2.workbench.report.ReportManagerI#updateObjectReport(net.sf.taverna.t2.
+        * workflowmodel.Dataflow, java.lang.Object)
+        */
+       @Override
+       public void updateObjectReport(Dataflow d, Object o) {
+               updateObjectReportInternal(d, o);
+               multiCaster.notify(new DataflowReportEvent(d));
+       }
+
+       private Set<VisitReport> getTimeConsumingReports(Dataflow d) {
+               Set<VisitReport> result = new HashSet<VisitReport>();
+               Map<Object, Set<VisitReport>> currentReports = getReports(d);
+               if (currentReports != null) {
+                       for (Object o : currentReports.keySet()) {
+                               for (VisitReport vr : currentReports.get(o)) {
+                                       if (vr.wasTimeConsuming()) {
+                                               result.add(vr);
+                                       }
+                               }
+                       }
+               }
+               return result;
+       }
+
+       private void removeReport(Dataflow d) {
+               reportMap.remove(d);
+               statusMap.remove(d);
+               summaryMap.remove(d);
+       }
+
+       private void addReport(Map<Object, Set<VisitReport>> reports, 
Map<Object, Status> statusEntry,
+                       Map<Object, String> summaryEntry, VisitReport 
newReport) {
+               if (newReport.getCheckTime() == 0) {
+                       newReport.setCheckTime(System.currentTimeMillis());
+               }
+               Object subject = newReport.getSubject();
+               Set<VisitReport> currentReports = reports.get(subject);
+               Status newReportStatus = newReport.getStatus();
+               if (currentReports == null) {
+                       currentReports = new HashSet<VisitReport>();
+                       reports.put(subject, currentReports);
+                       statusEntry.put(subject, newReportStatus);
+                       summaryEntry.put(subject, newReport.getMessage());
+               } else {
+                       Status currentStatus = statusEntry.get(subject);
+                       if (currentStatus.compareTo(newReportStatus) < 0) {
+                               statusEntry.put(subject, newReportStatus);
+                               summaryEntry.put(subject, 
newReport.getMessage());
+                       } else if (currentStatus.compareTo(newReportStatus) == 
0) {
+                               if (currentStatus.equals(Status.WARNING)) {
+                                       summaryEntry.put(subject, "Multiple 
warnings");
+                               } else if (currentStatus.equals(Status.SEVERE)) 
{
+                                       summaryEntry.put(subject, "Multiple 
errors");
+                               }
+                       }
+               }
+               currentReports.add(newReport);
+       }
+
+       private void validateDataflow(Dataflow d, Map<Object, Set<VisitReport>> 
reportsEntry,
+                       Map<Object, Status> statusEntry, Map<Object, String> 
summaryEntry) {
+               DataflowValidationReport validationReport = d.checkValidity();
+               if (validationReport.isWorkflowIncomplete()) {
+                       addReport(reportsEntry, statusEntry, summaryEntry, new 
VisitReport(
+                                       IncompleteDataflowKind.getInstance(), 
d, "Incomplete workflow",
+                                       
IncompleteDataflowKind.INCOMPLETE_DATAFLOW, VisitReport.Status.SEVERE));
+               } else if (!validationReport.isValid()) {
+                       addReport(reportsEntry, statusEntry, summaryEntry,
+                                       new 
VisitReport(InvalidDataflowKind.getInstance(), d, "Invalid workflow",
+                                                       
InvalidDataflowKind.INVALID_DATAFLOW, VisitReport.Status.SEVERE));
+               }
+               fillInReport(reportsEntry, statusEntry, summaryEntry, 
validationReport);
+       }
+
+       private void fillInReport(Map<Object, Set<VisitReport>> reportsEntry,
+                       Map<Object, Status> statusEntry, Map<Object, String> 
summaryEntry,
+                       DataflowValidationReport report) {
+               for (Object o : report.getUnresolvedOutputs()) {
+                       addReport(reportsEntry, statusEntry, summaryEntry,
+                                       new 
VisitReport(UnresolvedOutputKind.getInstance(), o,
+                                                       "Invalid workflow 
output", UnresolvedOutputKind.OUTPUT,
+                                                       
VisitReport.Status.SEVERE));
+               }
+               for (Object o : report.getFailedEntities()) {
+                       addReport(reportsEntry, statusEntry, summaryEntry,
+                                       new 
VisitReport(FailedEntityKind.getInstance(), o,
+                                                       "Mismatch of input list 
depths", FailedEntityKind.FAILED_ENTITY,
+                                                       
VisitReport.Status.SEVERE));
+               }
+               for (Object o : report.getUnsatisfiedEntities()) {
+                       addReport(reportsEntry, statusEntry, summaryEntry, new 
VisitReport(
+                                       UnsatisfiedEntityKind.getInstance(), o, 
"Unknown prior list depth",
+                                       
UnsatisfiedEntityKind.UNSATISFIED_ENTITY, VisitReport.Status.SEVERE));
+               }
+               // for (DataflowValidationReport subReport : 
report.getInvalidDataflows().values()) {
+               // fillInReport(descriptionMap, subReport);
+               // }
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * 
net.sf.taverna.t2.workbench.report.ReportManagerI#getReports(net.sf.taverna.t2.workflowmodel
+        * .Dataflow, java.lang.Object)
+        */
+       @Override
+       public Set<VisitReport> getReports(Dataflow d, Object object) {
+               Set<VisitReport> result = new HashSet<VisitReport>();
+               Map<Object, Set<VisitReport>> objectReports = reportMap.get(d);
+               if (objectReports != null) {
+                       Set<Object> objects = new HashSet<Object>();
+                       objects.add(object);
+                       if (object instanceof Processor) {
+                               objects.addAll(((Processor) 
object).getActivityList());
+                       }
+                       for (Object o : objects) {
+                               if (objectReports.containsKey(o)) {
+                                       result.addAll(objectReports.get(o));
+                               }
+                       }
+               }
+               return result;
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * 
net.sf.taverna.t2.workbench.report.ReportManagerI#getReports(net.sf.taverna.t2.workflowmodel
+        * .Dataflow)
+        */
+       @Override
+       public Map<Object, Set<VisitReport>> getReports(Dataflow d) {
+               return reportMap.get(d);
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see 
net.sf.taverna.t2.workbench.report.ReportManagerI#isStructurallySound(net.sf.taverna.t2.
+        * workflowmodel.Dataflow)
+        */
+       @Override
+       public boolean isStructurallySound(Dataflow d) {
+               Map<Object, Set<VisitReport>> objectReports = reportMap.get(d);
+               if (objectReports == null) {
+                       return false;
+               }
+               for (Set<VisitReport> visitReportSet : objectReports.values()) {
+                       for (VisitReport vr : visitReportSet) {
+                               if (vr.getStatus().equals(Status.SEVERE)) {
+                                       VisitKind vk = vr.getKind();
+                                       if ((vk instanceof 
IncompleteDataflowKind)
+                                                       || (vk instanceof 
InvalidDataflowKind)
+                                                       || (vk instanceof 
UnresolvedOutputKind)
+                                                       || (vk instanceof 
FailedEntityKind)
+                                                       || (vk instanceof 
UnsatisfiedEntityKind)) {
+                                               return false;
+                                       }
+                               }
+                       }
+               }
+               return true;
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * 
net.sf.taverna.t2.workbench.report.ReportManagerI#getStatus(net.sf.taverna.t2.workflowmodel
+        * .Dataflow)
+        */
+       @Override
+       public Status getStatus(Dataflow d) {
+               Map<Object, Set<VisitReport>> objectReports = reportMap.get(d);
+               if (objectReports == null) {
+                       return Status.OK;
+               }
+               Status currentStatus = Status.OK;
+               for (Set<VisitReport> visitReportSet : objectReports.values()) {
+                       for (VisitReport vr : visitReportSet) {
+                               Status status = vr.getStatus();
+                               if (status.compareTo(currentStatus) > 0) {
+                                       currentStatus = status;
+                               }
+                               if (currentStatus.equals(Status.SEVERE)) {
+                                       return currentStatus;
+                               }
+                       }
+               }
+               return currentStatus;
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * 
net.sf.taverna.t2.workbench.report.ReportManagerI#getStatus(net.sf.taverna.t2.workflowmodel
+        * .Dataflow, java.lang.Object)
+        */
+       @Override
+       public Status getStatus(Dataflow d, Object object) {
+               Status result = Status.OK;
+               Map<Object, Status> statusEntry = statusMap.get(d);
+               if (statusEntry != null) {
+                       Status value = statusEntry.get(object);
+                       if (value != null) {
+                               result = value;
+                       }
+               }
+               return result;
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see 
net.sf.taverna.t2.workbench.report.ReportManagerI#getSummaryMessage(net.sf.taverna.t2.
+        * workflowmodel.Dataflow, java.lang.Object)
+        */
+       @Override
+       public String getSummaryMessage(Dataflow d, Object object) {
+               String result = null;
+               if (!getStatus(d, object).equals(Status.OK)) {
+                       Map<Object, String> summaryEntry = summaryMap.get(d);
+                       if (summaryEntry != null) {
+                               result = summaryEntry.get(object);
+                       }
+               }
+               return result;
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see 
net.sf.taverna.t2.workbench.report.ReportManagerI#getLastCheckedTime(net.sf.taverna.t2.
+        * workflowmodel.Dataflow)
+        */
+       @Override
+       public long getLastCheckedTime(Dataflow d) {
+               Long l = lastCheckedMap.get(d);
+               if (l == null) {
+                       return 0;
+               } else {
+                       return l.longValue();
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * 
net.sf.taverna.t2.workbench.report.ReportManagerI#getLastFullCheckedTime(net.sf.taverna.t2
+        * .workflowmodel.Dataflow)
+        */
+       @Override
+       public long getLastFullCheckedTime(Dataflow d) {
+               Long l = lastFullCheckedMap.get(d);
+               if (l == null) {
+                       return 0;
+               } else {
+                       return l.longValue();
+               }
+       }
+
+       /**
+        * @author alanrw
+        *
+        */
+       public class ReportManagerFileObserver implements 
Observer<FileManagerEvent> {
+
+               public void notify(Observable<FileManagerEvent> sender, 
FileManagerEvent message)
+                               throws Exception {
+                       String onOpen = reportManagerConfiguration.getProperty(
+                                       ReportManagerConfiguration.ON_OPEN);
+                       if (message instanceof ClosedDataflowEvent) {
+                               
ReportManagerImpl.this.removeReport(((ClosedDataflowEvent) 
message).getDataflow());
+                       } else if (message instanceof SetCurrentDataflowEvent) {
+                               Dataflow dataflow = ((SetCurrentDataflowEvent) 
message).getDataflow();
+                               if (!reportMap.containsKey(dataflow)) {
+                                       if 
(!onOpen.equals(ReportManagerConfiguration.NO_CHECK)) {
+                                               updateReport(dataflow,
+                                                               
onOpen.equals(ReportManagerConfiguration.FULL_CHECK), true);
+                                       } else {
+                                               
ReportManagerImpl.this.multiCaster
+                                                               .notify(new 
DataflowReportEvent(dataflow));
+                                       }
+                               } else {
+                                       
ReportManagerImpl.this.multiCaster.notify(new DataflowReportEvent(dataflow));
+                               }
+                       }
+               }
+
+       }
+
+       private MultiCaster<ReportManagerEvent> multiCaster = new 
MultiCaster<ReportManagerEvent>(this);
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * 
net.sf.taverna.t2.workbench.report.ReportManagerI#addObserver(net.sf.taverna.t2.lang.observer
+        * .Observer)
+        */
+       @Override
+       public void addObserver(Observer<ReportManagerEvent> observer) {
+               multiCaster.addObserver(observer);
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see net.sf.taverna.t2.workbench.report.ReportManagerI#getObservers()
+        */
+       @Override
+       public List<Observer<ReportManagerEvent>> getObservers() {
+               return multiCaster.getObservers();
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * 
net.sf.taverna.t2.workbench.report.ReportManagerI#removeObserver(net.sf.taverna.t2.lang.observer
+        * .Observer)
+        */
+       @Override
+       public void removeObserver(Observer<ReportManagerEvent> observer) {
+               multiCaster.removeObserver(observer);
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see 
net.sf.taverna.t2.workbench.report.ReportManagerI#isReportOutdated(net.sf.taverna.t2.
+        * workflowmodel.Dataflow)
+        */
+       @Override
+       public boolean isReportOutdated(Dataflow dataflow) {
+               String lastCheckedId = 
lastFullCheckedDataflowIdMap.get(dataflow);
+               Long lastCheck = lastFullCheckedMap.get(dataflow);
+               if (lastCheckedId == null || lastCheck == null) {
+                       // Unknown, so outdated
+                       return true;
+               }
+               if (!lastCheckedId.equals(dataflow.getIdentifier())) {
+                       // Workflow changed, so outdaeted
+                       return true;
+               }
+               long now = System.currentTimeMillis();
+               long age = now - lastCheck;
+               // Outdated if it is older than the maximum
+               return age > MAX_AGE_OUTDATED_MILLIS;
+       }
+
+       public class ReportManagerEditObserver implements 
Observer<EditManagerEvent> {
+               public void notify(Observable<EditManagerEvent> sender, 
EditManagerEvent message)
+                               throws Exception {
+                       String onEdit = reportManagerConfiguration
+                                       
.getProperty(ReportManagerConfiguration.ON_EDIT);
+                       Dataflow dataflow = fileManager.getCurrentDataflow();
+                       if (message instanceof AbstractDataflowEditEvent) {
+                               AbstractDataflowEditEvent adee = 
(AbstractDataflowEditEvent) message;
+                               if (adee.getDataFlow().equals(dataflow)) {
+                                       if 
(onEdit.equals(ReportManagerConfiguration.QUICK_CHECK)) {
+                                               updateReport(dataflow, false, 
true);
+                                       } else if 
(onEdit.equals(ReportManagerConfiguration.FULL_CHECK)) {
+                                               updateReport(dataflow, true, 
true);
+                                       }
+                               }
+                       }
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-report-impl/src/main/resources/META-INF/spring/report-impl-context-osgi.xml
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-report-impl/src/main/resources/META-INF/spring/report-impl-context-osgi.xml
 
b/taverna-workbench-report-impl/src/main/resources/META-INF/spring/report-impl-context-osgi.xml
new file mode 100644
index 0000000..31c7432
--- /dev/null
+++ 
b/taverna-workbench-report-impl/src/main/resources/META-INF/spring/report-impl-context-osgi.xml
@@ -0,0 +1,23 @@
+<?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="ProcessorFragilityChecker" 
interface="net.sf.taverna.t2.visit.fragility.FragilityChecker" /> -->
+
+       <!-- <service ref="FragilityCheck" 
interface="net.sf.taverna.t2.visit.VisitKind" /> -->
+
+       <service ref="ReportManagerImpl" 
interface="net.sf.taverna.t2.workbench.report.ReportManager" />
+
+       <service ref="ReportManagerConfiguration" 
interface="net.sf.taverna.t2.workbench.report.config.ReportManagerConfiguration"
 />
+
+       <reference id="editManager" 
interface="net.sf.taverna.t2.workbench.edits.EditManager" />
+       <reference id="fileManager" 
interface="net.sf.taverna.t2.workbench.file.FileManager" />
+       <reference id="configurationManager" 
interface="uk.org.taverna.configuration.ConfigurationManager" />
+
+       <set id="visitors" interface="net.sf.taverna.t2.visit.Visitor" 
cardinality="0..N" />
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-report-impl/src/main/resources/META-INF/spring/report-impl-context.xml
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-report-impl/src/main/resources/META-INF/spring/report-impl-context.xml
 
b/taverna-workbench-report-impl/src/main/resources/META-INF/spring/report-impl-context.xml
new file mode 100644
index 0000000..966d50d
--- /dev/null
+++ 
b/taverna-workbench-report-impl/src/main/resources/META-INF/spring/report-impl-context.xml
@@ -0,0 +1,21 @@
+<?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="ProcessorFragilityChecker" 
class="net.sf.taverna.t2.visit.fragility.impl.ProcessorFragilityChecker" /> -->
+
+       <!-- <bean id="FragilityCheck" 
class="net.sf.taverna.t2.visit.fragility.impl.FragilityCheck" /> -->
+
+       <bean id="ReportManagerImpl" 
class="net.sf.taverna.t2.workbench.report.impl.ReportManagerImpl">
+       <constructor-arg ref="editManager" />
+       <constructor-arg ref="fileManager" />
+       <constructor-arg ref="visitors" />
+               <constructor-arg ref="ReportManagerConfiguration"/>
+       </bean>
+
+       <bean id="ReportManagerConfiguration" 
class="net.sf.taverna.t2.workbench.report.config.impl.ReportManagerConfigurationImpl">
+               <constructor-arg ref="configurationManager"/>
+       </bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-selection-impl/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-workbench-selection-impl/pom.xml 
b/taverna-workbench-selection-impl/pom.xml
new file mode 100644
index 0000000..cb6cbcb
--- /dev/null
+++ b/taverna-workbench-selection-impl/pom.xml
@@ -0,0 +1,35 @@
+<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/xsd/maven-4.0.0.xsd";>
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>net.sf.taverna.t2</groupId>
+               <artifactId>ui-impl</artifactId>
+               <version>2.0-SNAPSHOT</version>
+       </parent>
+       <groupId>net.sf.taverna.t2.ui-impl</groupId>
+       <artifactId>selection-impl</artifactId>
+       <packaging>bundle</packaging>
+       <name>Selection Implementation</name>
+       <dependencies>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.ui-api</groupId>
+                       <artifactId>edits-api</artifactId>
+                       <version>${t2.ui.api.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.ui-api</groupId>
+                       <artifactId>file-api</artifactId>
+                       <version>${t2.ui.api.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.ui-api</groupId>
+                       <artifactId>selection-api</artifactId>
+                       <version>${t2.ui.api.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.osgi</groupId>
+                       <artifactId>org.osgi.compendium</artifactId>
+                       <version>${osgi.core.version}</version>
+               </dependency>
+       </dependencies>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-selection-impl/src/main/java/net/sf/taverna/t2/workbench/selection/impl/DataflowSelectionModelImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-selection-impl/src/main/java/net/sf/taverna/t2/workbench/selection/impl/DataflowSelectionModelImpl.java
 
b/taverna-workbench-selection-impl/src/main/java/net/sf/taverna/t2/workbench/selection/impl/DataflowSelectionModelImpl.java
new file mode 100644
index 0000000..09d6f71
--- /dev/null
+++ 
b/taverna-workbench-selection-impl/src/main/java/net/sf/taverna/t2/workbench/selection/impl/DataflowSelectionModelImpl.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.selection.impl;
+
+import static 
net.sf.taverna.t2.workbench.selection.events.DataflowSelectionMessage.Type.ADDED;
+import static 
net.sf.taverna.t2.workbench.selection.events.DataflowSelectionMessage.Type.REMOVED;
+
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import net.sf.taverna.t2.lang.observer.MultiCaster;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.workbench.selection.DataflowSelectionModel;
+import net.sf.taverna.t2.workbench.selection.events.DataflowSelectionMessage;
+
+/**
+ * Default implementation of a <code>DataflowSelectionModel</code>.
+ *
+ * @author David Withers
+ */
+public class DataflowSelectionModelImpl implements DataflowSelectionModel {
+       private MultiCaster<DataflowSelectionMessage> multiCaster;
+       private Set<Object> selection = new TreeSet<>(new Comparator<Object>() {
+               @Override
+               public int compare(Object o1, Object o2) {
+                       if (o1 == o2)
+                               return 0;
+                       return o1.hashCode() - o2.hashCode();
+               }
+       });
+
+       /**
+        * Constructs a new instance of DataflowSelectionModelImpl.
+        */
+       public DataflowSelectionModelImpl() {
+               multiCaster = new MultiCaster<>(this);
+       }
+
+       @Override
+       public void addSelection(Object element) {
+               if (element != null) {
+                       if (!selection.contains(element)) {
+                               clearSelection();
+                               selection.add(element);
+                               multiCaster.notify(new 
DataflowSelectionMessage(ADDED, element));
+                       }
+               }
+       }
+
+       @Override
+       public void clearSelection() {
+               for (Object element : new HashSet<>(selection))
+                       removeSelection(element);
+       }
+
+       @Override
+       public Set<Object> getSelection() {
+               return new HashSet<>(selection);
+       }
+
+       @Override
+       public void removeSelection(Object element) {
+               if (element != null && selection.remove(element))
+                       multiCaster.notify(new 
DataflowSelectionMessage(REMOVED, element));
+       }
+
+       @Override
+       public void setSelection(Set<Object> elements) {
+               if (elements == null) {
+                       clearSelection();
+                       return;
+               }
+               Set<Object> newSelection = new HashSet<>(elements);
+               for (Object element : new HashSet<>(selection))
+                       if (!newSelection.remove(element))
+                               removeSelection(element);
+               for (Object element : newSelection)
+                       addSelection(element);
+       }
+
+       @Override
+       public void addObserver(Observer<DataflowSelectionMessage> observer) {
+               multiCaster.addObserver(observer);
+       }
+
+       @Override
+       public List<Observer<DataflowSelectionMessage>> getObservers() {
+               return multiCaster.getObservers();
+       }
+
+       @Override
+       public void removeObserver(Observer<DataflowSelectionMessage> observer) 
{
+               multiCaster.removeObserver(observer);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-selection-impl/src/main/java/net/sf/taverna/t2/workbench/selection/impl/SelectionManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-selection-impl/src/main/java/net/sf/taverna/t2/workbench/selection/impl/SelectionManagerImpl.java
 
b/taverna-workbench-selection-impl/src/main/java/net/sf/taverna/t2/workbench/selection/impl/SelectionManagerImpl.java
new file mode 100644
index 0000000..2e86f1a
--- /dev/null
+++ 
b/taverna-workbench-selection-impl/src/main/java/net/sf/taverna/t2/workbench/selection/impl/SelectionManagerImpl.java
@@ -0,0 +1,367 @@
+/*******************************************************************************
+ * 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.selection.impl;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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 net.sf.taverna.t2.workbench.edits.CompoundEdit;
+import net.sf.taverna.t2.workbench.edits.Edit;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.edits.EditManager.DataFlowUndoEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.EditManagerEvent;
+import net.sf.taverna.t2.workbench.file.FileManager;
+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.SetCurrentDataflowEvent;
+import net.sf.taverna.t2.workbench.selection.DataflowSelectionModel;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+import net.sf.taverna.t2.workbench.selection.events.DataflowSelectionMessage;
+import net.sf.taverna.t2.workbench.selection.events.PerspectiveSelectionEvent;
+import net.sf.taverna.t2.workbench.selection.events.ProfileSelectionEvent;
+import net.sf.taverna.t2.workbench.selection.events.SelectionManagerEvent;
+import 
net.sf.taverna.t2.workbench.selection.events.WorkflowBundleSelectionEvent;
+import net.sf.taverna.t2.workbench.selection.events.WorkflowRunSelectionEvent;
+import net.sf.taverna.t2.workbench.selection.events.WorkflowSelectionEvent;
+import net.sf.taverna.t2.workbench.ui.zaria.PerspectiveSPI;
+import net.sf.taverna.t2.workflow.edits.AddChildEdit;
+
+import org.apache.log4j.Logger;
+
+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.port.InputWorkflowPort;
+import uk.org.taverna.scufl2.api.port.OutputWorkflowPort;
+import uk.org.taverna.scufl2.api.profiles.Profile;
+
+/**
+ * Implementation of the {@link SelectionManager}.
+ *
+ * @author David Withers
+ */
+public class SelectionManagerImpl implements SelectionManager {
+       private static final String RESULTS_PERSPECTIVE_ID = 
"net.sf.taverna.t2.ui.perspectives.results.ResultsPerspective";
+
+       private static final String DESIGN_PERSPECTIVE_ID = 
"net.sf.taverna.t2.ui.perspectives.design.DesignPerspective";
+
+       private static final Logger logger = 
Logger.getLogger(SelectionManagerImpl.class);
+
+       private WorkflowBundle selectedWorkflowBundle;
+       private Map<WorkflowBundle, DataflowSelectionModel> 
workflowSelectionModels = new IdentityHashMap<>();
+       private Map<WorkflowBundle, Workflow> selectedWorkflows = new 
IdentityHashMap<>();
+       private Map<WorkflowBundle, Profile> selectedProfiles = new 
IdentityHashMap<>();
+       private String selectedWorkflowRun;
+       private Map<String, DataflowSelectionModel> workflowRunSelectionModels 
= new HashMap<>();
+       private PerspectiveSPI selectedPerspective;
+       private MultiCaster<SelectionManagerEvent> observers = new 
MultiCaster<>(this);
+       private FileManager fileManager;
+       private List<PerspectiveSPI> perspectives;
+
+       @Override
+       public DataflowSelectionModel getDataflowSelectionModel(WorkflowBundle 
dataflow) {
+               DataflowSelectionModel selectionModel;
+               synchronized (workflowSelectionModels) {
+                       selectionModel = workflowSelectionModels.get(dataflow);
+                       if (selectionModel == null) {
+                               selectionModel = new 
DataflowSelectionModelImpl();
+                               workflowSelectionModels.put(dataflow, 
selectionModel);
+                       }
+               }
+               return selectionModel;
+       }
+
+       @Override
+       public WorkflowBundle getSelectedWorkflowBundle() {
+               return selectedWorkflowBundle;
+       }
+
+       @Override
+       public void setSelectedWorkflowBundle(WorkflowBundle workflowBundle) {
+               setSelectedWorkflowBundle(workflowBundle, true);
+       }
+
+       private void setSelectedWorkflowBundle(WorkflowBundle workflowBundle, 
boolean notifyFileManager) {
+               if (workflowBundle == null || workflowBundle == 
selectedWorkflowBundle)
+                       return;
+               if (notifyFileManager) {
+                       fileManager.setCurrentDataflow(workflowBundle);
+                       return;
+               }
+               if (selectedWorkflows.get(workflowBundle) == null)
+                       selectedWorkflows.put(workflowBundle,
+                                       workflowBundle.getMainWorkflow());
+               if (selectedProfiles.get(workflowBundle) == null)
+                       selectedProfiles.put(workflowBundle,
+                                       workflowBundle.getMainProfile());
+               SelectionManagerEvent selectionManagerEvent = new 
WorkflowBundleSelectionEvent(
+                               selectedWorkflowBundle, workflowBundle);
+               selectedWorkflowBundle = workflowBundle;
+               notify(selectionManagerEvent);
+               selectDesignPerspective();
+       }
+
+       private void removeWorkflowBundle(WorkflowBundle dataflow) {
+               synchronized (workflowSelectionModels) {
+                       DataflowSelectionModel selectionModel = 
workflowSelectionModels.remove(dataflow);
+                       if (selectionModel != null)
+                               for (Observer<DataflowSelectionMessage> 
observer : selectionModel.getObservers())
+                                       selectionModel.removeObserver(observer);
+               }
+               synchronized (selectedWorkflows) {
+                       selectedWorkflows.remove(dataflow);
+               }
+               synchronized (selectedProfiles) {
+                       selectedProfiles.remove(dataflow);
+               }
+       }
+
+       @Override
+       public Workflow getSelectedWorkflow() {
+               return selectedWorkflows.get(selectedWorkflowBundle);
+       }
+
+       @Override
+       public void setSelectedWorkflow(Workflow workflow) {
+               if (workflow != null) {
+                       Workflow selectedWorkflow = 
selectedWorkflows.get(workflow
+                                       .getParent());
+                       if (selectedWorkflow != workflow) {
+                               SelectionManagerEvent selectionManagerEvent = 
new WorkflowSelectionEvent(
+                                               selectedWorkflow, workflow);
+                               selectedWorkflows.put(workflow.getParent(), 
workflow);
+                               notify(selectionManagerEvent);
+                       }
+               }
+       }
+
+       @Override
+       public Profile getSelectedProfile() {
+               return selectedProfiles.get(selectedWorkflowBundle);
+       }
+
+       @Override
+       public void setSelectedProfile(Profile profile) {
+               if (profile != null) {
+                       Profile selectedProfile = 
selectedProfiles.get(profile.getParent());
+                       if (selectedProfile != profile) {
+                               SelectionManagerEvent selectionManagerEvent = 
new ProfileSelectionEvent(
+                                               selectedProfile, profile);
+                               selectedProfiles.put(profile.getParent(), 
profile);
+                               notify(selectionManagerEvent);
+                       }
+               }
+       }
+
+       @Override
+       public String getSelectedWorkflowRun() {
+               return selectedWorkflowRun;
+       }
+
+       @Override
+       public void setSelectedWorkflowRun(String workflowRun) {
+               if ((selectedWorkflowRun == null && workflowRun != null)
+                               || !selectedWorkflowRun.equals(workflowRun)) {
+                       SelectionManagerEvent selectionManagerEvent = new 
WorkflowRunSelectionEvent(
+                                       selectedWorkflowRun, workflowRun);
+                       selectedWorkflowRun = workflowRun;
+                       notify(selectionManagerEvent);
+                       selectResultsPerspective();
+               }
+       }
+
+       @Override
+       public DataflowSelectionModel getWorkflowRunSelectionModel(String 
workflowRun) {
+               DataflowSelectionModel selectionModel;
+               synchronized (workflowRunSelectionModels) {
+                       selectionModel = 
workflowRunSelectionModels.get(workflowRun);
+                       if (selectionModel == null) {
+                               selectionModel = new 
DataflowSelectionModelImpl();
+                               workflowRunSelectionModels.put(workflowRun, 
selectionModel);
+                       }
+               }
+               return selectionModel;
+       }
+
+       @SuppressWarnings("unused")
+       private void removeWorkflowRun(String workflowRun) {
+               synchronized (workflowRunSelectionModels) {
+                       DataflowSelectionModel selectionModel = 
workflowRunSelectionModels
+                                       .remove(workflowRun);
+                       if (selectionModel != null)
+                               for (Observer<DataflowSelectionMessage> 
observer : selectionModel
+                                               .getObservers())
+                                       selectionModel.removeObserver(observer);
+               }
+       }
+
+       @Override
+       public PerspectiveSPI getSelectedPerspective() {
+               return selectedPerspective;
+       }
+
+       @Override
+       public void setSelectedPerspective(PerspectiveSPI perspective) {
+               if (selectedPerspective != perspective) {
+                       SelectionManagerEvent selectionManagerEvent = new 
PerspectiveSelectionEvent(
+                                       selectedPerspective, perspective);
+                       selectedPerspective = perspective;
+                       notify(selectionManagerEvent);
+               }
+       }
+
+       private void selectDesignPerspective() {
+               for (PerspectiveSPI perspective : perspectives)
+                       if (DESIGN_PERSPECTIVE_ID.equals(perspective.getID())) {
+                               setSelectedPerspective(perspective);
+                               break;
+                       }
+       }
+
+       private void selectResultsPerspective() {
+               for (PerspectiveSPI perspective : perspectives)
+                       if (RESULTS_PERSPECTIVE_ID.equals(perspective.getID())) 
{
+                               setSelectedPerspective(perspective);
+                               break;
+                       }
+       }
+
+       @Override
+       public void addObserver(Observer<SelectionManagerEvent> observer) {
+               synchronized (observers) {
+                       WorkflowBundle selectedWorkflowBundle = 
getSelectedWorkflowBundle();
+                       Workflow selectedWorkflow = getSelectedWorkflow();
+                       Profile selectedProfile = getSelectedProfile();
+                       String selectedWorkflowRun = getSelectedWorkflowRun();
+                       PerspectiveSPI selectedPerspective = 
getSelectedPerspective();
+                       try {
+                               if (selectedWorkflowBundle != null)
+                                       observer.notify(this, new 
WorkflowBundleSelectionEvent(
+                                                       null, 
selectedWorkflowBundle));
+                               if (selectedWorkflow != null)
+                                       observer.notify(this, new 
WorkflowSelectionEvent(null,
+                                                       selectedWorkflow));
+                               if (selectedProfile != null)
+                                       observer.notify(this, new 
ProfileSelectionEvent(null,
+                                                       selectedProfile));
+                               if (selectedWorkflowRun != null)
+                                       observer.notify(this, new 
WorkflowRunSelectionEvent(null,
+                                                       selectedWorkflowRun));
+                               if (selectedPerspective != null)
+                                       observer.notify(this, new 
PerspectiveSelectionEvent(null,
+                                                       selectedPerspective));
+                       } catch (Exception e) {
+                               logger.warn("Could not notify " + observer, e);
+                       }
+                       observers.addObserver(observer);
+               }
+       }
+
+       @Override
+       public void removeObserver(Observer<SelectionManagerEvent> observer) {
+               observers.removeObserver(observer);
+       }
+
+       @Override
+       public List<Observer<SelectionManagerEvent>> getObservers() {
+               return observers.getObservers();
+       }
+
+       public void setFileManager(FileManager fileManager) {
+               this.fileManager = fileManager;
+               setSelectedWorkflowBundle(fileManager.getCurrentDataflow());
+               fileManager.addObserver(new FileManagerObserver());
+       }
+
+       public void setEditManager(EditManager editManager) {
+               editManager.addObserver(new EditManagerObserver());
+       }
+
+       public void setPerspectives(List<PerspectiveSPI> perspectives) {
+               this.perspectives = perspectives;
+       }
+
+       public class FileManagerObserver implements Observer<FileManagerEvent> {
+               @Override
+               public void notify(Observable<FileManagerEvent> sender,
+                               FileManagerEvent message) throws Exception {
+                       if (message instanceof ClosedDataflowEvent) {
+                               WorkflowBundle workflowBundle = 
((ClosedDataflowEvent) message).getDataflow();
+                               removeWorkflowBundle(workflowBundle);
+                       } else if (message instanceof OpenedDataflowEvent) {
+                               WorkflowBundle workflowBundle = 
((OpenedDataflowEvent) message).getDataflow();
+                               setSelectedWorkflowBundle(workflowBundle, 
false);
+                       } else if (message instanceof SetCurrentDataflowEvent) {
+                               WorkflowBundle workflowBundle = 
((SetCurrentDataflowEvent) message).getDataflow();
+                               setSelectedWorkflowBundle(workflowBundle, 
false);
+                       }
+               }
+       }
+
+       private class EditManagerObserver implements Observer<EditManagerEvent> 
{
+               @Override
+               public void notify(Observable<EditManagerEvent> sender, 
EditManagerEvent message)
+                               throws Exception {
+                       Edit<?> edit = message.getEdit();
+                       considerEdit(edit, message instanceof 
DataFlowUndoEvent);
+               }
+
+               private void considerEdit(Edit<?> edit, boolean undoing) {
+                       if (edit instanceof CompoundEdit) {
+                               CompoundEdit compound = (CompoundEdit) edit;
+                               for (Edit<?> e : compound.getChildEdits())
+                                       considerEdit(e, undoing);
+                       } else if (edit instanceof AddChildEdit
+                                       && edit.getSubject() instanceof 
Workflow) {
+                               Workflow subject = (Workflow) edit.getSubject();
+                               DataflowSelectionModel selectionModel = 
getDataflowSelectionModel(subject
+                                               .getParent());
+                               Object child = ((AddChildEdit<?>) 
edit).getChild();
+                               if (child instanceof Processor
+                                               || child instanceof 
InputWorkflowPort
+                                               || child instanceof 
OutputWorkflowPort) {
+                                       if (undoing
+                                                       && 
selectionModel.getSelection().contains(child))
+                                               selectionModel.clearSelection();
+                                       else {
+                                               Set<Object> selection = new 
HashSet<>();
+                                               selection.add(child);
+                                               
selectionModel.setSelection(selection);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       private void notify(SelectionManagerEvent event) {
+               synchronized (observers) {
+                       observers.notify(event);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-selection-impl/src/main/resources/META-INF/spring/selection-impl-context-osgi.xml
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-selection-impl/src/main/resources/META-INF/spring/selection-impl-context-osgi.xml
 
b/taverna-workbench-selection-impl/src/main/resources/META-INF/spring/selection-impl-context-osgi.xml
new file mode 100644
index 0000000..19faa00
--- /dev/null
+++ 
b/taverna-workbench-selection-impl/src/main/resources/META-INF/spring/selection-impl-context-osgi.xml
@@ -0,0 +1,17 @@
+<?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="selectionManager" 
interface="net.sf.taverna.t2.workbench.selection.SelectionManager" />
+
+       <reference id="editManager" 
interface="net.sf.taverna.t2.workbench.edits.EditManager" />
+       <reference id="fileManager" 
interface="net.sf.taverna.t2.workbench.file.FileManager" />
+       <!-- <reference id="menuManager" 
interface="net.sf.taverna.t2.ui.menu.MenuManager" /> -->
+
+       <list id="perspectives" 
interface="net.sf.taverna.t2.workbench.ui.zaria.PerspectiveSPI" 
cardinality="0..N" />
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-selection-impl/src/main/resources/META-INF/spring/selection-impl-context.xml
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-selection-impl/src/main/resources/META-INF/spring/selection-impl-context.xml
 
b/taverna-workbench-selection-impl/src/main/resources/META-INF/spring/selection-impl-context.xml
new file mode 100644
index 0000000..84bbff1
--- /dev/null
+++ 
b/taverna-workbench-selection-impl/src/main/resources/META-INF/spring/selection-impl-context.xml
@@ -0,0 +1,12 @@
+<?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="selectionManager" 
class="net.sf.taverna.t2.workbench.selection.impl.SelectionManagerImpl" >
+               <property name="fileManager" ref="fileManager"/>
+               <property name="editManager" ref="editManager"/>
+               <property name="perspectives" ref="perspectives"/>
+       </bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-update-manager/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-workbench-update-manager/pom.xml 
b/taverna-workbench-update-manager/pom.xml
new file mode 100644
index 0000000..c2f2003
--- /dev/null
+++ b/taverna-workbench-update-manager/pom.xml
@@ -0,0 +1,26 @@
+<?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>
+       <parent>
+               <groupId>net.sf.taverna.t2</groupId>
+               <artifactId>ui-impl</artifactId>
+               <version>2.0-SNAPSHOT</version>
+       </parent>
+       <groupId>net.sf.taverna.t2.ui-impl</groupId>
+       <artifactId>update-manager</artifactId>
+       <version>2.0.1-SNAPSHOT</version>
+       <packaging>bundle</packaging>
+       <name>Taverna Workbench Update Manager</name>
+       <dependencies>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.ui-api</groupId>
+                       <artifactId>menu-api</artifactId>
+                       <version>${t2.ui.api.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>uk.org.taverna.commons</groupId>
+                       <artifactId>taverna-update-api</artifactId>
+                       <version>${taverna.commons.version}</version>
+               </dependency>
+       </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/update/impl/UpdateManagerView.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/update/impl/UpdateManagerView.java
 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/update/impl/UpdateManagerView.java
new file mode 100644
index 0000000..6b70101
--- /dev/null
+++ 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/update/impl/UpdateManagerView.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (C) 2013 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.update.impl;
+
+import java.awt.GridBagLayout;
+
+import javax.swing.JPanel;
+
+import uk.org.taverna.commons.update.UpdateManager;
+
+/**
+ * @author David Withers
+ */
+@SuppressWarnings({ "serial", "unused" })
+public class UpdateManagerView extends JPanel {
+
+       private UpdateManager updateManager;
+
+       public UpdateManagerView(UpdateManager updateManager) {
+               this.updateManager = updateManager;
+               initialize();
+       }
+
+       private void initialize() {
+               setLayout(new GridBagLayout());
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/update/impl/menu/UpdateMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/update/impl/menu/UpdateMenuAction.java
 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/update/impl/menu/UpdateMenuAction.java
new file mode 100644
index 0000000..2c1459b
--- /dev/null
+++ 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/update/impl/menu/UpdateMenuAction.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (C) 2013 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.update.impl.menu;
+
+import static javax.swing.JOptionPane.YES_OPTION;
+import static javax.swing.JOptionPane.showConfirmDialog;
+import static javax.swing.JOptionPane.showMessageDialog;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.net.URI;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuAction;
+
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.commons.update.UpdateException;
+import uk.org.taverna.commons.update.UpdateManager;
+
+public class UpdateMenuAction extends AbstractMenuAction {
+       private static final Logger logger = 
Logger.getLogger(UpdateMenuAction.class);
+       private static final URI ADVANCED_MENU_URI = URI
+                       
.create("http://taverna.sf.net/2008/t2workbench/menu#advanced";);
+
+       private UpdateManager updateManager;
+
+       public UpdateMenuAction() {
+               super(ADVANCED_MENU_URI, 1000);
+       }
+
+       @SuppressWarnings("serial")
+       @Override
+       protected Action createAction() {
+               return new AbstractAction("Check for updates") {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               findUpdates();
+                       }
+               };
+       }
+
+       public void setUpdateManager(UpdateManager updateManager) {
+               this.updateManager = updateManager;
+       }
+
+       private void findUpdates() {
+               Component parent = null;
+               try {
+                       if (!areUpdatesAvailable()) {
+                               showMessageDialog(null, "No update available");
+                               return;
+                       }
+                       if (showConfirmDialog(parent, "Update available. Update 
Now?") != YES_OPTION)
+                               return;
+                       applyUpdates();
+                       showMessageDialog(parent,
+                                       "Update complete. Restart Taverna to 
apply update.");
+               } catch (UpdateException ex) {
+                       showMessageDialog(parent, "Update failed: " + 
ex.getMessage());
+                       logger.warn("Update failed", ex);
+               }
+       }
+
+       protected boolean areUpdatesAvailable() throws UpdateException {
+               return updateManager.checkForUpdates();
+       }
+
+       protected void applyUpdates() throws UpdateException {
+               updateManager.update();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/PluginMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/PluginMenuAction.java
 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/PluginMenuAction.java
new file mode 100644
index 0000000..e6b4695
--- /dev/null
+++ 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/PluginMenuAction.java
@@ -0,0 +1,52 @@
+package net.sf.taverna.t2.workbench.updatemanager;
+
+import static java.awt.event.KeyEvent.VK_F12;
+import static javax.swing.KeyStroke.getKeyStroke;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.net.URI;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuAction;
+
+public class PluginMenuAction extends AbstractMenuAction {
+       private static final String UPDATES_AND_PLUGINS = "Updates and plugins";
+
+       @SuppressWarnings("serial")
+       protected class SoftwareUpdates extends AbstractAction {
+               public SoftwareUpdates() {
+                       super(UPDATES_AND_PLUGINS, 
null/*UpdatesAvailableIcon.updateRecommendedIcon*/);
+                       putValue(ACCELERATOR_KEY, getKeyStroke(VK_F12, 0));
+               }
+
+               @Override
+               public void actionPerformed(ActionEvent e) {
+                       @SuppressWarnings("unused")
+                       Component parent = null;
+                       if (e.getSource() instanceof Component) {
+                               parent = (Component) e.getSource();
+                       }
+                       //FIXME this does nothing!
+                       //final PluginManagerFrame pluginManagerUI = new 
PluginManagerFrame(
+                       //              PluginManager.getInstance());
+                       //if (parent != null) {
+                       //      pluginManagerUI.setLocationRelativeTo(parent);
+                       //}
+                       //pluginManagerUI.setVisible(true);
+               }
+       }
+
+       public PluginMenuAction() {
+               
super(URI.create("http://taverna.sf.net/2008/t2workbench/menu#advanced";),
+                               100);
+       }
+
+       @Override
+       protected Action createAction() {
+               //return new SoftwareUpdates();
+               return null;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/UpdatesAvailableMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/UpdatesAvailableMenuAction.java
 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/UpdatesAvailableMenuAction.java
new file mode 100644
index 0000000..e2611be
--- /dev/null
+++ 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/UpdatesAvailableMenuAction.java
@@ -0,0 +1,19 @@
+package net.sf.taverna.t2.workbench.updatemanager;
+
+import static 
net.sf.taverna.t2.workbench.updatemanager.UpdatesToolbarSection.UPDATES_SECTION;
+
+import java.awt.Component;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuCustom;
+
+public class UpdatesAvailableMenuAction extends AbstractMenuCustom {
+       public UpdatesAvailableMenuAction() {
+               super(UPDATES_SECTION, 10);
+       }
+
+       @Override
+       protected Component createCustomComponent() {
+               //return new UpdatesAvailableIcon();
+               return null;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/UpdatesToolbarSection.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/UpdatesToolbarSection.java
 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/UpdatesToolbarSection.java
new file mode 100644
index 0000000..b16d614
--- /dev/null
+++ 
b/taverna-workbench-update-manager/src/main/java/net/sf/taverna/t2/workbench/updatemanager/UpdatesToolbarSection.java
@@ -0,0 +1,16 @@
+package net.sf.taverna.t2.workbench.updatemanager;
+
+import static net.sf.taverna.t2.ui.menu.DefaultToolBar.DEFAULT_TOOL_BAR;
+
+import java.net.URI;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuSection;
+
+public class UpdatesToolbarSection extends AbstractMenuSection {
+       public static final URI UPDATES_SECTION = URI
+                       
.create("http://taverna.sf.net/2008/t2workbench/toolbar#updatesSection";);
+
+       public UpdatesToolbarSection() {
+               super(DEFAULT_TOOL_BAR, 10000, UPDATES_SECTION);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-update-manager/src/main/resources/META-INF/spring/update-manager-context-osgi.xml
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-update-manager/src/main/resources/META-INF/spring/update-manager-context-osgi.xml
 
b/taverna-workbench-update-manager/src/main/resources/META-INF/spring/update-manager-context-osgi.xml
new file mode 100644
index 0000000..ea637dd
--- /dev/null
+++ 
b/taverna-workbench-update-manager/src/main/resources/META-INF/spring/update-manager-context-osgi.xml
@@ -0,0 +1,13 @@
+<?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="UpdateMenuAction" auto-export="interfaces" />
+
+       <reference id="updateManager" 
interface="uk.org.taverna.commons.update.UpdateManager" />
+
+</beans:beans>

Reply via email to