blob: bd93be5ba33c1ba770939de9797067a742984b8a [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package net.sf.taverna.t2.workflowmodel.processor.iteration;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import net.sf.taverna.t2.invocation.Completion;
import net.sf.taverna.t2.workflowmodel.WorkflowStructureException;
import net.sf.taverna.t2.workflowmodel.processor.activity.Job;
/**
* Abstract superclass for implementations of IterationStrategyNode, adds logic
* to connect nodes together and convenience methods to push jobs and completion
* events up to the parent node.
*
* @author Tom Oinn
* @author Stian Soiland-Reyes
*
*/
public abstract class AbstractIterationStrategyNode implements
IterationStrategyNode {
private List<IterationStrategyNode> children = new ArrayList<IterationStrategyNode>();
private IterationStrategyNode parent = null;
/**
* Implement TreeNode
*/
public final synchronized Enumeration<IterationStrategyNode> children() {
return new Vector<IterationStrategyNode>(children).elements();
}
/**
* Clear the child list and parent of this node
*/
public final synchronized void clear() {
for (IterationStrategyNode child : children) {
child.setParent(null);
}
children.clear();
this.parent = null;
}
/**
* Implement TreeNode
*/
public boolean getAllowsChildren() {
return true;
}
/**
* Implement TreeNode
*/
public final synchronized IterationStrategyNode getChildAt(int position) {
return children.get(position);
}
/**
* Implement TreeNode
*/
public final int getChildCount() {
return children.size();
}
/**
* Implements IterationStrategyNode
*/
public final synchronized List<IterationStrategyNode> getChildren() {
return new ArrayList<IterationStrategyNode>(this.children);
}
/**
* Implement TreeNode
*/
public final synchronized int getIndex(TreeNode node) {
return children.indexOf(node);
}
/**
* Implement TreeNode
*/
public final IterationStrategyNode getParent() {
return parent;
}
public synchronized void insert(MutableTreeNode child) {
insert(child, getChildCount());
}
public synchronized void insert(MutableTreeNode child, int index) {
if (!getAllowsChildren()) {
throw new IllegalStateException("Node does not allow children");
}
if (!(child instanceof IterationStrategyNode)) {
throw new IllegalArgumentException(
"Child not an instance of IterationStrategyNode: " + child);
}
if (child == this) {
throw new IllegalArgumentException("Can't be it's own parent");
}
// Check if it is already there (in case we'll just move it)
int alreadyExistsIndex = children.indexOf(child);
children.add(index, (IterationStrategyNode) child);
if (alreadyExistsIndex > -1) {
// Remove it from the old position
if (index < alreadyExistsIndex
&& alreadyExistsIndex + 1 < children.size()) {
alreadyExistsIndex++;
}
children.remove(alreadyExistsIndex);
}
if (child.getParent() != this) {
child.setParent(this);
}
}
/**
* Implement TreeNode
*/
public boolean isLeaf() {
return children.isEmpty();
}
public void remove(int index) {
if (!getAllowsChildren()) {
throw new IllegalStateException("Node does not allow children");
}
children.remove(index);
}
public synchronized void remove(MutableTreeNode node) {
if (!getAllowsChildren()) {
throw new IllegalStateException("Node does not allow children");
}
children.remove(node);
if (node.getParent() == this) {
node.setParent(null);
}
}
public void removeFromParent() {
if (parent != null) {
IterationStrategyNode oldParent = parent;
parent = null;
oldParent.remove(this);
}
}
/**
* Implements IterationStrategyNode
*/
public final synchronized void setParent(MutableTreeNode newParent) {
if (newParent != null && !(newParent instanceof IterationStrategyNode)) {
throw new IllegalArgumentException(
"Parent not a IterationStrategyNode instance: " + newParent);
}
if (newParent != null && !newParent.getAllowsChildren()) {
throw new IllegalStateException(
"New parent does not allow children");
}
if (newParent == this) {
throw new IllegalArgumentException("Can't be it's own parent");
}
removeFromParent();
parent = (IterationStrategyNode) newParent;
if (parent != null) {
if (!parent.getChildren().contains(this)) {
parent.insert(this);
}
}
}
public void setUserObject(Object object) {
throw new UnsupportedOperationException("Can't set user object");
}
/**
* Push the specified completion event to the parent node
*/
protected final void pushCompletion(Completion completion) {
if (parent != null) {
parent.receiveCompletion(parent.getIndex(this), completion);
}
}
/**
* Push the specified job up to the parent node in the iteration strategy.
*/
protected final void pushJob(Job job) {
if (parent != null) {
int index = parent.getIndex(this);
if (index < 0) {
throw new WorkflowStructureException(
"Parent doesn't have this node in its child list!");
}
parent.receiveJob(parent.getIndex(this), job);
}
}
}