You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2018/06/29 10:55:11 UTC

[24/27] incubator-taverna-plugin-component git commit: package rename folders

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentDeleteMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentDeleteMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentDeleteMenuAction.java
new file mode 100644
index 0000000..99c75f9
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentDeleteMenuAction.java
@@ -0,0 +1,67 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import io.github.taverna_extras.component.ui.util.Utils;
+import org.apache.taverna.workbench.file.FileManager;
+
+/**
+ * @author alanrw
+ */
+public class ComponentDeleteMenuAction extends AbstractComponentMenuAction {
+	private static final URI DELETE_COMPONENT_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentDelete");
+
+	private FileManager fm;
+	private ComponentServiceIcon icon;
+	private ComponentPreference prefs;
+	private Utils utils;
+
+	public ComponentDeleteMenuAction() {
+		super(1200, DELETE_COMPONENT_URI);
+	}
+
+	public void setFileManager(FileManager fm) {
+		this.fm = fm;
+	}
+	
+	public void setIcon(ComponentServiceIcon icon) {
+		this.icon = icon;
+	}
+
+	public void setPreferences(ComponentPreference prefs) {
+		this.prefs = prefs;
+	}
+
+	public void setUtils(Utils utils) {
+		this.utils = utils;
+	}
+
+	@Override
+	protected Action createAction() {
+		return new ComponentDeleteAction(fm, prefs, icon, utils);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMenuAction.java
new file mode 100644
index 0000000..1176e6d
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMenuAction.java
@@ -0,0 +1,56 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import static io.github.taverna_extras.component.ui.menu.component.ComponentMenuSection.COMPONENT_SECTION;
+
+import java.net.URI;
+
+import javax.swing.Action;
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+
+/**
+ * Basis for all menu actions. Intended to be configured by Spring.
+ * 
+ * @author Donal Fellows
+ */
+public class ComponentMenuAction extends AbstractMenuAction {
+	/**
+	 * Construct a menu action to appear within the "Components" menu.
+	 * @param positionHint
+	 *            Where on the menu this should come.
+	 * @param id
+	 *            How this should be identified to Taverna.
+	 */
+	public ComponentMenuAction(int positionHint, String id) {
+		super(COMPONENT_SECTION, positionHint, URI.create(id));
+	}
+
+	private Action action;
+
+	public void setAction(Action action) {
+		this.action = action;
+	}
+
+	@Override
+	protected Action createAction() {
+		return action;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMenuSection.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMenuSection.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMenuSection.java
new file mode 100644
index 0000000..07e037d
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMenuSection.java
@@ -0,0 +1,37 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import static io.github.taverna_extras.component.ui.menu.ComponentMenu.COMPONENT;
+
+import java.net.URI;
+import org.apache.taverna.ui.menu.AbstractMenuSection;
+
+/**
+ * @author alanrw
+ */
+public class ComponentMenuSection extends AbstractMenuSection {
+	public static final URI COMPONENT_SECTION = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentSection");
+
+	public ComponentMenuSection() {
+		super(COMPONENT, 400, COMPONENT_SECTION);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMergeAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMergeAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMergeAction.java
new file mode 100644
index 0000000..a350b16
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMergeAction.java
@@ -0,0 +1,135 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import static java.awt.GridBagConstraints.BOTH;
+import static java.awt.GridBagConstraints.WEST;
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
+import static javax.swing.JOptionPane.OK_OPTION;
+import static javax.swing.JOptionPane.showConfirmDialog;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.log4j.Logger.getLogger;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JPanel;
+import javax.swing.border.TitledBorder;
+
+import org.apache.log4j.Logger;
+import io.github.taverna_extras.component.api.Component;
+import io.github.taverna_extras.component.api.ComponentException;
+import io.github.taverna_extras.component.api.Version;
+import io.github.taverna_extras.component.ui.panel.ComponentChoiceMessage;
+import io.github.taverna_extras.component.ui.panel.ComponentChooserPanel;
+import io.github.taverna_extras.component.ui.panel.ProfileChoiceMessage;
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+
+/**
+ * @author alanrw
+ */
+public class ComponentMergeAction extends AbstractAction {
+	private static final long serialVersionUID = 6791184757725253807L;
+	private static final Logger logger = getLogger(ComponentMergeAction.class);
+	private static final String MERGE_COMPONENT = "Merge component...";
+
+	private final ComponentPreference prefs;
+
+	public ComponentMergeAction(ComponentPreference prefs,
+			ComponentServiceIcon icon) {
+		super(MERGE_COMPONENT, icon.getIcon());
+		this.prefs = prefs;
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent arg0) {
+		JPanel overallPanel = new JPanel();
+		overallPanel.setLayout(new GridBagLayout());
+
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		ComponentChooserPanel source = new ComponentChooserPanel(prefs);
+		source.setBorder(new TitledBorder("Source component"));
+
+		gbc.insets = new Insets(0, 5, 0, 5);
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.anchor = WEST;
+		gbc.fill = BOTH;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1;
+		overallPanel.add(source, gbc);
+
+		final ComponentChooserPanel target = new ComponentChooserPanel(prefs);
+		target.setBorder(new TitledBorder("Target component"));
+		gbc.gridy++;
+		overallPanel.add(target, gbc);
+
+		source.addObserver(new Observer<ComponentChoiceMessage>() {
+			@Override
+			public void notify(Observable<ComponentChoiceMessage> sender,
+					ComponentChoiceMessage message) throws Exception {
+				target.notify(null, new ProfileChoiceMessage(message
+						.getComponentFamily().getComponentProfile()));
+			}
+		});
+
+		int answer = showConfirmDialog(null, overallPanel, "Merge Component",
+				OK_CANCEL_OPTION);
+		if (answer == OK_OPTION)
+			doMerge(source.getChosenComponent(), target.getChosenComponent());
+	}
+
+	private void doMerge(Component sourceComponent, Component targetComponent) {
+		if (sourceComponent == null) {
+			showMessageDialog(null, "Unable to determine source component",
+					"Component Merge Problem", ERROR_MESSAGE);
+			return;
+		} else if (targetComponent == null) {
+			showMessageDialog(null, "Unable to determine target component",
+					"Component Merge Problem", ERROR_MESSAGE);
+			return;
+		} else if (sourceComponent.equals(targetComponent)) {
+			showMessageDialog(null, "Cannot merge a component with itself",
+					"Component Merge Problem", ERROR_MESSAGE);
+			return;
+		}
+
+		try {
+			Version sourceVersion = sourceComponent.getComponentVersionMap()
+					.get(sourceComponent.getComponentVersionMap().lastKey());
+			targetComponent.addVersionBasedOn(
+					sourceVersion.getImplementation(), "Merge from "
+							+ sourceComponent.getFamily().getName() + ":"
+							+ sourceComponent.getName());
+		} catch (ComponentException e) {
+			logger.error("failed to merge component", e);
+			showMessageDialog(null, "Failed to merge component: " + e,
+					"Component Merge Problem", ERROR_MESSAGE);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMergeMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMergeMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMergeMenuAction.java
new file mode 100644
index 0000000..1bcac6a
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentMergeMenuAction.java
@@ -0,0 +1,55 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+
+/**
+ * @author alanrw
+ */
+public class ComponentMergeMenuAction extends AbstractComponentMenuAction {
+	private static final URI MERGE_COMPONENT_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentMerge");
+
+	private ComponentServiceIcon icon;
+	private ComponentPreference prefs;
+
+	public ComponentMergeMenuAction() {
+		super(900, MERGE_COMPONENT_URI);
+	}
+
+	public void setIcon(ComponentServiceIcon icon) {
+		this.icon = icon;
+	}
+
+	public void setPreferences(ComponentPreference prefs) {
+		this.prefs = prefs;
+	}
+
+	@Override
+	protected Action createAction() {
+		return new ComponentMergeAction(prefs, icon);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSaveAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSaveAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSaveAction.java
new file mode 100644
index 0000000..0226432
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSaveAction.java
@@ -0,0 +1,69 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import static org.apache.log4j.Logger.getLogger;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import org.apache.log4j.Logger;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import io.github.taverna_extras.component.ui.util.Utils;
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.file.events.FileManagerEvent;
+
+/**
+ * @author alanrw
+ */
+public class ComponentSaveAction extends AbstractAction implements
+		Observer<FileManagerEvent> {
+	private static final long serialVersionUID = -2391891750558659714L;
+	@SuppressWarnings("unused")
+	private static Logger logger = getLogger(ComponentSaveAction.class);
+	private static final String SAVE_COMPONENT = "Save component";
+
+	private Utils utils;
+	private Action saveWorkflowAction;
+
+	public ComponentSaveAction(Action saveAction, FileManager fm,
+			ComponentServiceIcon icon, Utils utils) {
+		super(SAVE_COMPONENT, icon.getIcon());
+		saveWorkflowAction = saveAction;
+		this.utils = utils;
+		fm.addObserver(this);
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		saveWorkflowAction.actionPerformed(e);
+	}
+
+	@Override
+	public void notify(Observable<FileManagerEvent> sender,
+			FileManagerEvent message) throws Exception {
+		setEnabled(saveWorkflowAction.isEnabled()
+				&& utils.currentDataflowIsComponent());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSaveMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSaveMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSaveMenuAction.java
new file mode 100644
index 0000000..cd0418d
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSaveMenuAction.java
@@ -0,0 +1,67 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import io.github.taverna_extras.component.ui.util.Utils;
+import org.apache.taverna.workbench.file.FileManager;
+
+/**
+ * @author alanrw
+ */
+public class ComponentSaveMenuAction extends AbstractComponentMenuAction {
+	private static final URI SAVE_COMPONENT_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentSave");
+
+	private Action action;
+	private FileManager fm;
+	private ComponentServiceIcon icon;
+	private Utils utils;
+
+	public ComponentSaveMenuAction() {
+		super(1100, SAVE_COMPONENT_URI);
+	}
+
+	//FIXME beaninject net.sf.taverna.t2.workbench.file.impl.actions.SaveWorkflowAction
+	public void setSaveWorkflowAction(Action action) {
+		this.action = action;
+	}
+
+	public void setFileManager(FileManager fm) {
+		this.fm = fm;
+	}
+
+	public void setIcon(ComponentServiceIcon icon) {
+		this.icon = icon;
+	}
+
+	public void setUtils(Utils utils) {
+		this.utils = utils;
+	}
+
+	@Override
+	protected Action createAction() {
+		return new ComponentSaveAction(action, fm, icon, utils);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSearchAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSearchAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSearchAction.java
new file mode 100644
index 0000000..56e7395
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSearchAction.java
@@ -0,0 +1,169 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import static java.awt.GridBagConstraints.BOTH;
+import static java.awt.GridBagConstraints.WEST;
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
+import static javax.swing.JOptionPane.OK_OPTION;
+import static javax.swing.JOptionPane.QUESTION_MESSAGE;
+import static javax.swing.JOptionPane.showConfirmDialog;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static javax.swing.JOptionPane.showOptionDialog;
+import static org.apache.log4j.Logger.getLogger;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.util.Map.Entry;
+import java.util.SortedMap;
+
+import javax.swing.AbstractAction;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+import org.apache.log4j.Logger;
+import io.github.taverna_extras.component.api.ComponentFactory;
+import io.github.taverna_extras.component.api.Registry;
+import io.github.taverna_extras.component.api.Version;
+import io.github.taverna_extras.component.api.profile.Profile;
+import io.github.taverna_extras.component.ui.panel.PrefixPanel;
+import io.github.taverna_extras.component.ui.panel.ProfileChooserPanel;
+import io.github.taverna_extras.component.ui.panel.RegistryChooserPanel;
+import io.github.taverna_extras.component.ui.panel.SearchChoicePanel;
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceDesc;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import org.apache.taverna.services.ServiceRegistry;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.workflowview.WorkflowView;
+
+/**
+ * @author alanrw
+ */
+public class ComponentSearchAction extends AbstractAction {
+	private static final String WFDESC_PREFIX = "wfdesc";
+	private static final long serialVersionUID = -7780471499146286881L;
+	@SuppressWarnings("unused")
+	private static final Logger logger = getLogger(ComponentSearchAction.class);
+	private static final String SEARCH_FOR_COMPONENTS = "Search for components...";
+
+	private final ComponentPreference prefs;
+	private final ComponentFactory factory;
+	private final EditManager em;
+	private final MenuManager mm;
+	private final SelectionManager sm;
+	private final ServiceRegistry sr;
+	private final ComponentServiceIcon icon;
+
+	public ComponentSearchAction(ComponentPreference prefs,
+			ComponentFactory factory, EditManager em, MenuManager mm,
+			SelectionManager sm, ServiceRegistry sr, ComponentServiceIcon icon) {
+		super(SEARCH_FOR_COMPONENTS, icon.getIcon());
+		this.prefs = prefs;
+		this.factory = factory;
+		this.em = em;
+		this.mm = mm;
+		this.sm = sm;
+		this.sr = sr;
+		this.icon = icon;
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		JPanel overallPanel = new JPanel(new GridBagLayout());
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		RegistryChooserPanel registryPanel = new RegistryChooserPanel(prefs);
+
+		gbc.insets.left = 5;
+		gbc.insets.right = 5;
+		gbc.gridx = 0;
+		gbc.anchor = WEST;
+		gbc.fill = BOTH;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1;
+		gbc.gridy++;
+		overallPanel.add(registryPanel, gbc);
+
+		ProfileChooserPanel profilePanel = new ProfileChooserPanel(registryPanel);
+		gbc.gridx = 0;
+		gbc.gridy++;
+		overallPanel.add(profilePanel, gbc);
+
+		PrefixPanel prefixPanel = new PrefixPanel(profilePanel);
+		gbc.gridx = 0;
+		gbc.gridy++;
+		overallPanel.add(prefixPanel, gbc);
+
+		JTextArea queryPane = new JTextArea(20, 80);
+		gbc.gridx = 0;
+		gbc.weighty = 1;
+		gbc.gridy++;
+		overallPanel.add(new JScrollPane(queryPane), gbc);
+
+		int answer = showConfirmDialog(null, overallPanel,
+				"Search for components", OK_CANCEL_OPTION);
+		if (answer == OK_OPTION)
+			doSearch(registryPanel.getChosenRegistry(),
+					profilePanel.getChosenProfile(),
+					prefixPanel.getPrefixMap(), queryPane.getText());
+	}
+
+	private void doSearch(Registry chosenRegistry, Profile chosenProfile,
+			SortedMap<String, String> prefixMap, String queryString) {
+		if (chosenRegistry == null) {
+			showMessageDialog(null, "Unable to determine registry",
+					"Component Registry Problem", ERROR_MESSAGE);
+			return;
+		}
+		if (chosenProfile == null) {
+			showMessageDialog(null, "Unable to determine profile",
+					"Component Profile Problem", ERROR_MESSAGE);
+			return;
+		}
+		StringBuilder prefixString = new StringBuilder();
+		for (Entry<String, String> entry : prefixMap.entrySet())
+			if (!entry.getKey().equals(WFDESC_PREFIX))
+				prefixString.append(constructPrefixString(entry));
+
+		SearchChoicePanel searchChoicePanel = new SearchChoicePanel(
+				chosenRegistry, prefixString.toString(), queryString);
+		int answer = showOptionDialog(null, searchChoicePanel,
+				"Matching components", OK_CANCEL_OPTION, QUESTION_MESSAGE,
+				null, new String[] { "Add to workflow", "Cancel" }, "Cancel");
+		if (answer == OK_OPTION) {
+			Version.ID ident = searchChoicePanel.getVersionIdentification();
+			if (ident != null)
+				WorkflowView.importServiceDescription(new ComponentServiceDesc(prefs,
+						factory, icon, ident), false, em, mm, sm, sr);
+		}
+	}
+
+	private static String constructPrefixString(Entry<String, String> entry) {
+		String key = entry.getKey();
+		String value = entry.getValue();
+		return String.format("PREFIX %s:<%s>\n", key, value);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSearchMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSearchMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSearchMenuAction.java
new file mode 100644
index 0000000..c621651
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentSearchMenuAction.java
@@ -0,0 +1,85 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import io.github.taverna_extras.component.api.ComponentFactory;
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import org.apache.taverna.services.ServiceRegistry;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+
+/**
+ * @author alanrw
+ */
+public class ComponentSearchMenuAction extends AbstractComponentMenuAction {
+	private static final URI SEARCH_COMPONENT_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentSearch");
+	private ComponentPreference prefs;
+	private ComponentFactory factory;
+	private EditManager em;
+	private MenuManager mm;
+	private SelectionManager sm;
+	private ServiceRegistry serviceRegistry;
+	private ComponentServiceIcon icon;
+
+	public ComponentSearchMenuAction() {
+		super(1500, SEARCH_COMPONENT_URI);
+	}
+
+	public void setPreferences(ComponentPreference prefs) {
+		this.prefs = prefs;
+	}
+
+	public void setComponentFactory(ComponentFactory factory) {
+		this.factory = factory;
+	}
+
+	public void setEditManager(EditManager em) {
+		this.em = em;
+	}
+
+	public void setMenuManager(MenuManager mm) {
+		this.mm = mm;
+	}
+
+	public void setSelectionManager(SelectionManager sm) {
+		this.sm = sm;
+	}
+
+	public void setServiceRegistry(ServiceRegistry serviceRegistry) {
+		this.serviceRegistry = serviceRegistry;
+	}
+
+	public void setIcon(ComponentServiceIcon icon) {
+		this.icon = icon;
+	}
+
+	@Override
+	protected Action createAction() {
+		return new ComponentSearchAction(prefs, factory, em, mm, sm,
+				serviceRegistry, icon);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentServiceCreatorAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentServiceCreatorAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentServiceCreatorAction.java
new file mode 100644
index 0000000..0c7a668
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentServiceCreatorAction.java
@@ -0,0 +1,112 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.log4j.Logger.getLogger;
+import static org.apache.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+
+import org.apache.log4j.Logger;
+import io.github.taverna_extras.component.api.Version;
+import io.github.taverna_extras.component.ui.menu.component.ComponentCreatorSupport.CopiedProcessor;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+import org.apache.taverna.workbench.selection.SelectionManager;
+
+/**
+ * @author alanrw
+ */
+public class ComponentServiceCreatorAction extends AbstractAction {
+	private static final long serialVersionUID = -2611514696254112190L;
+	private static Logger logger = getLogger(ComponentServiceCreatorAction.class);
+
+	private final Processor p;
+	private final Profile profile;
+	private final ComponentCreatorSupport support;
+
+	public ComponentServiceCreatorAction(Processor processor, SelectionManager sm,
+			ComponentCreatorSupport support, ComponentServiceIcon icon) {
+		super("Create component...", icon.getIcon());
+		this.support = support;
+		p = processor;
+		profile = sm.getSelectedProfile();
+	}
+
+	private Workflow getNestedWorkflow(Activity a) {
+		JsonNode nw = a.getConfiguration().getJson().get("nestedWorkflow");
+		return a.getParent().getParent().getWorkflows().getByName(nw.asText());
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent event) {
+		Version.ID ident = support.getNewComponentIdentification(p.getName());
+		if (ident == null)
+			return;
+
+		Activity a = p.getActivity(profile);
+
+		try {
+			Workflow d;
+			if (NESTED_WORKFLOW.equals(a.getType()))
+				d = getNestedWorkflow(a);
+			else {
+				d = new Workflow();
+
+				/* TODO: Keep the description */
+				// fm.setCurrentDataflow(current);
+
+				CopiedProcessor processorElement = support.copyProcessor(p);
+
+				Processor newProcessor;
+				try {
+					newProcessor = support.pasteProcessor(processorElement, d);
+				} catch (IllegalArgumentException e) {
+					logger.error(
+							"failed to paste processor representing component",
+							e);
+					showMessageDialog(null, e.getMessage(),
+							"Component creation failure", ERROR_MESSAGE);
+					return;
+				}
+
+				support.connectNewProcessor(d, newProcessor);
+			}
+
+			Activity ca = new Activity();
+			support.saveWorkflowAsComponent(d, ident).installConfiguration(ca);
+			support.moveComponentActivityIntoPlace(a, p, ca);
+		} catch (Exception e) {
+			logger.error("failed to instantiate component", e);
+			showMessageDialog(null, e.getCause().getMessage(),
+					"Component creation failure", ERROR_MESSAGE);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentServiceCreatorMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentServiceCreatorMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentServiceCreatorMenuAction.java
new file mode 100644
index 0000000..ef55fa5
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentServiceCreatorMenuAction.java
@@ -0,0 +1,77 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import io.github.taverna_extras.component.ui.menu.AbstractContextComponentMenuAction;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.workbench.selection.SelectionManager;
+
+/**
+ * @author alanrw
+ */
+public class ComponentServiceCreatorMenuAction extends
+		AbstractContextComponentMenuAction {
+	private static final URI configureSection = URI
+			.create("http://taverna.sf.net/2009/contextMenu/configure");
+
+	private ComponentCreatorSupport support;
+	private SelectionManager sm;
+	private ComponentServiceIcon icon;
+
+	public ComponentServiceCreatorMenuAction() {
+		super(configureSection, 60);
+	}
+
+	public void setIcon(ComponentServiceIcon icon) {
+		this.icon = icon;
+	}
+
+	public void setSelectionManager(SelectionManager sm) {
+		this.sm = sm;
+	}
+	
+	public void setSupport(ComponentCreatorSupport support) {
+		this.support = support;
+	}
+
+	@Override
+	public boolean isEnabled() {
+		if (!super.isEnabled())
+			return false;
+		Activity a = findActivity();
+		if (a == null)
+			return false;
+		return !isComponentActivity(a);
+	}
+
+	@Override
+	protected Action createAction() {
+		return new ComponentServiceCreatorAction(
+				(Processor) getContextualSelection().getSelection(), sm,
+				support, icon);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentWorkflowCreatorAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentWorkflowCreatorAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentWorkflowCreatorAction.java
new file mode 100644
index 0000000..c21de5b
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentWorkflowCreatorAction.java
@@ -0,0 +1,84 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.log4j.Logger.getLogger;
+
+import java.awt.event.ActionEvent;
+
+import org.apache.log4j.Logger;
+import io.github.taverna_extras.component.api.Version;
+import io.github.taverna_extras.component.ui.ComponentAction;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import io.github.taverna_extras.component.ui.util.Utils;
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.file.events.FileManagerEvent;
+import org.apache.taverna.workbench.views.graph.GraphViewComponent;
+
+/**
+ * @author alanrw
+ */
+public class ComponentWorkflowCreatorAction extends ComponentAction implements
+		Observer<FileManagerEvent> {
+	private static final long serialVersionUID = -299685223430721587L;
+	private static Logger logger = getLogger(ComponentWorkflowCreatorAction.class);
+	private static final String CREATE_COMPONENT = "Create component from current workflow...";
+
+	private ComponentCreatorSupport support;
+	private FileManager fileManager;
+	private Utils utils;
+
+	public ComponentWorkflowCreatorAction(ComponentCreatorSupport support,
+			FileManager fm, GraphViewComponent graphView,
+			ComponentServiceIcon icon, Utils utils) {
+		super(CREATE_COMPONENT, graphView);
+		this.support = support;
+		this.utils = utils;
+		fm.addObserver(this);
+		this.setIcon(icon);
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent event) {
+		WorkflowBundle bundle = fileManager.getCurrentDataflow();
+		try {
+			Version.ID ident = support.getNewComponentIdentification(bundle.getName());//TODO is this right
+			if (ident == null)
+				return;
+			support.saveWorkflowAsComponent(bundle, ident);
+		} catch (Exception e) {
+			showMessageDialog(graphView, e.getCause().getMessage(),
+					"Component creation failure", ERROR_MESSAGE);
+			logger.error("failed to save workflow as component", e);
+		}
+	}
+
+	@Override
+	public void notify(Observable<FileManagerEvent> sender,
+			FileManagerEvent message) throws Exception {
+		setEnabled(!utils.currentDataflowIsComponent());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentWorkflowCreatorMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentWorkflowCreatorMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentWorkflowCreatorMenuAction.java
new file mode 100644
index 0000000..8ddaf5c
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/ComponentWorkflowCreatorMenuAction.java
@@ -0,0 +1,72 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import io.github.taverna_extras.component.ui.util.Utils;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.views.graph.GraphViewComponent;
+
+/**
+ * @author alanrw
+ */
+public class ComponentWorkflowCreatorMenuAction extends AbstractComponentMenuAction {
+	private static final URI COMPONENT_WORKFLOW_CREATE_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentCreate");
+
+	private ComponentCreatorSupport support;
+	private FileManager fm;
+	private GraphViewComponent graphView;
+	private ComponentServiceIcon icon;
+	private Utils utils;
+
+	public ComponentWorkflowCreatorMenuAction() {
+		super(600, COMPONENT_WORKFLOW_CREATE_URI);
+	}
+
+	public void setSupport(ComponentCreatorSupport support) {
+		this.support = support;
+	}
+
+	public void setFileManager(FileManager fm) {
+		this.fm = fm;
+	}
+
+	public void setGraphView(GraphViewComponent graphView) {
+		this.graphView = graphView;
+	}
+
+	public void setIcon(ComponentServiceIcon icon) {
+		this.icon = icon;
+	}
+
+	public void setUtils(Utils utils) {
+		this.utils = utils;
+	}
+
+	@Override
+	protected Action createAction() {
+		return new ComponentWorkflowCreatorAction(support, fm, graphView, icon, utils);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/FileOpenFromComponentMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/FileOpenFromComponentMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/FileOpenFromComponentMenuAction.java
new file mode 100644
index 0000000..016098f
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/FileOpenFromComponentMenuAction.java
@@ -0,0 +1,74 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.file.FileType;
+import org.apache.taverna.workbench.views.graph.GraphViewComponent;
+
+/**
+ * @author alanrw
+ */
+public class FileOpenFromComponentMenuAction extends
+		AbstractComponentMenuAction {
+	private static final URI FILE_OPEN_FROM_COMPONENT_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentOpen");
+	private FileManager fm;
+	private FileType ft;
+	private ComponentPreference prefs;
+	private GraphViewComponent graphView;
+	private ComponentServiceIcon icon;
+
+	public FileOpenFromComponentMenuAction() {
+		super(700, FILE_OPEN_FROM_COMPONENT_URI);
+	}
+
+	public void setFileManager(FileManager fm) {
+		this.fm = fm;
+	}
+
+	public void setFileType(FileType ft) {
+		this.ft = ft;
+	}
+
+	public void setPreferences(ComponentPreference prefs) {
+		this.prefs = prefs;
+	}
+
+	public void setGraphView(GraphViewComponent graphView) {
+		this.graphView = graphView;
+	}
+
+	public void setIcon(ComponentServiceIcon icon) {
+		this.icon = icon;
+	}
+
+	@Override
+	protected Action createAction() {
+		return new OpenWorkflowFromComponentAction(fm, ft, prefs, graphView,
+				icon);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/OpenWorkflowFromComponentAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/OpenWorkflowFromComponentAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/OpenWorkflowFromComponentAction.java
new file mode 100644
index 0000000..373195f
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/component/OpenWorkflowFromComponentAction.java
@@ -0,0 +1,137 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.component;
+
+import static javax.swing.JOptionPane.CANCEL_OPTION;
+import static javax.swing.JOptionPane.OK_OPTION;
+import static javax.swing.JOptionPane.QUESTION_MESSAGE;
+import static javax.swing.JOptionPane.YES_NO_OPTION;
+import static javax.swing.JOptionPane.showOptionDialog;
+import static org.apache.log4j.Logger.getLogger;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+
+import org.apache.log4j.Logger;
+import io.github.taverna_extras.component.api.Component;
+import io.github.taverna_extras.component.api.Family;
+import io.github.taverna_extras.component.api.Registry;
+import io.github.taverna_extras.component.api.Version;
+import io.github.taverna_extras.component.ui.ComponentAction;
+import io.github.taverna_extras.component.ui.panel.ComponentChoiceMessage;
+import io.github.taverna_extras.component.ui.panel.ComponentVersionChooserPanel;
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.file.FileType;
+import org.apache.taverna.workbench.file.exceptions.OpenException;
+import org.apache.taverna.workbench.views.graph.GraphViewComponent;
+
+/**
+ * @author alanrw
+ */
+public class OpenWorkflowFromComponentAction extends ComponentAction {
+	private static final long serialVersionUID = 7382677337746318211L;
+	private static final Logger logger = getLogger(OpenWorkflowFromComponentAction.class);
+	private static final String ACTION_NAME = "Open component...";
+	private static final String ACTION_DESCRIPTION = "Open the workflow that implements a component";
+
+	private final FileManager fm;
+	private final FileType ft;
+	private final ComponentPreference prefs;
+
+	public OpenWorkflowFromComponentAction(FileManager fm, FileType ft,
+			ComponentPreference prefs, GraphViewComponent graphView,
+			ComponentServiceIcon icon) {
+		super(ACTION_NAME, graphView);
+		this.fm = fm;
+		this.ft = ft;
+		this.prefs = prefs;
+		setIcon(icon);
+		putValue(SHORT_DESCRIPTION, ACTION_DESCRIPTION);
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent arg) {
+		final ComponentVersionChooserPanel panel = new ComponentVersionChooserPanel(prefs);	
+		
+		final JButton okay = new JButton("OK");
+		okay.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				getOptionPane((JComponent) e.getSource()).setValue(OK_OPTION);
+				doOpen(panel.getChosenRegistry(), panel.getChosenFamily(),
+						panel.getChosenComponent(),
+						panel.getChosenComponentVersion());
+			}
+		});
+		okay.setEnabled(false);
+		// Only enable the OK button of a component is not null
+		panel.getComponentChooserPanel().addObserver(
+				new Observer<ComponentChoiceMessage>() {
+					@Override
+					public void notify(
+							Observable<ComponentChoiceMessage> sender,
+							ComponentChoiceMessage message) throws Exception {
+						okay.setEnabled(message.getChosenComponent() != null);
+					}
+				});
+
+		final JButton cancel = new JButton("Cancel");
+		cancel.addActionListener(new ActionListener() {
+		    @Override
+		    public void actionPerformed(ActionEvent e) {
+                getOptionPane((JComponent)e.getSource()).setValue(CANCEL_OPTION);
+		    }
+		});
+
+		showOptionDialog(graphView, panel, "Component version choice",
+				YES_NO_OPTION, QUESTION_MESSAGE, null, new Object[] { okay,
+						cancel }, okay);
+	}
+	
+    protected JOptionPane getOptionPane(JComponent parent) {
+		if (parent instanceof JOptionPane)
+			return (JOptionPane) parent;
+		return getOptionPane((JComponent) parent.getParent());
+    }
+
+	private void doOpen(Registry registry, Family family, Component component,
+			Version version) {
+		Version.ID ident = new Version.Identifier(
+				registry.getRegistryBase(), family.getName(),
+				component.getName(), version.getVersionNumber());
+
+		try {
+			WorkflowBundle d = fm.openDataflow(ft, ident);
+			markGraphAsBelongingToComponent(d);
+		} catch (OpenException e) {
+			logger.error("Failed to open component definition", e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyCreateAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyCreateAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyCreateAction.java
new file mode 100644
index 0000000..0fe2ee4
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyCreateAction.java
@@ -0,0 +1,176 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.family;
+
+import static java.awt.GridBagConstraints.BOTH;
+import static java.awt.GridBagConstraints.WEST;
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
+import static javax.swing.JOptionPane.OK_OPTION;
+import static javax.swing.JOptionPane.showConfirmDialog;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.log4j.Logger.getLogger;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
+
+import org.apache.log4j.Logger;
+import io.github.taverna_extras.component.api.ComponentException;
+import io.github.taverna_extras.component.api.License;
+import io.github.taverna_extras.component.api.Registry;
+import io.github.taverna_extras.component.api.SharingPolicy;
+import io.github.taverna_extras.component.api.profile.Profile;
+import io.github.taverna_extras.component.ui.panel.LicenseChooserPanel;
+import io.github.taverna_extras.component.ui.panel.ProfileChooserPanel;
+import io.github.taverna_extras.component.ui.panel.RegistryChooserPanel;
+import io.github.taverna_extras.component.ui.panel.SharingPolicyChooserPanel;
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+
+/**
+ * @author alanrw
+ */
+public class ComponentFamilyCreateAction extends AbstractAction {
+	private static final long serialVersionUID = -7780471499146286881L;
+	private static final Logger logger = getLogger(ComponentFamilyCreateAction.class);
+	private static final String CREATE_FAMILY = "Create family...";
+
+	private ComponentPreference prefs;
+	private JPanel overallPanel;
+	private GridBagConstraints gbc;
+
+	public ComponentFamilyCreateAction(ComponentPreference prefs,
+			ComponentServiceIcon iconProvider) {
+		super(CREATE_FAMILY, iconProvider.getIcon());
+		this.prefs = prefs;
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent arg0) {
+		overallPanel = new JPanel(new GridBagLayout());
+		gbc = new GridBagConstraints();
+
+		RegistryChooserPanel registryPanel = new RegistryChooserPanel(prefs);
+
+		gbc.insets.left = 5;
+		gbc.insets.right = 5;
+		gbc.gridx = 0;
+		gbc.anchor = WEST;
+		gbc.fill = BOTH;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1;
+		gbc.gridy++;
+		overallPanel.add(registryPanel, gbc);
+
+		ProfileChooserPanel profilePanel = new ProfileChooserPanel(
+				registryPanel);
+		gbc.gridx = 0;
+		gbc.weighty = 1;
+		gbc.gridy++;
+		overallPanel.add(profilePanel, gbc);
+
+		gbc.gridx = 0;
+		gbc.gridwidth = 1;
+		gbc.weightx = 0;
+		gbc.weighty = 0;
+		gbc.gridy++;
+		overallPanel.add(new JLabel("Component family name:"), gbc);
+
+		gbc.gridx = 1;
+		gbc.weightx = 1;
+		JTextField familyNameField = new JTextField(60);
+		overallPanel.add(familyNameField, gbc);
+
+		gbc.gridx = 0;
+		gbc.gridwidth = 2;
+		gbc.weightx = 0;
+		gbc.weighty = 0;
+		gbc.gridy++;
+		JTextArea familyDescription = new JTextArea(10, 60);
+		JScrollPane familyDescriptionPane = new JScrollPane(familyDescription);
+		familyDescriptionPane.setBorder(new TitledBorder("Family description"));
+		overallPanel.add(familyDescriptionPane, gbc);
+
+		gbc.gridx = 0;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1;
+		gbc.weighty = 1;
+		gbc.gridy++;
+		SharingPolicyChooserPanel permissionPanel = new SharingPolicyChooserPanel(
+				registryPanel);
+		overallPanel.add(permissionPanel, gbc);
+
+		gbc.gridy++;
+		LicenseChooserPanel licensePanel = new LicenseChooserPanel();
+		registryPanel.addObserver(licensePanel);
+		overallPanel.add(licensePanel, gbc);
+
+		int answer = showConfirmDialog(null, overallPanel,
+				"Create Component Family", OK_CANCEL_OPTION);
+		if (answer == OK_OPTION)
+			doCreate(registryPanel.getChosenRegistry(),
+					profilePanel.getChosenProfile(), familyNameField.getText(),
+					familyDescription.getText(),
+					permissionPanel.getChosenPermission(),
+					licensePanel.getChosenLicense());
+	}
+
+	private void doCreate(Registry chosenRegistry, Profile chosenProfile,
+			String newName, String familyDescription, SharingPolicy permission,
+			License license) {
+		if (chosenRegistry == null) {
+			showMessageDialog(null, "Unable to determine registry",
+					"Component Registry Problem", ERROR_MESSAGE);
+			return;
+		} else if (chosenProfile == null) {
+			showMessageDialog(null, "Unable to determine profile",
+					"Component Profile Problem", ERROR_MESSAGE);
+			return;
+		} else if ((newName == null) || newName.isEmpty()) {
+			showMessageDialog(null, "Name must be specified",
+					"Missing component family name", ERROR_MESSAGE);
+			return;
+		}
+
+		try {
+			if (chosenRegistry.getComponentFamily(newName) != null) {
+				showMessageDialog(null, newName + " is already used",
+						"Duplicate component family name", ERROR_MESSAGE);
+				return;
+			}
+			chosenRegistry.createComponentFamily(newName, chosenProfile,
+					familyDescription, license, permission);
+		} catch (ComponentException e) {
+			logger.error("failed to create family", e);
+			showMessageDialog(null,
+					"Unable to create family: " + e.getMessage(),
+					"Family creation problem", ERROR_MESSAGE);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyCreateMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyCreateMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyCreateMenuAction.java
new file mode 100644
index 0000000..94c0080
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyCreateMenuAction.java
@@ -0,0 +1,58 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.family;
+
+import static io.github.taverna_extras.component.ui.menu.family.ComponentFamilyMenuSection.COMPONENT_FAMILY_SECTION;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+
+/**
+ * @author alanrw
+ */
+public class ComponentFamilyCreateMenuAction extends AbstractMenuAction {
+	private static final URI COMPONENT_FAMILY_CREATE_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentFamilyCreate");
+
+	private ComponentPreference prefs;
+	private ComponentServiceIcon iconProvider;
+
+	public ComponentFamilyCreateMenuAction() {
+		super(COMPONENT_FAMILY_SECTION, 400, COMPONENT_FAMILY_CREATE_URI);
+	}
+
+	public void setPreferences(ComponentPreference prefs) {
+		this.prefs = prefs;
+	}
+
+	public void setIcon(ComponentServiceIcon iconProvider) {
+		this.iconProvider = iconProvider;
+	}
+
+	@Override
+	protected Action createAction() {
+		return new ComponentFamilyCreateAction(prefs, iconProvider);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyDeleteAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyDeleteAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyDeleteAction.java
new file mode 100644
index 0000000..4ac20e4
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyDeleteAction.java
@@ -0,0 +1,201 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.family;
+
+import static java.awt.GridBagConstraints.BOTH;
+import static java.awt.GridBagConstraints.WEST;
+import static java.lang.String.format;
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
+import static javax.swing.JOptionPane.OK_OPTION;
+import static javax.swing.JOptionPane.YES_NO_OPTION;
+import static javax.swing.JOptionPane.YES_OPTION;
+import static javax.swing.JOptionPane.showConfirmDialog;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.log4j.Logger.getLogger;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.util.concurrent.ExecutionException;
+
+import javax.swing.AbstractAction;
+import javax.swing.JPanel;
+import javax.swing.SwingWorker;
+
+import org.apache.log4j.Logger;
+import io.github.taverna_extras.component.api.ComponentException;
+import io.github.taverna_extras.component.api.Family;
+import io.github.taverna_extras.component.api.Registry;
+import io.github.taverna_extras.component.api.Version;
+import io.github.taverna_extras.component.ui.panel.FamilyChooserPanel;
+import io.github.taverna_extras.component.ui.panel.RegistryChooserPanel;
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceProviderConfig;
+import io.github.taverna_extras.component.ui.util.Utils;
+
+import org.apache.taverna.scufl2.api.configurations.Configuration;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.workbench.file.FileManager;
+
+/**
+ * @author alanrw
+ */
+public class ComponentFamilyDeleteAction extends AbstractAction {
+	private static final String CONFIRM_MSG = "Are you sure you want to delete %s";
+	private static final String CONFIRM_TITLE = "Delete Component Family Confirmation";
+	private static final String DELETE_FAMILY_LABEL = "Delete family...";
+	private static final String ERROR_TITLE = "Component Family Deletion Error";
+	private static final String FAILED_MSG = "Unable to delete %s: %s";
+	private static final String FAMILY_FAIL_TITLE = "Component Family Problem";
+	private static final String OPEN_MSG = "Components in the family are open";
+	private static final String PICK_FAMILY_TITLE = "Delete Component Family";
+	private static final String REGISTRY_FAIL_TITLE = "Component Registry Problem";
+	private static final String WHAT_FAMILY_MSG = "Unable to determine family";
+	private static final String WHAT_REGISTRY_MSG = "Unable to determine registry";
+	private static final Logger logger = getLogger(ComponentFamilyDeleteAction.class);
+	private static final long serialVersionUID = -4976161883778371344L;
+
+	private final FileManager fm;
+	private final ComponentPreference prefs;
+	private final Utils utils;
+
+	public ComponentFamilyDeleteAction(FileManager fm,
+			ComponentPreference prefs, ComponentServiceIcon icon, Utils utils) {
+		super(DELETE_FAMILY_LABEL, icon.getIcon());
+		this.fm = fm;
+		this.prefs = prefs;
+		this.utils = utils;
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent ev) {
+		JPanel overallPanel = new JPanel(new GridBagLayout());
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		RegistryChooserPanel registryPanel = new RegistryChooserPanel(prefs);
+
+		gbc.insets = new Insets(0, 5, 0, 5);
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.anchor = WEST;
+		gbc.fill = BOTH;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1;
+		overallPanel.add(registryPanel, gbc);
+
+		FamilyChooserPanel familyPanel = new FamilyChooserPanel(registryPanel);
+		gbc.gridx = 0;
+		gbc.gridy = 1;
+		gbc.weighty = 1;
+		overallPanel.add(familyPanel, gbc);
+
+		int answer = showConfirmDialog(null, overallPanel, PICK_FAMILY_TITLE,
+				OK_CANCEL_OPTION);
+		if (answer == OK_OPTION)
+			deletionActionFlow(registryPanel.getChosenRegistry(),
+					familyPanel.getChosenFamily());
+	}
+
+	/**
+	 * Check if the preconditions for the deletion action are satisfied.
+	 * 
+	 * @param chosenRegistry
+	 *            What registry contains the family.
+	 * @param chosenFamily
+	 */
+	private void deletionActionFlow(Registry chosenRegistry,
+			final Family chosenFamily) {
+		if (chosenRegistry == null) {
+			showMessageDialog(null, WHAT_REGISTRY_MSG, REGISTRY_FAIL_TITLE,
+					ERROR_MESSAGE);
+			return;
+		} else if (chosenFamily == null) {
+			showMessageDialog(null, WHAT_FAMILY_MSG, FAMILY_FAIL_TITLE,
+					ERROR_MESSAGE);
+			return;
+		} else if (familyIsInUse(chosenRegistry, chosenFamily)) {
+			showMessageDialog(null, OPEN_MSG, FAMILY_FAIL_TITLE, ERROR_MESSAGE);
+			return;
+		} else if (showConfirmDialog(null,
+				format(CONFIRM_MSG, chosenFamily.getName()), CONFIRM_TITLE,
+				YES_NO_OPTION) == YES_OPTION)
+			new SwingWorker<ComponentServiceProviderConfig, Object>() {
+				@Override
+				protected ComponentServiceProviderConfig doInBackground()
+						throws Exception {
+					return deleteFamily(chosenFamily);
+				}
+
+				@Override
+				protected void done() {
+					deletionDone(chosenFamily, this);
+				}
+			}.execute();
+	}
+
+	private ComponentServiceProviderConfig deleteFamily(Family family)
+			throws ComponentException {
+		ComponentServiceProviderConfig config = new ComponentServiceProviderConfig(
+				family);
+		family.delete();
+		return config;
+	}
+
+	private void deletionDone(Family family,
+			SwingWorker<ComponentServiceProviderConfig, Object> worker) {
+		Configuration config;
+		try {
+		config = worker.get().getConfiguration();
+		} catch (InterruptedException e) {
+			logger.warn("interrupted during removal of component family", e);
+			return;
+		} catch (ExecutionException e) {
+			logger.error("failed to delete family", e.getCause());
+			showMessageDialog(
+					null,
+					format(FAILED_MSG, family.getName(), e.getCause()
+							.getMessage()), ERROR_TITLE, ERROR_MESSAGE);
+			return;
+		}
+		try {
+			utils.removeComponentServiceProvider(config);
+		} catch (Exception e) {
+			logger.error("failed to update service provider panel "
+					+ "after deleting family", e);
+		}
+	}
+
+	private boolean familyIsInUse(Registry chosenRegistry, Family chosenFamily) {
+		for (WorkflowBundle d : fm.getOpenDataflows()) {
+			Object dataflowSource = fm.getDataflowSource(d);
+			if (dataflowSource instanceof Version.ID) {
+				Version.ID ident = (Version.ID) dataflowSource;
+				if (ident.getRegistryBase().toString()
+						.equals(chosenRegistry.getRegistryBase().toString())
+						&& ident.getFamilyName().equals(chosenFamily.getName()))
+					return true;
+			}
+		}
+		return false;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyDeleteMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyDeleteMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyDeleteMenuAction.java
new file mode 100644
index 0000000..ffb3cbf
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyDeleteMenuAction.java
@@ -0,0 +1,69 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.family;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+import io.github.taverna_extras.component.ui.util.Utils;
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+import org.apache.taverna.workbench.file.FileManager;
+
+/**
+ * @author alanrw
+ */
+public class ComponentFamilyDeleteMenuAction extends AbstractMenuAction {
+	private static final URI COMPONENT_FAMILY_DELETE_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentFamilyDelete");
+
+	private FileManager fm;
+	private ComponentPreference prefs;
+	private ComponentServiceIcon icon;
+	private Utils utils;
+
+	public ComponentFamilyDeleteMenuAction() {
+		super(ComponentFamilyMenuSection.COMPONENT_FAMILY_SECTION, 500,
+				COMPONENT_FAMILY_DELETE_URI);
+	}
+
+	public void setFileManager(FileManager fm) {
+		this.fm = fm;
+	}
+
+	public void setIcon(ComponentServiceIcon icon) {
+		this.icon = icon;
+	}
+	
+	public void setPreferences(ComponentPreference prefs) {
+		this.prefs = prefs;
+	}
+
+	public void setUtils(Utils utils) {
+		this.utils = utils;
+	}
+
+	@Override
+	protected Action createAction() {
+		return new ComponentFamilyDeleteAction(fm, prefs, icon, utils);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyMenuSection.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyMenuSection.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyMenuSection.java
new file mode 100644
index 0000000..dbc331e
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/family/ComponentFamilyMenuSection.java
@@ -0,0 +1,37 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.family;
+
+import java.net.URI;
+
+import io.github.taverna_extras.component.ui.menu.ComponentMenu;
+import org.apache.taverna.ui.menu.AbstractMenuSection;
+
+/**
+ * @author alanrw
+ */
+public class ComponentFamilyMenuSection extends AbstractMenuSection {
+	public static final URI COMPONENT_FAMILY_SECTION = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#componentFamilySection");
+
+	public ComponentFamilyMenuSection() {
+		super(ComponentMenu.COMPONENT, 300, COMPONENT_FAMILY_SECTION);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/profile/ComponentProfileCopyAction.java
----------------------------------------------------------------------
diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/profile/ComponentProfileCopyAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/profile/ComponentProfileCopyAction.java
new file mode 100644
index 0000000..2d8295a
--- /dev/null
+++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/profile/ComponentProfileCopyAction.java
@@ -0,0 +1,177 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.github.taverna_extras.component.ui.menu.profile;
+
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
+import static javax.swing.JOptionPane.OK_OPTION;
+import static javax.swing.JOptionPane.showConfirmDialog;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.log4j.Logger.getLogger;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JPanel;
+import javax.swing.border.TitledBorder;
+
+import org.apache.log4j.Logger;
+import io.github.taverna_extras.component.api.ComponentException;
+import io.github.taverna_extras.component.api.License;
+import io.github.taverna_extras.component.api.Registry;
+import io.github.taverna_extras.component.api.SharingPolicy;
+import io.github.taverna_extras.component.api.profile.Profile;
+import io.github.taverna_extras.component.ui.panel.LicenseChooserPanel;
+import io.github.taverna_extras.component.ui.panel.ProfileChooserPanel;
+import io.github.taverna_extras.component.ui.panel.RegistryChooserPanel;
+import io.github.taverna_extras.component.ui.panel.SharingPolicyChooserPanel;
+import io.github.taverna_extras.component.ui.preference.ComponentPreference;
+import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceIcon;
+
+/**
+ * @author alanrw
+ */
+public class ComponentProfileCopyAction extends AbstractAction {
+	private static final long serialVersionUID = 6332253931049645259L;
+	private static final Logger log = getLogger(ComponentProfileCopyAction.class);
+	private static final String COPY_PROFILE = "Copy profile...";
+
+	private final ComponentPreference prefs;
+
+	public ComponentProfileCopyAction(ComponentPreference prefs,
+			ComponentServiceIcon iconProvider) {
+		super(COPY_PROFILE, iconProvider.getIcon());
+		this.prefs = prefs;
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent ev) {
+		JPanel overallPanel = new JPanel();
+		overallPanel.setLayout(new GridBagLayout());
+
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		RegistryChooserPanel sourceRegistryPanel = new RegistryChooserPanel(prefs);
+		sourceRegistryPanel.setBorder(new TitledBorder("Source registry"));
+
+		gbc.insets = new Insets(0, 5, 0, 5);
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.BOTH;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1;
+		overallPanel.add(sourceRegistryPanel, gbc);
+
+		ProfileChooserPanel profilePanel = new ProfileChooserPanel(sourceRegistryPanel);
+		profilePanel.setBorder(new TitledBorder("Source profile"));
+
+		gbc.gridx = 0;
+		gbc.gridy = 1;
+		gbc.weighty = 1;
+		overallPanel.add(profilePanel, gbc);
+
+		RegistryChooserPanel targetRegistryPanel = new RegistryChooserPanel(prefs);
+		targetRegistryPanel.setBorder(new TitledBorder("Target registry"));
+		gbc.gridy = 2;
+		overallPanel.add(targetRegistryPanel, gbc);
+
+		gbc.gridx = 0;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1;
+		gbc.weighty = 1;
+		gbc.gridy++;
+		SharingPolicyChooserPanel permissionPanel = new SharingPolicyChooserPanel(targetRegistryPanel);
+		overallPanel.add(permissionPanel, gbc);
+
+		gbc.gridy++;
+		LicenseChooserPanel licensePanel = new LicenseChooserPanel();
+		targetRegistryPanel.addObserver(licensePanel);
+		overallPanel.add(licensePanel, gbc);
+
+		int answer = showConfirmDialog(null, overallPanel,
+				"Copy Component Profile", OK_CANCEL_OPTION);
+		try {
+			if (answer == OK_OPTION) 
+				doCopy(sourceRegistryPanel.getChosenRegistry(),
+						profilePanel.getChosenProfile(),
+						targetRegistryPanel.getChosenRegistry(),
+						permissionPanel.getChosenPermission(),
+						licensePanel.getChosenLicense());
+		} catch (ComponentException e) {
+			log.error("failed to copy profile", e);
+			showMessageDialog(null, "Unable to save profile: " + e.getMessage(),
+					"Registry Exception", ERROR_MESSAGE);
+		}
+	}
+
+	private void doCopy(Registry sourceRegistry, Profile sourceProfile,
+			Registry targetRegistry, SharingPolicy permission, License license)
+			throws ComponentException {
+		if (sourceRegistry == null) {
+			showMessageDialog(null, "Unable to determine source registry",
+					"Component Registry Problem", ERROR_MESSAGE);
+			return;
+		}
+		if (targetRegistry == null) {
+			showMessageDialog(null, "Unable to determine target registry",
+					"Component Registry Problem", ERROR_MESSAGE);
+			return;
+		}
+		if (sourceRegistry.equals(targetRegistry)) {
+			showMessageDialog(null, "Cannot copy to the same registry",
+					"Copy Problem", ERROR_MESSAGE);
+			return;
+		}
+		if (sourceProfile == null) {
+			showMessageDialog(null, "Unable to determine source profile",
+					"Component Profile Problem", ERROR_MESSAGE);
+			return;
+		}
+		for (Profile p : targetRegistry.getComponentProfiles()) {
+			if (p.getName().equals(sourceProfile.getName())) {
+				showMessageDialog(null,
+						"Target registry already contains a profile named "
+								+ sourceProfile.getName(), "Copy Problem",
+						ERROR_MESSAGE);
+				return;
+			}
+			String sourceId = sourceProfile.getId();
+			if (sourceId == null) {
+				showMessageDialog(null,
+						"Source profile \"" + sourceProfile.getName()
+								+ "\" has no id ", "Copy Problem",
+						ERROR_MESSAGE);
+				return;
+			}
+			String id = p.getId();
+			if (sourceId.equals(id)) {
+				showMessageDialog(null,
+						"Target registry already contains a profile with id "
+								+ sourceId, "Copy Problem", ERROR_MESSAGE);
+				return;
+			}
+		}
+		targetRegistry.addComponentProfile(sourceProfile, license, permission);
+	}
+}