You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/03/06 23:34:39 UTC
[43/50] [abbrv] incubator-taverna-workbench git commit: taverna-*
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-io/src/main/java/net/sf/taverna/t2/lang/io/StreamCopier.java
----------------------------------------------------------------------
diff --git a/taverna-io/src/main/java/net/sf/taverna/t2/lang/io/StreamCopier.java b/taverna-io/src/main/java/net/sf/taverna/t2/lang/io/StreamCopier.java
new file mode 100644
index 0000000..b0d600d
--- /dev/null
+++ b/taverna-io/src/main/java/net/sf/taverna/t2/lang/io/StreamCopier.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.lang.io;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Copies an InputStream to an OutputStream.
+ *
+ * @author Tom Oinn
+ */
+public class StreamCopier extends Thread {
+
+ private static Logger logger = Logger
+ .getLogger(StreamCopier.class);
+
+ InputStream is;
+
+ OutputStream os;
+
+ /**
+ * Create a new StreamCopier which will, when started, copy the specified
+ * InputStream to the specified OutputStream
+ */
+ public StreamCopier(InputStream is, OutputStream os) {
+ super("StreamCopier");
+ this.is = is;
+ this.os = os;
+ }
+
+ /**
+ * Start copying the stream, exits when the InputStream runs out of data
+ */
+ public void run() {
+ try {
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = is.read(buffer)) != -1) {
+ os.write(buffer, 0, bytesRead);
+ }
+ os.flush();
+ os.close();
+ } catch (Exception ex) {
+ logger.error("Could not copy stream", ex);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-io/src/main/java/net/sf/taverna/t2/lang/io/StreamDevourer.java
----------------------------------------------------------------------
diff --git a/taverna-io/src/main/java/net/sf/taverna/t2/lang/io/StreamDevourer.java b/taverna-io/src/main/java/net/sf/taverna/t2/lang/io/StreamDevourer.java
new file mode 100644
index 0000000..8495e27
--- /dev/null
+++ b/taverna-io/src/main/java/net/sf/taverna/t2/lang/io/StreamDevourer.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.lang.io;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Devours an input stream and allows the contents to be read as a String once
+ * the stream has completed.
+ *
+ * @author Tom Oinn
+ * @author Alan R Williams
+ */
+public class StreamDevourer extends Thread {
+
+ private static Logger logger = Logger.getLogger(StreamDevourer.class);
+
+ private static byte[] newLine = System.getProperty("line.separator").getBytes();
+
+ BufferedReader br;
+
+ ByteArrayOutputStream output;
+
+ /**
+ * Returns the current value of the internal ByteArrayOutputStream
+ */
+ @Override
+ public String toString() {
+ return output.toString();
+ }
+
+ /**
+ * Waits for the stream to close then returns the String representation of
+ * its contents (this is equivalent to doing a join then calling toString)
+ */
+ public String blockOnOutput() {
+ try {
+ this.join();
+ return output.toString();
+ } catch (InterruptedException ie) {
+ logger.error("Interrupted", ie);
+ interrupt();
+ return "";
+ }
+ }
+
+ /**
+ * Create the StreamDevourer and point it at an InputStream to consume
+ */
+ public StreamDevourer(InputStream is) {
+ super("StreamDevourer");
+ this.br = new BufferedReader(new InputStreamReader(is));
+ this.output = new ByteArrayOutputStream();
+ }
+
+ /**
+ * When started this Thread will copy all data from the InputStream into a
+ * ByteArrayOutputStream via a BufferedReader. Because of the use of the
+ * BufferedReader this is only really appropriate for streams of textual
+ * data
+ */
+ @Override
+ public void run() {
+ try {
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ // && line.endsWith("</svg>") == false) {
+ if (line.endsWith("\\") && !line.endsWith("\\\\")) {
+ line = line.substring(0, line.length() - 1);
+ output.write(line.getBytes());
+ } else {
+ output.write(line.getBytes());
+ output.write(newLine);
+ }
+ }
+ br.close();
+ } catch (IOException ioe) {
+ logger.error(ioe);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-partition/pom.xml b/taverna-partition/pom.xml
new file mode 100644
index 0000000..ba5088a
--- /dev/null
+++ b/taverna-partition/pom.xml
@@ -0,0 +1,23 @@
+<?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>lang</artifactId>
+ <version>2.0.1-SNAPSHOT</version>
+ </parent>
+ <groupId>net.sf.taverna.t2.lang</groupId>
+ <artifactId>partition</artifactId>
+ <packaging>bundle</packaging>
+ <name>Partition</name>
+ <description>API for recursive subset partitioning</description>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/HashSetModel.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/HashSetModel.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/HashSetModel.java
new file mode 100644
index 0000000..3a66eb0
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/HashSetModel.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.partition;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Implementation of SetModel based on a HashSet
+ *
+ * @author Tom Oinn
+ */
+public class HashSetModel<ItemType> extends HashSet<ItemType> implements
+ SetModel<ItemType> {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5763277571663880941L;
+ // Listeners for set change events
+ private List<SetModelChangeListener<ItemType>> changeListeners;
+
+ /**
+ * Default constructor, creates a set model based on a HashSet
+ */
+ public HashSetModel() {
+ super();
+ changeListeners = new ArrayList<SetModelChangeListener<ItemType>>();
+ }
+
+ /**
+ * Implements SetModel
+ */
+ public synchronized void addSetModelChangeListener(
+ SetModelChangeListener<ItemType> listener) {
+ changeListeners.add(listener);
+ }
+
+ /**
+ * Implements SetModel
+ */
+ public synchronized void removeSetModelChangeListener(
+ SetModelChangeListener<ItemType> listener) {
+ changeListeners.remove(listener);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public synchronized void clear() {
+ notifyRemoval((Set<Object>) this);
+ super.clear();
+ }
+
+ @Override
+ public synchronized boolean add(ItemType item) {
+ if (super.add(item)) {
+ notifyAddition(Collections.singleton(item));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized boolean remove(Object item) {
+ if (super.remove(item)) {
+ notifyRemoval(Collections.singleton(item));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Push addition notification to listeners
+ *
+ * @param itemsAdded
+ */
+ private synchronized void notifyAddition(Set<ItemType> itemsAdded) {
+ for (SetModelChangeListener<ItemType> listener : new ArrayList<SetModelChangeListener<ItemType>>(
+ changeListeners)) {
+ listener.itemsWereAdded(itemsAdded);
+ }
+ }
+
+ /**
+ * Push removal notification to listeners
+ *
+ * @param itemsRemoved
+ */
+ private synchronized void notifyRemoval(Set<Object> itemsRemoved) {
+ for (SetModelChangeListener<ItemType> listener : new ArrayList<SetModelChangeListener<ItemType>>(
+ changeListeners)) {
+ listener.itemsWereRemoved(itemsRemoved);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/Partition.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/Partition.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/Partition.java
new file mode 100644
index 0000000..e1e5819
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/Partition.java
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ * 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.partition;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.swing.event.TreeModelEvent;
+import javax.swing.tree.TreePath;
+
+/**
+ * A partition represents a set of items which can be exclusively classified
+ * into one or more distinct subsets along with the algorithm to perform this
+ * subset operation.
+ *
+ * @author Tom Oinn
+ *
+ * @param <ItemType>
+ * all items in the underlying set of which this is a subset are
+ * instances of this type or can be cast to it according to
+ * conventional java language rules.
+ * @param <PartitionValueType>
+ * the partition value type used by the parent partition algorithm to
+ * create this partition object. As an example, if this partition
+ * object represented all those entries with a particular host
+ * institution this would be a String or possibly URL.
+ * @param <ChildPartitionValueType>
+ * the partition value type used by this partition's partition
+ * algorithm to create sub-partitions, it's used in the signature
+ * here because ordering of children is done based on these values.
+ * Any child partition will have a getPartitionValue return type
+ * cast-able to this type.
+ */
+public class Partition<ItemType extends Comparable, PartitionValueType, ChildPartitionValueType> {
+
+ // A comparator operating over the value type of the child partitions and
+ // used to order them as created or to re-order on a change of this property
+ private Comparator<ChildPartitionValueType> childPartitionOrder = null;
+
+ // Back reference to the root partition of which this is a direct or
+ // indirect sub-partition. If this *is* the root partition this points to
+ // self
+ protected RootPartition<ItemType> root;
+
+ // A subset of the parent's member set containing items which have been
+ // allocated to this partition by the parent's partition algorithm. The
+ // partition is specified by the partitionValue field.
+ private List<ItemType> members;
+
+ // The parent partition of which this is a subset
+ private Partition<ItemType, ?, PartitionValueType> parent;
+
+ // Specification of the partition in terms of the parent's partitioning
+ // algorithm
+ private PartitionValueType partitionValue;
+
+ // List of partitioning algorithms to be applied to this subset to create
+ // further partitions, the algorithm at index 0 is the one used for this
+ // partition, all others are passed in to the constructors for
+ // sub-partitions
+ protected List<PartitionAlgorithm<?>> partitionAlgorithms;
+
+ // An initially empty list of sub-partitions created by the head element of
+ // the partition algorithm list
+ protected List<Partition<ItemType, ChildPartitionValueType, ?>> children;
+
+ // Path from this node back to the root, initialised on first access and
+ // cached
+ private List<Partition<ItemType, ?, ?>> partitionPath = null;
+
+ // For leaf partitions this is equal to the number of items in the member
+ // set, for all other partitions it is the sum of the item count of all
+ // child partitions
+ protected int itemCount = 0;
+
+ /**
+ * Construct a new Partition, this is used by the RootPartition and by this
+ * class to construct the recursively sub-divided partition structure based
+ * on the rules encapsulated by the partition algorithm list.
+ *
+ * @param parent
+ * parent partition of which this is a subset
+ * @param pa
+ * partition algorithm list, with the algorithm used to create
+ * child partitions of this one at position 0, if this list is
+ * empty this is a leaf partition.
+ * @param root
+ * reference to the RootPartition acting as the externally
+ * visible front-end to this structure
+ * @param pv
+ * the value which the parent's partition algorithm has assigned
+ * to this partition. This must be interpreted in the context of
+ * the parent's first partition algorithm for display and other
+ * purposes
+ */
+ protected Partition(Partition<ItemType, ?, PartitionValueType> parent,
+ List<PartitionAlgorithm<?>> pa, RootPartition<ItemType> root,
+ PartitionValueType pv) {
+ this.root = root;
+ this.members = new ArrayList<ItemType>();
+ this.parent = parent;
+ this.partitionValue = pv;
+ this.partitionAlgorithms = pa;
+ this.children = new ArrayList<Partition<ItemType, ChildPartitionValueType, ?>>();
+ }
+
+ /**
+ * Return the number of items below this node in the partition tree; in the
+ * case of leaf partitions this is the number of items in the member set,
+ * for non-leaf partitions it is the sum of the item count for all immediate
+ * child partitions.
+ */
+ public int getItemCount() {
+ return this.itemCount;
+ }
+
+ /**
+ * Sub-partitions of this partition are ordered based on a comparator over
+ * the child partition value type.
+ *
+ * @return a comparator over child partition value types, or null if no
+ * comparator has been specified (by default this returns null)
+ */
+ public Comparator<ChildPartitionValueType> getChildPartitionOrder() {
+ return this.childPartitionOrder;
+ }
+
+ /**
+ * Set a comparator for child partition ordering - if the supplied
+ * comparator is different to the current one this will also trigger a
+ * re-order of all child partitions and corresponding events in the root
+ * partition's tree view. In the current implementation this is the very
+ * broad 'tree structure changed' event for this node in the tree view.
+ *
+ * @param order
+ * a new comparator to order child partitions
+ */
+ public void setChildPartitionOrder(Comparator<ChildPartitionValueType> order) {
+ if (!order.equals(childPartitionOrder)) {
+ childPartitionOrder = order;
+ sortChildPartitions();
+ }
+ }
+
+ /**
+ * Return the parent partition of which this is a sub-partition, or null if
+ * this is the root partition.
+ */
+ public Partition<ItemType, ?, PartitionValueType> getParent() {
+ return this.parent;
+ }
+
+ /**
+ * The parent partition created this partition based on a particular value
+ * of a property of the members of the sub-partition. This returns that
+ * value, and is the result returned from the parent partition's first
+ * partition algorithm when run on all members of this partition or its
+ * direct or indirect sub-partitions.
+ */
+ public PartitionValueType getPartitionValue() {
+ return this.partitionValue;
+ }
+
+ @Override
+ public String toString() {
+ if (getParent() != null) {
+ // query type
+ String string = this.getParent().getPartitionAlgorithms().get(0)
+ .toString();
+ // result of query
+ String string2 = this.partitionValue.toString();
+ return string2 + " (" + getItemCount() + ")";
+ } else {
+ // This is for a root partition, loop through its children to return
+ // the correct number when running a new query
+ int items = 0;
+ for (Partition child : children) {
+ items = items + child.getItemCount();
+ }
+ String queryType = getPartitionAlgorithms().get(0).toString();
+ // return "Activities which match query = " + getItemCount();
+ return "Available activities (" + items + ")";
+ //+ ", query by "
+ // + queryType;
+ }
+ }
+
+ /**
+ * Return a list of Partition objects from the root (at index 0) to this
+ * node at the final position in the list. Computes the first time then
+ * caches, as it should be impossible for this to be modified without
+ * recreation of the entire structure from scratch.
+ */
+ public synchronized List<Partition<ItemType, ?, ?>> getPartitionPath() {
+ if (partitionPath == null) {
+ List<Partition<ItemType, ?, ?>> al = new ArrayList<Partition<ItemType, ?, ?>>();
+ Partition<ItemType, ?, ?> activePartition = this;
+ al.add(activePartition);
+ while (activePartition.getParent() != null) {
+ al.add(0, activePartition.getParent());
+ activePartition = activePartition.getParent();
+ }
+ partitionPath = al;
+ }
+ return partitionPath;
+ }
+
+ /**
+ * If this is a leaf partition, defined as one with an empty list of
+ * partition algorithms, then this method returns the set of all items which
+ * have been classified as belonging to this leaf partition. For non-leaf
+ * partitions it will return an empty set.
+ */
+ public final List<ItemType> getMembers() {
+ return Collections.unmodifiableList(this.members);
+ }
+
+ /**
+ * The list of partition algorithms applicable to this node (at index 0) and
+ * subsequent downstream sub-partitions of it. If this is empty then the
+ * partition is a leaf partition.
+ */
+ public final List<PartitionAlgorithm<?>> getPartitionAlgorithms() {
+ return Collections.unmodifiableList(partitionAlgorithms);
+ }
+
+ /**
+ * Sub-partitions of this partition defined by the partition algorithm at
+ * index 0 of the list. If this is a leaf partition this will always be
+ * empty.
+ */
+ public final List<Partition<ItemType, ChildPartitionValueType, ?>> getChildren() {
+ return Collections.unmodifiableList(children);
+ }
+
+ /**
+ * Inject an item into this partition, if there are partition algorithms in
+ * the partition algorithm list (i.e. this is not a leaf) this will
+ * recursively call the same method on child partitions or create new
+ * partitions where there are none that match the value from the partition
+ * algorithm. If this is a leaf partition the item is added to the member
+ * set. The list is sorted when adding an item and it is inserted in the
+ * appropriate place
+ *
+ * @param item
+ * the item to add to the partition structure.
+ */
+ @SuppressWarnings("unchecked")
+ protected synchronized void addItem(ItemType item) {
+ if (partitionAlgorithms.isEmpty()) {
+ // itemCount = 0;
+ // Allocate directly to member set, no further partitioning
+ members.add(item);
+ Collections.sort(members);
+ int indexOf = members.indexOf(item);
+ // root.treeNodesInserted(new TreeModelEvent(this, getTreePath(),
+ // new int[] { members.size() - 1 }, new Object[] { item }));
+ root.treeNodesInserted(new TreeModelEvent(this, getTreePath(),
+ new int[] { indexOf }, new Object[] { item }));
+ // Increment item count for all partitions in the partition path
+ for (Partition<ItemType, ?, ?> p : getPartitionPath()) {
+ synchronized (p) {
+ p.itemCount++;
+ root.treeNodesChanged(new TreeModelEvent(this, p
+ .getTreePath()));
+ }
+ }
+
+ // Cache the storage of this item to this partition in the root
+ // partition for more efficient removal if required (saves having to
+ // search the entire partition tree, although that wouldn't be too
+ // painful if it was required this is faster at the cost of a few
+ // bytes of memory)
+ root.itemStoredAt(item, this);
+ // TODO - when the tree model covers items on the leaf nodes we'll
+ // want to message it here as well.
+ } else {
+ PartitionAlgorithm<ChildPartitionValueType> pa;
+ pa = (PartitionAlgorithm<ChildPartitionValueType>) partitionAlgorithms
+ .get(0);
+ ChildPartitionValueType pvalue = pa.allocate(item, root
+ .getPropertyExtractorRegistry());
+ // FIXME not sure how to do this since you seem to have to add the
+ // items to the partition if you want to then search them again,
+ // maybe you need a non-showing partition or something?
+ // //if it is a failed search then don't bother adding to the
+ // partition
+ // if (pvalue.toString().equalsIgnoreCase("No match")) {
+ // return;
+ // }
+ // See if there's a partition with this value already in the child
+ // partition list
+ for (Partition<ItemType, ChildPartitionValueType, ?> potentialChild : children) {
+ if (potentialChild.getPartitionValue().equals(pvalue)) {
+ potentialChild.addItem(item);
+ return;
+ }
+ }
+ // If not we have to create a new sub-partition
+ List<PartitionAlgorithm<?>> tail = new ArrayList<PartitionAlgorithm<?>>();
+ for (int i = 1; i < partitionAlgorithms.size(); i++) {
+ tail.add(partitionAlgorithms.get(i));
+ }
+ Partition<ItemType, ChildPartitionValueType, ?> newPartition = new Partition(
+ this, tail, this.root, pvalue);
+ // Insert the new partition in the correct place according to the
+ // comparator currently installed, or at the end if none exists or
+ // the list is empty
+ if (childPartitionOrder == null || children.isEmpty()) {
+ children.add(newPartition);
+ root.treeNodesInserted(new TreeModelEvent(this, getTreePath(),
+ new int[] { children.indexOf(newPartition) },
+ new Object[] { newPartition }));
+ } else {
+ boolean foundIndex = false;
+ for (int i = 0; i < children.size(); i++) {
+ ChildPartitionValueType existingPartitionValue = children
+ .get(i).getPartitionValue();
+ if (childPartitionOrder.compare(pvalue,
+ existingPartitionValue) < 0) {
+ children.add(i, newPartition);
+ root.treeNodesInserted(new TreeModelEvent(this,
+ getTreePath(), new int[] { i },
+ new Object[] { newPartition }));
+ if (i != 0) {
+ root.treeStructureChanged(new TreeModelEvent(this,
+ getTreePath()));
+ }
+ foundIndex = true;
+ break;
+ }
+ }
+ if (!foundIndex) {
+ // Fallen off the end of the array without finding something
+ // with greater index than the new partition so we add it at
+ // the
+ // end (by definition this is the largest value according to
+ // the
+ // comparator)
+ children.add(newPartition);
+ root.treeNodesInserted(new TreeModelEvent(this,
+ getTreePath(), new int[] { children
+ .indexOf(newPartition) },
+ new Object[] { newPartition }));
+ }
+ }
+ // Add the item to the new partition to trigger creation of any
+ // sub-partitions required
+ newPartition.addItem(item);
+ }
+ }
+
+ /**
+ * Remove an item from the member set
+ *
+ * @param item
+ * the item to remove
+ */
+ protected void removeMember(ItemType item) {
+ this.members.remove(item);
+ }
+
+ /**
+ * Re-order the child partitions based on the comparator, if no comparator
+ * has been defined this method does nothing. Tree structure changed
+ * messages are fired from this node in the tree view if the comparator is
+ * defined even if no nodes have been changed (lazy but not too much of an
+ * issue I suspect)
+ */
+ protected synchronized final void sortChildPartitions() {
+ if (this.childPartitionOrder == null) {
+ // Can't do anything unless the comparator is set appropriately
+ return;
+ }
+ Comparator<Partition<ItemType, ChildPartitionValueType, ?>> comparator = new Comparator<Partition<ItemType, ChildPartitionValueType, ?>>() {
+ public int compare(
+ Partition<ItemType, ChildPartitionValueType, ?> o1,
+ Partition<ItemType, ChildPartitionValueType, ?> o2) {
+ // FIXME is this really safe to do? It's fairly specific to our
+ // case. Doesn't seem very generic
+ if (o1.getPartitionValue().toString().equalsIgnoreCase(
+ "no value")) {
+ // No value so put it to the end
+ return 1;
+ }
+ return childPartitionOrder.compare(o1.getPartitionValue(), o2
+ .getPartitionValue());
+ }
+ };
+ Collections.<Partition<ItemType, ChildPartitionValueType, ?>> sort(
+ children, comparator);
+ // Message the root that the node structure under this node has changed
+ // (this is a bit lazy and we could almost certainly be more clever here
+ // as the nodes have been removed and added to re-order them)
+ root.treeStructureChanged(new TreeModelEvent(this, getTreePath()));
+ }
+
+ /**
+ * Return a TreePath object with this node as the final entry in the path
+ */
+ protected final synchronized TreePath getTreePath() {
+ return new TreePath(getPartitionPath().toArray());
+ }
+
+ // public void sortItems() {
+ // System.out.println("sorting the items");
+ // synchronized (members) {
+ // List<ItemType> oldOrder = new ArrayList<ItemType>(members);
+ // Collections.sort(oldOrder);
+ //
+ // for (ItemType item : oldOrder) {
+ // removeMember(item);
+ // }
+ // for (ItemType item : oldOrder) {
+ // addItem(item);
+ // }
+ // }
+ //
+ // }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PartitionAlgorithm.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PartitionAlgorithm.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PartitionAlgorithm.java
new file mode 100644
index 0000000..b7b80f6
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PartitionAlgorithm.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.partition;
+
+/**
+ * Interface for classes which can partition a set of objects into subsets according
+ * to some embedded partitioning rule
+ *
+ * @author Tom Oinn
+ * @author Stuart Owen
+ *
+ * @param ValueType
+ * the java type of values used to represent the distinct partitions
+ * created by this algorithm, in many cases these will be primitive
+ * java types such as String but they could represent ranges of
+ * values in the case of binning of continuous quantities etc.
+ */
+public interface PartitionAlgorithm<ValueType> {
+
+ /**
+ * Given an object to classify return the value of the partition into which
+ * the object falls.
+ *
+ * @param newItem
+ * @return
+ */
+ ValueType allocate(Object newItem, PropertyExtractorRegistry reg);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PartitionAlgorithmSetSPI.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PartitionAlgorithmSetSPI.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PartitionAlgorithmSetSPI.java
new file mode 100644
index 0000000..330a11a
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PartitionAlgorithmSetSPI.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.partition;
+
+import java.util.Set;
+
+/**
+ * An SPI interface that provides access to a Set of partition algorithms.
+ *
+ * @author Stuart Owen
+ *
+ */
+public interface PartitionAlgorithmSetSPI {
+ /**
+ * @return a Set of PartitionAlgorithms
+ */
+ public Set<PartitionAlgorithm<?>> getPartitionAlgorithms();
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PropertyExtractorRegistry.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PropertyExtractorRegistry.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PropertyExtractorRegistry.java
new file mode 100644
index 0000000..229aa87
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PropertyExtractorRegistry.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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.partition;
+
+import java.util.Map;
+
+/**
+ * Convenience to allow caching of property extractors. Implementations should
+ * scan for available PropertyExtractorSPI implementations and use these to get
+ * the properties for each target, caching as applicable.
+ *
+ * @author Tom Oinn
+ *
+ */
+public interface PropertyExtractorRegistry {
+
+ public Map<String, Object> getAllPropertiesFor(Object target);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PropertyExtractorSPI.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PropertyExtractorSPI.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PropertyExtractorSPI.java
new file mode 100644
index 0000000..130f2b7
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/PropertyExtractorSPI.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.partition;
+
+import java.util.Map;
+
+/**
+ * SPI for classes which can extract or infer a set of named properties from a
+ * target object.
+ *
+ * @author Tom Oinn
+ *
+ */
+public interface PropertyExtractorSPI {
+
+ /**
+ * Given a target object extract or infer the property map from it. If the
+ * target is one which this plugin cannot act on then simply return an empty
+ * map.
+ *
+ * @param target
+ * @return
+ */
+ Map<String, Object> extractProperties(Object target);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/Query.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/Query.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/Query.java
new file mode 100644
index 0000000..c8f3cb6
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/Query.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.partition;
+
+import java.util.Date;
+
+/**
+ * Defines a query which can be re-run and which presents a set view on its
+ * results. The Query is intended to represent both the old Taverna scavenger
+ * class (which were queries in all but name) and new integration with external
+ * search-able repositories in which case the term 'query' is a more literal
+ * description.
+ *
+ * @author Tom Oinn
+ *
+ * @param <ItemType>
+ * the parameterised type of the result set of the query
+ */
+public interface Query<ItemType> extends SetModel<ItemType> {
+
+ /**
+ * Run the query. The query has internal state from any previous runs
+ * (including the initial empty state) and will notify all listeners from
+ * the SetModel interface of any items that are present in the new query
+ * result and not in the old state or vice versa. It also updates the query
+ * time to be the current time.
+ */
+ public void doQuery();
+
+ /**
+ * Returns the time at which the query was last invoked, or null if the
+ * query has not been invoked yet.
+ *
+ * @return time of last call to doQuery or null if this hasn't happened yet.
+ */
+ public Date getLastQueryTime();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/RootPartition.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/RootPartition.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/RootPartition.java
new file mode 100644
index 0000000..64edfd8
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/RootPartition.java
@@ -0,0 +1,394 @@
+/*******************************************************************************
+ * 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.partition;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.SwingUtilities;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+
+/**
+ * Subclass of Partition acting as the public access point for the partition
+ * structure. Exposes a TreeModel for use with a UI.
+ *
+ * @author Tom Oinn
+ *
+ * @param <ItemType>
+ * all items added to this partition must cast to this type
+ */
+public class RootPartition<ItemType extends Comparable> extends
+ Partition<ItemType, Object, Object> implements TreeModel {
+
+ // Used to track where we ended up putting items with the addOrUpdateItem
+ // method, this makes checking for duplicate items, reclassification and
+ // removal of partitions much faster at the expense of a few bytes of memory
+ private Map<ItemType, Partition<ItemType, ?, ?>> itemToLeafPartition;
+
+ private PropertyExtractorRegistry propertyExtractorRegistry;
+
+ private final SetModelChangeListener<ItemType> setChangeListener = new SetModelChangeListener<ItemType>() {
+
+ private List<Query<?>> queryList = new ArrayList<Query<?>>();
+
+ public void itemsWereAdded(Set<ItemType> newItems) {
+ for (ItemType item : newItems) {
+ addOrUpdateItem(item);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void itemsWereRemoved(Set<Object> itemsRemoved) {
+ for (Object item : itemsRemoved) {
+ try {
+ removeItem((ItemType) item);
+ } catch (ClassCastException cce) {
+ // Obviously wasn't the right type of item but that means it
+ // couldn't have been added in the first place so we can
+ // safely ignore this.
+ }
+ }
+ }
+
+ public void addQuery(Query<?> query) {
+ queryList.add(query);
+ }
+
+ public List<Query<?>> getQueries() {
+ return queryList;
+ }
+
+ };
+
+ /**
+ * Build a new empty root partition with the specified list of partition
+ * algorithm implementations used to recursively allocate new data items to
+ * the sub-partitions below this one on addition
+ *
+ * @param pa
+ */
+ public RootPartition(List<PartitionAlgorithm<?>> pa,
+ PropertyExtractorRegistry per) {
+ super(null, pa, null, null);
+ this.root = this;
+ this.propertyExtractorRegistry = per;
+ this.itemToLeafPartition = new HashMap<ItemType, Partition<ItemType, ?, ?>>();
+ }
+
+ /**
+ * The root partition comes with a convenience implementation of
+ * SetModelChangeListener which can be used to attach it to a compliant
+ * instance of SetModel (assuming the item types match). This allows the
+ * SetModel to act as the backing data store for the partition - as Query
+ * and the various subset / set union operators also implement this it
+ * provides a relatively simple mechanism to link multiple sets of data to
+ * this partition.
+ */
+ public SetModelChangeListener<ItemType> getSetModelChangeListener() {
+ return this.setChangeListener;
+ }
+
+ /**
+ * Alter the list of partition algorithms which drive the construction of
+ * the partitions. Calling this effectively forces a complete rebuild of the
+ * tree structure which is an expensive operation so be careful when you use
+ * it.
+ *
+ * @param pa
+ * a new list of PartitionAlgorithmSPI instances to use as the
+ * basis for the partition structure.
+ */
+ public synchronized void setPartitionAlgorithmList(
+ List<PartitionAlgorithm<?>> pa) {
+ if (pa.equals(this.partitionAlgorithms)) {
+ // At the least this checks for reference equality, although I'm not
+ // sure it does much more than that. TODO - replace this with a
+ // smarter check to see whether the list has really changed, doing a
+ // full re-build is expensive.
+ return;
+ }
+ // First create a copy of the keyset containing all the items we've
+ // added to this point.
+ Set<ItemType> itemsToAdd = new HashSet<ItemType>(itemToLeafPartition
+ .keySet());
+ this.partitionAlgorithms = pa;
+ this.children.clear();
+ this.itemToLeafPartition.clear();
+ treeStructureChanged(new TreeModelEvent(this, getTreePath()));
+ for (ItemType item : itemsToAdd) {
+ addOrUpdateItem(item);
+ }
+ sortChildPartitions();
+ }
+
+ /**
+ * Add a new item to the partition structure. If the item already exists
+ * this is interpreted as a request to reclassify according to properties
+ * which may have changed. This is not the same as a reclassification due to
+ * modification of the partition algorithm list, and just refers to the
+ * specified item. If the item exists already and its classification is
+ * changed the model will be notified with a removal event from the previous
+ * location and the item will be added as usual immediately afterwards.
+ */
+ public synchronized void addOrUpdateItem(ItemType item) {
+ // First check whether the item is already stored
+ if (itemToLeafPartition.containsKey(item)) {
+ // request to reclassify item.
+ List<Partition<ItemType, ?, ?>> partitions = itemToLeafPartition
+ .get(item).getPartitionPath();
+ // partitions[i].getPartitionValue is the result of running
+ // getPartitionAlgorithms[i-1] on the item, we run through the array
+ // until either we hit the end (no reclassification) or the item
+ // classifies differently in which case we remove and re-add it.
+ for (int i = 1; i < partitions.size(); i++) {
+ PartitionAlgorithm<?> pa = getPartitionAlgorithms().get(
+ i - 1);
+ Object existingValue = partitions.get(i).getPartitionValue();
+ Object reclassifiedValue = pa.allocate(item,
+ getPropertyExtractorRegistry());
+ if (existingValue.equals(reclassifiedValue) == false) {
+ // Items classify differently, remove it
+ removeItem(item);
+ // ...and add it back again, forcing reclassification
+ super.addItem(item);
+ return;
+ }
+ }
+ // return as the item wasn't changed.
+ return;
+ } else {
+ // Value wasn't already in the map so we just add it as usual
+ super.addItem(item);
+ }
+
+ }
+
+ /**
+ * Remove an item from the partition structure, if this leaves any
+ * partitions with zero item count they are removed as well to keep things
+ * tidy.
+ *
+ * @param item
+ * the item to remove from the partition structure. If this isn't
+ * present in the structure this method does nothing along the
+ * lines of the collections API.
+ */
+ public synchronized void removeItem(ItemType item) {
+ Partition<ItemType, ?, ?> partition = itemToLeafPartition.get(item);
+ if (partition != null) {
+ // Remove the item from the leaf partition
+ int previousIndex = partition.getMembers().indexOf(item);
+ TreePath pathToPartition = partition.getTreePath();
+ //partition.removeMember(item);
+ for (Partition<ItemType, ?, ?> parentPathElement : partition
+ .getPartitionPath()) {
+ // Notify path to root that the number of members
+ // has changed and it should update the renderers of
+ // any attached trees
+ treeNodesChanged(new TreeModelEvent(this, parentPathElement
+ .getTreePath()));
+ }
+ partition.removeMember(item);
+ treeNodesRemoved(new TreeModelEvent(this, pathToPartition,
+ new int[] { previousIndex }, new Object[] { item }));
+ // Traverse up the partition path and decrement the item count. If
+ // any item count becomes zero we mark this as a partition to
+ // remove, then at the end we remove the highest level one (so we
+ // only have to send a single delete event to the tree view)
+ for (Partition<ItemType, ?, ?> p : partition.getPartitionPath()) {
+ synchronized (p) {
+ p.itemCount--;
+ if (p.getItemCount() == 0 && p != this) {
+ // Can remove this node, all nodes after this will by
+ // definition have item count of zero. The exception is
+ // if this is the root node, in which case we just
+ // ignore it and move on to the next child. This avoids
+ // deleting the root, which is generally not a smart
+ // thing to do to a tree.
+ Partition<ItemType, ?, ?> parent = p.getParent();
+ int indexInParent = getIndexOfChild(parent, p);
+ parent.children.remove(indexInParent);
+ treeNodesRemoved(new TreeModelEvent(this, parent
+ .getTreePath(), new int[] { indexInParent },
+ new Object[] { p }));
+
+ break;
+ }
+ }
+ }
+ itemToLeafPartition.remove(item);
+ }
+ treeStructureChanged(new TreeModelEvent(this,getTreePath()));
+ }
+
+ /**
+ * Called by a leaf Partition when it has stored an item in its member set,
+ * used to keep track of where items have been stored to make removal more
+ * efficient.
+ */
+ void itemStoredAt(ItemType item, Partition<ItemType, ?, ?> partition) {
+ itemToLeafPartition.put(item, partition);
+ }
+
+ // ---------------------//
+ // TreeModel interfaces //
+ // ---------------------//
+ private List<TreeModelListener> treeListeners = new ArrayList<TreeModelListener>();
+
+ @SuppressWarnings("unchecked")
+ public synchronized Object getChild(Object parent, int index) {
+ if (parent instanceof Partition) {
+ Partition<ItemType, ?, ?> p = (Partition<ItemType, ?, ?>) parent;
+ if (p.getMembers().isEmpty() == false) {
+ if (index < 0 || index >= p.getMembers().size()) {
+ return null;
+ } else {
+ return p.getMembers().get(index);
+ }
+ } else {
+ if (index < 0 || index >= p.getChildren().size()) {
+ return null;
+ } else {
+ return p.getChildren().get(index);
+ }
+ }
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized int getChildCount(Object parent) {
+ if (parent instanceof Partition) {
+ Partition<ItemType, ?, ?> p = (Partition<ItemType, ?, ?>) parent;
+ if (p.getMembers().isEmpty() == false) {
+ return p.getMembers().size();
+ }
+ return p.getChildren().size();
+ }
+ return 0;
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized int getIndexOfChild(Object parent, Object child) {
+ if (parent != null && child != null && parent instanceof Partition
+ && child instanceof Partition) {
+ Partition<ItemType, ?, ?> p = (Partition<ItemType, ?, ?>) parent;
+ Partition<ItemType, ?, ?> c = (Partition<ItemType, ?, ?>) child;
+ if (p.root == c.root && p.root == this) {
+ // Parent and child must both be members of this tree structure
+ return p.getChildren().indexOf(child);
+ }
+ } else if (parent != null && child != null
+ && parent instanceof Partition) {
+ Partition<ItemType, ?, ?> p = (Partition<ItemType, ?, ?>) parent;
+ return p.getMembers().indexOf(child);
+ }
+ return -1;
+
+ }
+
+ public Object getRoot() {
+ // The root partition is also the root of the tree model
+ return this;
+ }
+
+ public boolean isLeaf(Object node) {
+ // No leaves at the moment as we're only considering partitions which
+ // are by definition not leaves (the items within the last partition are
+ // but at the moment we're not including them in the tree model)
+ return (!(node instanceof Partition));
+ }
+
+ public void removeTreeModelListener(TreeModelListener l) {
+ treeListeners.remove(l);
+ }
+
+ public void addTreeModelListener(TreeModelListener l) {
+ if (treeListeners.contains(l) == false) {
+ treeListeners.add(l);
+ }
+ }
+
+ public void valueForPathChanged(TreePath path, Object newValue) {
+ // Ignore this, the tree values are never changed by the user in this
+ // implementation so we don't have to do anything
+ }
+
+ // -------------------------------------------------------//
+ // Tree event forwarding helper methods used by Partition //
+ // -------------------------------------------------------//
+
+ void treeNodesChanged(final TreeModelEvent e) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ for (TreeModelListener listener : new ArrayList<TreeModelListener>(
+ treeListeners)) {
+ listener.treeNodesChanged(e);
+ }
+ }
+ });
+ }
+
+ void treeNodesInserted(final TreeModelEvent e) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ for (TreeModelListener listener : new ArrayList<TreeModelListener>(
+ treeListeners)) {
+ listener.treeNodesInserted(e);
+ }
+ }
+ });
+ }
+
+ void treeNodesRemoved(final TreeModelEvent e) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ for (TreeModelListener listener : new ArrayList<TreeModelListener>(
+ treeListeners)) {
+ listener.treeNodesRemoved(e);
+ }
+ }
+ });
+ }
+
+ void treeStructureChanged(final TreeModelEvent e) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ for (TreeModelListener listener : new ArrayList<TreeModelListener>(
+ treeListeners)) {
+ listener.treeStructureChanged(e);
+ }
+ }
+ });
+ }
+
+ public PropertyExtractorRegistry getPropertyExtractorRegistry() {
+ return this.propertyExtractorRegistry;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/SetModel.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/SetModel.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/SetModel.java
new file mode 100644
index 0000000..393d697
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/SetModel.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.partition;
+
+import java.util.Set;
+
+/**
+ * Extension of the java Set interface with the addition of change listener
+ * support. Intended to be plugged into the RootPartition class so the partition
+ * is synchronized with the set membership.
+ *
+ * @author Tom Oinn
+ *
+ * @param <ItemType>
+ * the parameterised type of the set
+ */
+public interface SetModel<ItemType> extends Set<ItemType> {
+
+ /**
+ * Add a listener to be notified of change events on the set's membership
+ *
+ * @param listener
+ */
+ public void addSetModelChangeListener(
+ SetModelChangeListener<ItemType> listener);
+
+ /**
+ * Remove a previously registered change listener
+ *
+ * @param listener
+ */
+ public void removeSetModelChangeListener(
+ SetModelChangeListener<ItemType> listener);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/SetModelChangeListener.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/SetModelChangeListener.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/SetModelChangeListener.java
new file mode 100644
index 0000000..176eb7c
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/SetModelChangeListener.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.partition;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Handler for change events on a SetModel instance
+ *
+ * @author Tom Oinn
+ *
+ */
+public interface SetModelChangeListener<ItemType> {
+
+ public void itemsWereAdded(Set<ItemType> newItems);
+
+ public void itemsWereRemoved(Set<Object> itemsRemoved);
+
+ public List<Query<?>> getQueries();
+
+ public void addQuery(Query<?> query);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/algorithms/CustomPartitionAlgorithm.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/algorithms/CustomPartitionAlgorithm.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/algorithms/CustomPartitionAlgorithm.java
new file mode 100644
index 0000000..b6a3eea
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/algorithms/CustomPartitionAlgorithm.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.partition.algorithms;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sf.taverna.t2.partition.PartitionAlgorithm;
+import net.sf.taverna.t2.partition.PropertyExtractorRegistry;
+
+/**
+ * Takes a custom search term and checks against the properties eg
+ * "operation" of each of the available items. Adds the item to the activity
+ * palette if it matches
+ *
+ * @author Ian Dunlop
+ *
+ */
+public class CustomPartitionAlgorithm implements PartitionAlgorithm<Object> {
+
+ private String searchValue;
+ private List<String> properties;
+ private static String NO_SEARCH = "No match";
+ private static String MATCHING_ITEMS = "Activities with a matching property";
+
+ public String getSearchValue() {
+ return searchValue;
+ }
+
+ public void setSearchValue(String searchValue) {
+ this.searchValue = searchValue;
+ }
+
+ public CustomPartitionAlgorithm() {
+ properties = new ArrayList<String>();
+ }
+
+ public CustomPartitionAlgorithm(String searchValue) {
+ super();
+ this.searchValue = searchValue;
+ // this.propertyName = propertyName;
+ properties = new ArrayList<String>();
+ }
+
+ public void addProperty(String propertyValue) {
+ properties.add(propertyValue);
+ }
+
+ /**
+ * Checks against the items property to see if it contains the search term.
+ * Search each of the properties in {@link #properties} in turn
+ */
+ public Object allocate(Object newItem, PropertyExtractorRegistry reg) {
+ for (String property : properties) {
+ Object propertyValue = reg.getAllPropertiesFor(newItem).get(
+ property);
+ String itemString = newItem.toString();
+ //search all the properties first
+ if (propertyValue != null) {
+ if (((String) propertyValue).contains(getSearchValue()
+ .toLowerCase())) {
+ return MATCHING_ITEMS;
+ }
+ }
+ //then the name of the item
+ if (itemString.toLowerCase().contains(
+ getSearchValue().toLowerCase())) {
+ return MATCHING_ITEMS;
+ }
+ }
+ return NO_SEARCH;
+
+ }
+
+ @Override
+ public String toString() {
+ return "search term=" + this.searchValue;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/algorithms/LiteralValuePartitionAlgorithm.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/algorithms/LiteralValuePartitionAlgorithm.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/algorithms/LiteralValuePartitionAlgorithm.java
new file mode 100644
index 0000000..b703d40
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/algorithms/LiteralValuePartitionAlgorithm.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * 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.partition.algorithms;
+
+import net.sf.taverna.t2.partition.PartitionAlgorithm;
+import net.sf.taverna.t2.partition.PropertyExtractorRegistry;
+
+/**
+ * A naive partition algorithm that simply returns the property value it's been
+ * configured to use from the property getter.
+ *
+ * @author Tom
+ *
+ */
+public class LiteralValuePartitionAlgorithm implements
+ PartitionAlgorithm<Object> {
+
+ private String propertyName = null;
+
+ private static String NO_PROPERTY = "No value";
+
+ /**
+ * Default constructor. The property name defaults to null, and needs setting using getPropertyName
+ */
+ public LiteralValuePartitionAlgorithm() {
+
+ }
+
+ /**
+ * Constructor that initialised the LiteralValuePartitionAlgorithm with a property name
+ *
+ * @param propertyName
+ */
+ public LiteralValuePartitionAlgorithm(String propertyName) {
+ super();
+ this.propertyName = propertyName;
+ }
+
+ public Object allocate(Object newItem, PropertyExtractorRegistry reg) {
+ if (propertyName == null) {
+ return NO_PROPERTY;
+ }
+ else {
+ Object propertyValue = reg.getAllPropertiesFor(newItem).get(propertyName);
+ if (propertyValue == null) {
+ return NO_PROPERTY;
+ }
+ else {
+ return propertyValue;
+ }
+ }
+ }
+
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ public void setPropertyName(String propertyName) {
+ this.propertyName = propertyName;
+ }
+
+
+
+ /**
+ * @return true if obj is a LiteralValuePartionAlgorithm and the property names match
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof LiteralValuePartitionAlgorithm) {
+ LiteralValuePartitionAlgorithm alg = (LiteralValuePartitionAlgorithm)obj;
+ return getPropertyName().equals(alg.getPropertyName());
+ }
+ else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return getPropertyName().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return this.propertyName;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/ui/PartitionAlgorithmListEditor.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/ui/PartitionAlgorithmListEditor.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/ui/PartitionAlgorithmListEditor.java
new file mode 100644
index 0000000..9c05c44
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/ui/PartitionAlgorithmListEditor.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * 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.partition.ui;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import net.sf.taverna.t2.partition.PartitionAlgorithm;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.GeneralPath;
+import java.util.List;
+
+public class PartitionAlgorithmListEditor extends JPanel {
+
+ // Serial version ID
+ private static final long serialVersionUID = 8206805090698009524L;
+
+ // Index of currently selected 'tab' or -1 if none selected
+ private int selectedIndex = 1;
+
+ // List of partition algorithm instances acting as the model for this
+ // component
+ private List<PartitionAlgorithm<?>> paList;
+
+ private int cornerSep = 8;
+ private int labelHorizontalPad = 10;
+ private int labelBottomPad = 2;
+ private int labelTopPad = 4;
+ private float selectedStrokeWidth = 3f;
+
+ public List<PartitionAlgorithm<?>> getPartitionAlgorithmList() {
+ return null;
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ if (paList.isEmpty()) {
+ return new Dimension(0, 16 + labelBottomPad + labelTopPad);
+ } else {
+ return new Dimension(0, (int) new Tab(getLabelForPA(paList.get(0)))
+ .getPreferredSize().getHeight());
+ }
+ }
+
+ public PartitionAlgorithmListEditor(
+ List<PartitionAlgorithm<?>> currentState) {
+ super();
+ this.paList = currentState;
+ }
+
+ protected JLabel getLabelForPA(PartitionAlgorithm<?> pa) {
+ return new JLabel("Test...");
+ }
+
+ protected Color getBorderColorForPA(PartitionAlgorithm<?> pa) {
+ return Color.black;
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ Graphics2D g2d = (Graphics2D) g.create();
+ // Enable anti-aliasing for the curved lines
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ int selectedStartsAt = 0;
+ int selectedEndsAt = 0;
+ Color frameColor = null;
+ int cumulativeTranslation = 0;
+
+ super.paintComponent(g2d);
+
+ for (int i = 0; i < paList.size(); i++) {
+
+ Tab t = new Tab(getLabelForPA(paList.get(i)));
+ t.setBackground(new Color(150, 150, 255));
+ t.setSelected(i == selectedIndex);
+ int width = (int) (t.getPreferredSize()).getWidth();
+ t.setSize(new Dimension(width, getHeight()));
+ t.paint(g2d);
+
+ if (i < selectedIndex) {
+ selectedStartsAt += width;
+ } else if (i == selectedIndex) {
+ selectedEndsAt = selectedStartsAt + width;
+ frameColor = t.getBackground();
+ }
+ cumulativeTranslation += width;
+ g2d.translate(width, 0);
+ }
+
+
+ // Reset the transform
+ g2d.translate(-cumulativeTranslation, 0);
+ if (selectedIndex > 0) {
+ g2d.setStroke(new BasicStroke(selectedStrokeWidth, BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_MITER));
+ int height = (int)(getHeight() - selectedStrokeWidth/2);
+ // Render the selected index line...
+ if (frameColor != null) {
+ g2d.setPaint(frameColor.darker());
+ }
+ GeneralPath path = new GeneralPath();
+ path.moveTo(0, height);
+ path.lineTo(selectedStartsAt, height);
+ path.lineTo(selectedStartsAt, cornerSep);
+ path.curveTo(selectedStartsAt, cornerSep / 2, selectedStartsAt
+ + cornerSep / 2, 0, selectedStartsAt + cornerSep, 0);
+ path.lineTo(selectedEndsAt - cornerSep, 0);
+ path.curveTo(selectedEndsAt - cornerSep / 2, 0, selectedEndsAt,
+ cornerSep / 2, selectedEndsAt, cornerSep);
+ path.lineTo(selectedEndsAt, height);
+ path.lineTo(getWidth(), height);
+
+ g2d.draw(path);
+ }
+ g2d.dispose();
+ }
+
+ @SuppressWarnings("serial")
+ // Renderer for a single tab in the partition algorithm list, used as a
+ // rubber stamp for a single tab in the tab list.
+ class Tab extends JComponent {
+
+ // Label to use to render tab contents
+ private JLabel label;
+
+ // If this is selected then we don't draw the stroke as it'll be drawn
+ // on later.
+ private boolean selected = false;
+
+ @Override
+ // Always false as we don't render the corners
+ public boolean isOpaque() {
+ return false;
+ }
+
+ public void setSelected(boolean b) {
+ this.selected = b;
+
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ Dimension d = label.getPreferredSize();
+ return new Dimension((int) (d.getWidth()) + labelHorizontalPad * 2,
+ ((int) d.getHeight()) + labelBottomPad + labelTopPad);
+ }
+
+ protected Tab(JLabel label) {
+ super();
+ this.label = label;
+ }
+
+ @Override
+ public void setBackground(Color colour) {
+ label.setBackground(colour);
+ }
+
+ @Override
+ public Color getBackground() {
+ return label.getBackground();
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ Graphics2D g2d = (Graphics2D) g.create();
+
+ int width = getWidth();
+ int height = getHeight();
+
+ // Create a general path to draw the tab shape
+ g2d.setPaint(label.getBackground());
+ GeneralPath path = new GeneralPath();
+ path.moveTo(0, height);
+ path.lineTo(0, cornerSep);
+ path.curveTo(0, cornerSep / 2, cornerSep / 2, 0, cornerSep, 0);
+ path.lineTo(width - cornerSep, 0);
+ path.curveTo(width - cornerSep / 2, 0, width, cornerSep / 2, width,
+ cornerSep);
+ path.lineTo(width, height);
+ path.closePath();
+ g2d.fill(path);
+ if (!selected) {
+ g2d.setPaint(label.getBackground().darker());
+ g2d.draw(path);
+ }
+
+ label.setSize(width - labelHorizontalPad * 2, height
+ - (labelBottomPad + labelTopPad));
+ g2d.translate(labelHorizontalPad, labelTopPad);
+ label.paint(g2d);
+ g2d.translate(-labelHorizontalPad, -labelTopPad);
+
+ g2d.dispose();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/f676ef35/taverna-partition/src/main/java/net/sf/taverna/t2/partition/ui/TableTreeNodeColumn.java
----------------------------------------------------------------------
diff --git a/taverna-partition/src/main/java/net/sf/taverna/t2/partition/ui/TableTreeNodeColumn.java b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/ui/TableTreeNodeColumn.java
new file mode 100644
index 0000000..c6b4b36
--- /dev/null
+++ b/taverna-partition/src/main/java/net/sf/taverna/t2/partition/ui/TableTreeNodeColumn.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.partition.ui;
+
+import java.awt.Color;
+import java.awt.Component;
+
+/**
+ * A column used in the tree part of the table tree node renderer
+ *
+ * @author Tom Oinn
+ *
+ */
+public interface TableTreeNodeColumn {
+
+ /**
+ * Get a string to use as the header text
+ *
+ * @return
+ */
+ public String getShortName();
+
+ /**
+ * Get a descriptive string for tooltips etc.
+ *
+ * @return
+ */
+ public String getDescription();
+
+ /**
+ * Given a node value render the appropriate property for this column
+ *
+ * @param value
+ * @return
+ */
+ public Component getCellRenderer(Object value);
+
+ /**
+ * Return the width in pixels for this column
+ *
+ * @return
+ */
+ public int getColumnWidth();
+
+ /**
+ * Get a header colour - the actual column colour will be a stripe of the
+ * result of applying the lighter operator twice and once to this colour.
+ */
+ public Color getColour();
+
+}