/*
* The University of Wales, Cardiff Triana Project Software License (Based
* on the Apache Software License Version 1.1)
*
* Copyright (c) 2007 University of Wales, Cardiff. All rights reserved.
*
* Redistribution and use of the software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any,
* must include the following acknowledgment: "This product includes
* software developed by the University of Wales, Cardiff for the Triana
* Project (http://www.trianacode.org)." Alternately, this
* acknowledgment may appear in the software itself, if and wherever
* such third-party acknowledgments normally appear.
*
* 4. The names "Triana" and "University of Wales, Cardiff" must not be
* used to endorse or promote products derived from this software
* without prior written permission. For written permission, please
* contact triana@trianacode.org.
*
* 5. Products derived from this software may not be called "Triana," nor
* may Triana appear in their name, without prior written permission of
* the University of Wales, Cardiff.
*
* 6. This software may not be sold, used or incorporated into any product
* for sale to third parties.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL UNIVERSITY OF WALES, CARDIFF OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* ------------------------------------------------------------------------
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Triana Project. For more information on the
* Triana Project, please see. http://www.trianacode.org.
*
* This license is based on the BSD license as adopted by the Apache
* Foundation and is governed by the laws of England and Wales.
*
*/
package org.trianacode.taskgraph;
import org.trianacode.taskgraph.imp.TaskFactoryImp;
import org.trianacode.taskgraph.imp.TaskGraphImp;
import org.trianacode.taskgraph.imp.TaskImp;
import org.trianacode.taskgraph.imp.ToolImp;
import org.trianacode.taskgraph.proxy.ProxyFactory;
import org.trianacode.taskgraph.proxy.ProxyInstantiationException;
import org.trianacode.taskgraph.tool.Tool;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Vector;
/**
* Utility functions useful in handling task graphs
*
* @author Ian Wang
* @version $Revision: 4048 $
*/
public class TaskGraphUtils {
/**
* @return true if the specified task is a control task
*/
public static boolean isControlTask(Task task) {
if (task.getParent() == null) {
return false;
} else {
return (task.getParent().getControlTask() == task);
}
}
/**
* Creates a non-runnable clone of the specfied tool.
*/
public static Tool cloneTool(Tool tool) throws TaskException {
if (tool instanceof TaskGraph) {
try {
return cloneTaskGraph((TaskGraph) tool, TaskGraphManager.NON_RUNNABLE_FACTORY_TYPE, false, false, true);
} catch (TaskGraphException except) {
throw (new TaskException(except));
}
} else {
return toolClone(tool);
}
}
/**
* Creates a non-runnable clone of the specfied task, optionally preserving the instance id.
*/
public static Task cloneTask(Task task, boolean preserveinst) throws TaskException {
if (task instanceof TaskGraph) {
try {
return (Task) cloneTaskGraph((TaskGraph) task, TaskGraphManager.NON_RUNNABLE_FACTORY_TYPE, preserveinst,
false, true);
} catch (TaskGraphException except) {
throw (new TaskException(except));
}
} else {
return taskClone(task, preserveinst);
}
}
/**
* Creates a clone of the tool. If the tool is a taskgraph then a dummy single tool is returned
*/
public static Tool dummyCloneTool(Tool tool) throws TaskException {
return toolClone(tool);
}
/**
* Creates a clone of the task. If the task is a taskgraph then a dummy single task is returned
*/
public static Task dummyCloneTask(Task task, boolean preserveinst) throws TaskException {
return taskClone(task, preserveinst);
}
/**
* Creates a place holder tool, which is a copy of only the nodes and tool classes of the specified tool.
*/
public static Tool createPlaceHolderTool(Tool tool) throws TaskException {
try {
ToolImp placeholder = new ToolImp(tool.getProperties());
placeholder.setToolName(tool.getToolName());
placeholder.setDataInputNodeCount(tool.getDataInputNodeCount());
placeholder.setDataOutputNodeCount(tool.getDataOutputNodeCount());
placeholder.setProxy(ProxyFactory.cloneProxy(tool.getProxy()));
placeholder.setProperties(tool.getProperties());
RenderingHint[] hints = tool.getRenderingHints();
for (int count = 0; count < hints.length; count++) {
placeholder.addRenderingHint(hints[count]);
}
String[] names = tool.getExtensionNames();
for (int count = 0; count < names.length; count++) {
placeholder.addExtension(names[count], tool.getExtension(names[count]));
}
int paramin = tool.getParameterInputNodeCount();
String[] paramnames = new String[paramin];
boolean[] trigger = new boolean[paramin];
for (int count = 0; count < paramin; count++) {
paramnames[count] = tool.getParameterInputName(count);
trigger[count] = tool.isParameterTriggerNode(count);
}
placeholder.setParameterInputs(paramnames, trigger);
int paramout = tool.getParameterOutputNodeCount();
paramnames = new String[paramout];
for (int count = 0; count < paramout; count++) {
paramnames[count] = tool.getParameterOutputName(count);
}
placeholder.setParameterOutputs(paramnames);
if (tool instanceof TaskGraph) {
return new TaskGraphImp(placeholder, new TaskFactoryImp(), false);
} else {
return placeholder;
}
} catch (NodeException except) {
throw (new TaskException(except));
} catch (ProxyInstantiationException except) {
throw (new TaskException(except));
}
}
/**
* Creates a clone of the specified taskgraph within the parent, optionally preserving the instance ids of the
* cloned task.
*/
public static TaskGraph cloneTaskGraph(TaskGraph taskgraph, TaskGraph parent, boolean preserveinst)
throws TaskGraphException {
TaskGraph clone;
String factorytype;
if (parent != null) {
factorytype = TaskGraphManager.getTaskGraphFactoryType(parent);
} else {
throw (new TaskException("Parent taskgraphs must be created using TaskGraphManager"));
}
if (preserveinst) {
clone = TaskGraphUtils.cloneTaskGraph(taskgraph, factorytype);
} else {
clone = TaskGraphUtils.copyTaskGraph(taskgraph, factorytype);
}
((Task) clone).setParent(parent);
((Task) clone).init();
return clone;
}
/**
* Creates a full clone of the taskgraph, preserving the instances of the clone and all the tasks within the clone.
* Note that setParent() and init() are not called on the clone.
*/
public static TaskGraph cloneTaskGraph(TaskGraph taskgraph, String factorytype) throws TaskGraphException {
return cloneTaskGraph(taskgraph, factorytype, true, true, true);
}
/**
* Creates a semi-clone of the taskgraph, preserving the instances of the tasks within the the clone, but not the
* clone itself (i.e. the clone is a new taskgraph instance with the same contents). Note that the control task is
* not cloned. Also note that setParent() and init() are not called on the clone.
*/
public static TaskGraph semiCloneTaskGraph(TaskGraph taskgraph, String factorytype) throws TaskGraphException {
return cloneTaskGraph(taskgraph, factorytype, false, true, false);
}
/**
* Creates a copy of the taskgraph, not preserving the instance id of the clone or the tasks within the clone. Note
* that setParent() and init() are not called on the clone.
*/
public static TaskGraph copyTaskGraph(TaskGraph taskgraph, String factorytype) throws TaskGraphException {
return cloneTaskGraph(taskgraph, factorytype, false, false, true);
}
/**
* Creates a clone of the specified tool
*/
private static Tool toolClone(Tool tool) throws TaskException {
return new ToolImp(tool);
}
/**
* Creates a clone of the specified tool
*/
private static Task taskClone(Task task, boolean preserveinst) throws TaskException {
return new TaskImp(task, new TaskFactoryImp(), preserveinst);
}
/**
* Creates a clone copy of the specified taskgraph that is created using the specified taskgraph factory, optionally
* preserving the instance id of the original taskgraph in the clone. Note that the control task for the clone is
* attached using the default connection policy.
*
* @param taskgraph the taskgraph being clones
* @param factorytype the taskgraph factory type used to create the clone
* @param presclone a flag indicating whether the instance of the taskgraph is preserved
* @param prestasks a flag indicating whether the instance of tasks within the taskgraph are preserved
* @param clonecontrol a flag indicating whether the control task is cloned
*/
private static TaskGraph cloneTaskGraph(TaskGraph taskgraph, String factorytype, boolean presclone,
boolean prestasks, boolean clonecontrol) throws TaskGraphException {
try {
TaskGraph clone = TaskGraphManager.createTaskGraph(taskgraph, factorytype, presclone);
if (taskgraph.getToolName() != null) {
clone.setToolName(taskgraph.getToolName());
}
Task[] tasks = taskgraph.getTasks(false);
for (int count = 0; count < tasks.length; count++) {
clone.createTask(tasks[count], prestasks);
}
Cable[] cables = TaskGraphUtils.getInternalCables(tasks);
Task task;
Node sendnode;
Node recnode;
try {
for (int count = 0; count < cables.length; count++) {
task = clone.getTask(taskgraph.getTask(cables[count].getSendingNode()).getToolName());
if (cables[count].getSendingNode().isParameterNode()) {
sendnode = task.getParameterOutputNode(cables[count].getSendingNode().getNodeIndex());
} else {
sendnode = task.getDataOutputNode(cables[count].getSendingNode().getNodeIndex());
}
task = clone.getTask(taskgraph.getTask(cables[count].getReceivingNode()).getToolName());
if (cables[count].getReceivingNode().isParameterNode()) {
recnode = task.getParameterInputNode(cables[count].getReceivingNode().getNodeIndex());
} else {
recnode = task.getDataInputNode(cables[count].getReceivingNode().getNodeIndex());
}
clone.connect(sendnode, recnode);
}
} catch (CableException e) {
e.printStackTrace();
}
TaskGraph group = taskgraph;
Node nodes[] = group.getDataInputNodes();
Node node;
Node clonenode;
try {
for (int count = 0; count < nodes.length; count++) {
if (taskgraph.isControlTaskConnected()) {
node = TaskGraphUtils.getControlNode(nodes[count]).getCable().getReceivingNode();
} else {
node = nodes[count].getParentNode();
}
if (node.isParameterNode()) {
clonenode = clone.getTask(taskgraph.getTask(node).getToolName())
.getParameterInputNode(node.getNodeIndex());
} else {
clonenode = clone.getTask(taskgraph.getTask(node).getToolName())
.getDataInputNode(node.getNodeIndex());
}
clone.setGroupNodeParent(clone.getDataInputNode(count), clonenode);
}
} catch (Exception e) {
e.printStackTrace();
}
nodes = group.getDataOutputNodes();
try {
for (int count = 0; count < nodes.length; count++) {
if (taskgraph.isControlTaskConnected()) {
node = TaskGraphUtils.getControlNode(nodes[count]).getCable().getSendingNode();
} else {
node = nodes[count].getParentNode();
}
if (node.isParameterNode()) {
clonenode = clone.getTask(taskgraph.getTask(node).getToolName())
.getParameterOutputNode(node.getNodeIndex());
} else {
clonenode = clone.getTask(taskgraph.getTask(node).getToolName())
.getDataOutputNode(node.getNodeIndex());
}
clone.setGroupNodeParent(clone.getDataOutputNode(count), clonenode);
}
} catch (Exception e) {
e.printStackTrace();
}
if (taskgraph.isControlTask() && clonecontrol) {
clone.createControlTask(taskgraph.getControlTask(), prestasks);
if (taskgraph.isControlTaskConnected()) {
connectControlTask(clone);
}
}
TaskGraphContext context = taskgraph.getContext();
Collection<String> keys = context.getKeys();
for (String key : keys) {
clone.setContextProperty(key, context.getProperty(key));
}
return clone;
} catch (ClassCastException except) {
except.printStackTrace();
throw (new TaskGraphException("cloningError" + ": " + "NodeError", except));
} catch (TaskGraphException except) {
except.printStackTrace();
throw (new TaskGraphException("cloningError" + ": " + except.getMessage(), except));
}
}
/**
* Create new tasks in the specified taskgraph taskgraph, optionally preserving the original instance ids in the new
* tasks. Any connections between the specified tools are also created.
*
* @return the interfaces to the new tasks
*/
public static Task[] createTasks(Tool[] tools, TaskGraph taskgraph, boolean preserveinst)
throws TaskException, CableException {
Task[] taskarray = new Task[tools.length];
Hashtable idmap = new Hashtable();
for (int count = 0; count < tools.length; count++) {
taskarray[count] = taskgraph.createTask(tools[count], preserveinst);
idmap.put(tools[count], taskarray[count]);
}
ArrayList tasklist = new ArrayList();
for (int count = 0; count < tools.length; count++) {
if (tools[count] instanceof Task) {
tasklist.add(tools[count]);
}
}
Task[] tasks = (Task[]) tasklist.toArray(new Task[tasklist.size()]);
Cable[] cables = TaskGraphUtils.getInternalCables(tasks);
Task sendtask;
Task rectask;
Node sendnode;
Node recnode;
for (int count = 0; count < cables.length; count++) {
sendtask = (Task) idmap.get(cables[count].getSendingTask());
rectask = (Task) idmap.get(cables[count].getReceivingTask());
if (cables[count].getSendingNode().isDataNode()) {
sendnode = sendtask.getDataOutputNode(cables[count].getSendingNode().getNodeIndex());
} else {
sendnode = sendtask.getParameterOutputNode(cables[count].getSendingNode().getNodeIndex());
}
if (cables[count].getReceivingNode().isDataNode()) {
recnode = rectask.getDataInputNode(cables[count].getReceivingNode().getNodeIndex());
} else {
recnode = rectask.getParameterInputNode(cables[count].getReceivingNode().getNodeIndex());
}
taskgraph.connect(sendnode, recnode);
}
return taskarray;
}
/**
* Replaces a current task with a new tool (instance id is preserved)
*/
public static Task replaceTask(Task curtask, Tool newtool, boolean rename) throws TaskGraphException {
return replaceTask(curtask, newtool, rename, true);
}
/**
* Replaces a current task with a new tool.
* <p/>
* Note that newtool is a task with no parent it is automatically disposed after the replacement task has been
* created.
*
* @param curtask the task being replaced
* @param newtool the tool used to replace the existing task
* @param rename true if the new task should take the same name as the existing task
* @param preserveinst true if the new task should preseve the instance id of newtool
*/
public static Task replaceTask(Task curtask, Tool newtool, boolean rename, boolean preserveinst)
throws TaskGraphException {
if (curtask.getParent() == null) {
throw (new RuntimeException("Error replacing task: Task being replaced does not have a parent taskgraph"));
}
TaskGraph parent = curtask.getParent();
boolean reconnectcontrol = false;
String taskname = curtask.getToolName();
rename = rename || (newtool.getToolName() == curtask.getToolName());
if (parent != null) {
if (parent.isControlTaskConnected()) {
TaskGraphUtils.disconnectControlTask(parent);
reconnectcontrol = true;
}
Node[] sendnodes = curtask.getInputNodes();
Node[] childinnodes = new Node[sendnodes.length];
for (int count = 0; count < sendnodes.length; count++) {
if (sendnodes[count].getChildNode() != null) {
childinnodes[count] = (Node) sendnodes[count].getChildNode();
((Node) sendnodes[count]).setChildNode(null);
}
if (sendnodes[count].isConnected()) {
sendnodes[count] = sendnodes[count].getCable().getSendingNode();
} else {
sendnodes[count] = null;
}
}
Node[] recnodes = curtask.getOutputNodes();
Node[] childoutnodes = new Node[recnodes.length];
for (int count = 0; count < recnodes.length; count++) {
if (recnodes[count].getChildNode() != null) {
childoutnodes[count] = (Node) recnodes[count].getChildNode();
((Node) recnodes[count]).setChildNode(null);
}
if (recnodes[count].isConnected()) {
recnodes[count] = recnodes[count].getCable().getReceivingNode();
} else {
recnodes[count] = null;
}
}
Task newtask = parent.createTask(newtool, preserveinst);
if (!(newtask instanceof TaskGraph)) {
while (newtask.getDataInputNodeCount() < curtask.getDataInputNodeCount()) {
newtask.addDataInputNode();
}
while (newtask.getDataInputNodeCount() > curtask.getDataInputNodeCount()) {
newtask.removeDataInputNode(newtask.getDataInputNode(newtask.getDataInputNodeCount() - 1));
}
while (newtask.getDataOutputNodeCount() < curtask.getDataOutputNodeCount()) {
newtask.addDataOutputNode();
}
while (newtask.getDataOutputNodeCount() > curtask.getDataOutputNodeCount()) {
newtask.removeDataOutputNode(newtask.getDataOutputNode(newtask.getDataOutputNodeCount() - 1));
}
while (newtask.getParameterInputNodeCount() > 0) {
newtask.removeParameterInputNode(newtask.getParameterInputNode(0));
}
for (int count = 0; count < curtask.getParameterInputNodeCount(); count++) {
newtask.addParameterInputNode(curtask.getParameterInputName(count));
}
while (newtask.getParameterOutputNodeCount() > 0) {
newtask.removeParameterOutputNode(newtask.getParameterOutputNode(0));
}
for (int count = 0; count < curtask.getParameterOutputNodeCount(); count++) {
newtask.addParameterOutputNode(curtask.getParameterOutputName(count));
}
}
Node[] innodes = newtask.getInputNodes();
for (int count = 0; (count < childinnodes.length); count++) {
if (childinnodes[count] != null) {
if (count < innodes.length) {
childinnodes[count].setParentNode((Node) innodes[count]);
((Node) innodes[count]).setChildNode(childinnodes[count]);
} else {
childinnodes[count].setParentNode(null);
}
}
}
Node[] outnodes = newtask.getOutputNodes();
for (int count = 0; (count < childoutnodes.length); count++) {
if (childoutnodes[count] != null) {
if (count < outnodes.length) {
childoutnodes[count].setParentNode((Node) outnodes[count]);
((Node) outnodes[count]).setChildNode(childoutnodes[count]);
} else {
childoutnodes[count].setParentNode(null);
}
}
}
for (int count = 0; (count < innodes.length) && (count < sendnodes.length); count++) {
if (sendnodes[count] != null) {
parent.connect(sendnodes[count], innodes[count].getBottomLevelNode());
}
}
for (int count = 0; (count < outnodes.length) && (count < recnodes.length); count++) {
if (recnodes[count] != null) {
parent.connect(outnodes[count].getBottomLevelNode(), recnodes[count]);
}
}
if (reconnectcontrol) {
TaskGraphUtils.connectControlTask(parent);
}
parent.removeTask(curtask);
if (rename) {
newtask.setToolName(taskname);
}
if ((newtool != curtask) && (newtool instanceof Task) && (((Task) newtool).getParent() == null)) {
TaskGraphUtils.disposeTool(newtool);
}
return newtask;
} else {
throw (new RuntimeException("Cannot recreate top-level parent taskgraph"));
}
}
/**
* Disposes of the specified tool if no longer required
*/
public static void disposeTool(Tool tool) {
if (tool instanceof Task) {
Task disposetask = (Task) tool;
if (disposetask.getParent() != null) {
disposetask.getParent().removeTask(disposetask);
} else {
disposetask.dispose();
}
}
}
/**
* @return an array of the cables connected to the specified task
*/
public static Cable[] getConnectedCables(Task task) {
ArrayList list = new ArrayList(100);
Node[] nodes;
nodes = task.getDataInputNodes();
for (int count = 0; count < nodes.length; count++) {
if ((nodes[count].isConnected()) && (!list.contains(nodes[count].getCable()))) {
list.add(nodes[count].getCable());
}
}
nodes = task.getDataOutputNodes();
for (int count = 0; count < nodes.length; count++) {
if ((nodes[count].isConnected()) && (!list.contains(nodes[count].getCable()))) {
list.add(nodes[count].getCable());
}
}
nodes = task.getParameterInputNodes();
for (int count = 0; count < nodes.length; count++) {
if ((nodes[count].isConnected()) && (!list.contains(nodes[count].getCable()))) {
list.add(nodes[count].getCable());
}
}
nodes = task.getParameterOutputNodes();
for (int count = 0; count < nodes.length; count++) {
if ((nodes[count].isConnected()) && (!list.contains(nodes[count].getCable()))) {
list.add(nodes[count].getCable());
}
}
return getCableArray(list.toArray());
}
/**
* @return an array of the cables connected to the specified tasks (internal and external)
*/
public static Cable[] getConnectedCables(Task[] tasklist) {
ArrayList list = new ArrayList(100);
Cable[] cables;
for (int count1 = 0; count1 < tasklist.length; count1++) {
cables = getConnectedCables(tasklist[count1]);
for (int count2 = 0; count2 < cables.length; count2++) {
if (!list.contains(cables[count2])) {
list.add(cables[count2]);
}
}
}
return getCableArray(list.toArray());
}
/**
* @return true if a given cable is connected to a given task
*/
public static boolean isConnectedCable(Cable cable, Task task) {
Cable[] cables = getConnectedCables(task);
boolean flag = false;
for (int count = 0; (count < cables.length) && (!flag); count++) {
flag = (cables[count] == cable);
}
return true;
}
/**
* Checks if a cable is connected to any task in an array of tasks
*/
public static boolean isConnectedCable(Cable cable, Task[] tasklist) {
Cable[] cables = getConnectedCables(tasklist);
boolean flag = false;
for (int count = 0; (count < cables.length) && (!flag); count++) {
flag = (cables[count] == cable);
}
return true;
}
/**
* @return the set of cables that are internal to a given set of tasks, i.e. only cables that connect two tasks in
* the input set.
*/
public static Cable[] getInternalCables(Task[] tasklist) {
ArrayList list = new ArrayList(10);
Cable[] cables;
for (int count1 = 0; count1 < tasklist.length; count1++) {
cables = getConnectedCables(tasklist[count1]);
for (int count2 = 0; count2 < cables.length; count2++) {
for (int count3 = 0; count3 < tasklist.length; count3++) {
if ((cables[count2].connects(tasklist[count3])) &&
(tasklist[count3] != tasklist[count1]) &&
(!list.contains(cables[count2]))) {
list.add(cables[count2]);
}
}
}
}
return getCableArray(list.toArray());
}
/**
* Checks to see if a given cable is internal to a set of tasks, i.e. it connects two of the given tasks.
*/
public static boolean isInternalCable(Cable cable, Task[] tasklist) {
Cable[] cables = getInternalCables(tasklist);
boolean flag = false;
for (int count = 0; (count < cables.length) && (!flag); count++) {
flag = (cables[count] == cable);
}
return true;
}
/**
* @return the set of cables that are external to a given set of tasks, i.e. only cables that connect a task in the
* input set with one outside.
*/
public static Cable[] getExternalCables(Task[] tasklist) {
ArrayList list = new ArrayList(10);
Cable[] cables;
boolean flag;
for (int count1 = 0; count1 < tasklist.length; count1++) {
cables = getConnectedCables(tasklist[count1]);
for (int count2 = 0; count2 < cables.length; count2++) {
flag = true;
for (int count3 = 0; count3 < tasklist.length; count3++) {
if (cables[count2].connects(tasklist[count3]) && (tasklist[count3] != tasklist[count1])) {
flag = false;
}
}
if ((flag) && (!list.contains(cables[count2]))) {
list.add(cables[count2]);
}
}
}
return getCableArray(list.toArray());
}
/**
* Checks to see if a given cable is external to a set of tasks, i.e. it connects a task in the input set with one
* outside.
*/
public static boolean isExternalCable(Cable cable, Task[] tasklist) {
Cable[] cables = getExternalCables(tasklist);
boolean flag = false;
for (int count = 0; (count < cables.length) && (!flag); count++) {
flag = (cables[count] == cable);
}
return true;
}
private static Cable[] getCableArray(Object[] master) {
Cable[] copy = new Cable[master.length];
for (int count = 0; count < master.length; count++) {
copy[count] = (Cable) master[count];
}
return copy;
}
/**
* @return all the tasks that preceed the specified task
*/
public static Task[] getInputTasks(Task task) {
Node[] nodes = task.getInputNodes();
ArrayList tasks = new ArrayList();
for (int count = 0; count < nodes.length; count++) {
if (nodes[count].getCable() != null) {
tasks.add(nodes[count].getCable().getSendingTask());
}
}
return (Task[]) tasks.toArray(new Task[tasks.size()]);
}
/**
* @return all the tasks that follow the specified task
*/
public static Task[] getOutputTasks(Task task) {
Node[] nodes = task.getOutputNodes();
ArrayList tasks = new ArrayList();
for (int count = 0; count < nodes.length; count++) {
if (nodes[count].getCable() != null) {
tasks.add(nodes[count].getCable().getReceivingTask());
}
}
return (Task[]) tasks.toArray(new Task[tasks.size()]);
}
/**
* @return all the tasks that are connected to the specified task
*/
public static Task[] getConnectedTasks(Task task) {
Node[] nodes = task.getInputNodes();
ArrayList tasks = new ArrayList();
for (int count = 0; count < nodes.length; count++) {
if (nodes[count].getCable() != null) {
tasks.add(nodes[count].getCable().getSendingTask());
}
}
nodes = task.getOutputNodes();
for (int count = 0; count < nodes.length; count++) {
if (nodes[count].getCable() != null) {
tasks.add(nodes[count].getCable().getReceivingTask());
}
}
return (Task[]) tasks.toArray(new Task[tasks.size()]);
}
/**
* @return the remaining workflow that follows the specified task, optionally including the original task at index
* 0.
*/
public static Task[] getRemainingWorkflow(Task task, boolean include) {
ArrayList tasks = new ArrayList();
Task temptask;
Task[] conntasks;
boolean done = false;
int ptr = 0;
if (include) {
tasks.add(task);
ptr++;
}
conntasks = getOutputTasks(task);
for (int count = 0; count < conntasks.length; count++) {
tasks.add(conntasks[count]);
}
while (ptr < tasks.size()) {
temptask = (Task) tasks.get(ptr++);
conntasks = getConnectedTasks(temptask);
for (int count = 0; count < conntasks.length; count++) {
if (!tasks.contains(conntasks[count])) {
tasks.add(conntasks[count]);
}
}
}
return (Task[]) tasks.toArray(new Task[tasks.size()]);
}
/**
* Sets up the connections for the loop task. Input/output from the group now goes via the loop task.
*/
public static void connectControlTask(TaskGraph taskgraph) throws TaskGraphException {
if (taskgraph.getControlTask() == null) {
return;
}
taskgraph.setControlTaskState(TaskGraph.CONTROL_TASK_UNSTABLE);
Task contask = taskgraph.getControlTask();
while (contask.getDataInputNodeCount() > 0) {
contask.removeDataInputNode(contask.getDataInputNode(0));
}
while (contask.getDataOutputNodeCount() > 0) {
contask.removeDataOutputNode(contask.getDataOutputNode(0));
}
TaskGraph grouptask = taskgraph;
Node loopnode;
Node groupnode;
Node[] innodes = grouptask.getDataInputNodes();
Node[] inconnodes = new Node[innodes.length];
for (int nodecount = 0; nodecount < innodes.length; nodecount++) {
inconnodes[nodecount] = innodes[nodecount].getParentNode();
groupnode = (Node) innodes[nodecount];
loopnode = (Node) contask.addDataInputNode();
grouptask.setGroupNodeParent(groupnode, loopnode);
}
Node[] outnodes = grouptask.getDataOutputNodes();
Node[] outconnodes = new Node[outnodes.length];
for (int nodecount = 0; nodecount < outnodes.length; nodecount++) {
outconnodes[nodecount] = outnodes[nodecount].getParentNode();
groupnode = (Node) grouptask.getDataOutputNode(nodecount);
loopnode = (Node) contask.addDataOutputNode();
grouptask.setGroupNodeParent(groupnode, loopnode);
}
for (int nodecount = 0; nodecount < innodes.length; nodecount++) {
taskgraph.connect(contask.addDataOutputNode(), inconnodes[nodecount]);
}
for (int nodecount = 0; nodecount < outnodes.length; nodecount++) {
taskgraph.connect(outconnodes[nodecount], contask.addDataInputNode());
}
taskgraph.setControlTaskState(TaskGraph.CONTROL_TASK_CONNECTED);
}
/**
* Removes the connections for the loop task.
*/
public static void disconnectControlTask(TaskGraph taskgraph) throws TaskGraphException {
if (!taskgraph.isControlTaskConnected()) {
return;
}
taskgraph.setControlTaskState(TaskGraph.CONTROL_TASK_UNSTABLE);
Task contask = taskgraph.getControlTask();
TaskGraph grouptask = taskgraph;
Node[] groupnodes;
Node[] connodes;
Node groupnode;
Node recnode;
Node sendnode;
Cable cable;
groupnodes = grouptask.getDataInputNodes();
connodes = contask.getDataOutputNodes();
int outcount = grouptask.getDataOutputNodeCount();
for (int count = 0; count < groupnodes.length; count++) {
cable = connodes[count + outcount].getCable();
recnode = (Node) cable.getReceivingNode();
groupnode = (Node) grouptask.getDataInputNode(count);
taskgraph.disconnect(cable);
groupnode.setParentNode(recnode);
recnode.setChildNode(groupnode);
((Node) contask.getDataInputNode(count)).setChildNode(null);
}
groupnodes = grouptask.getDataOutputNodes();
connodes = contask.getDataInputNodes();
int incount = grouptask.getDataInputNodeCount();
for (int count = 0; count < groupnodes.length; count++) {
cable = connodes[count + incount].getCable();
sendnode = (Node) cable.getSendingNode();
groupnode = (Node) grouptask.getDataOutputNode(count);
taskgraph.disconnect(cable);
groupnode.setParentNode(sendnode);
sendnode.setChildNode(groupnode);
((Node) contask.getDataOutputNode(count)).setChildNode(null);
}
while (contask.getDataInputNodeCount() > 0) {
contask.removeDataInputNode(contask.getDataInputNode(0));
}
while (contask.getDataOutputNodeCount() > 0) {
contask.removeDataOutputNode(contask.getDataOutputNode(0));
}
taskgraph.setControlTaskState(TaskGraph.CONTROL_TASK_DISCONNECTED);
}
/**
* Given a group input node returns the opposite node on the control task
*/
private static Node getControlNode(Node groupnode) {
Task controltask = groupnode.getTopLevelTask();
if (groupnode.isInputNode()) {
return controltask
.getDataOutputNode(groupnode.getNodeIndex() + groupnode.getTask().getDataOutputNodeCount());
} else {
return controltask.getDataInputNode(groupnode.getNodeIndex() + groupnode.getTask().getDataInputNodeCount());
}
}
/**
* @return the ultimate source node that sends data to/receives data from the given node (ignoring control tasks).
* Null if not connected.
*/
public static Node getSourceNode(Node node) {
Task task;
boolean bottom = false;
while (!bottom) {
node = node.getBottomLevelNode();
if (node.isConnected()) {
if (node.isInputNode()) {
node = node.getCable().getSendingNode();
} else {
node = node.getCable().getReceivingNode();
}
task = node.getTask();
if ((task.getParent() != null) && (task.getParent().getControlTask() == task)) {
if (node.isInputNode()) {
node = task.getDataOutputNode(node.getNodeIndex() - task.getParent().getDataInputNodeCount());
} else {
node = task.getDataInputNode(node.getNodeIndex() - task.getParent().getDataOutputNodeCount());
}
} else {
bottom = true;
}
} else {
return null;
}
}
return NodeUtils.getTopLevelNode(node);
}
/**
* @return a count of all the tasks within a taskgraph and its sub taskgraphs (optionally including control tasks)
*/
public static int getAllTasksCount(TaskGraph taskGraph, boolean includecontrol) {
Task[] tasks = taskGraph.getTasks(includecontrol);
int taskcount = 0;
for (int count = 0; count < tasks.length; count++) {
if (tasks[count] instanceof TaskGraph) {
taskcount += getAllTasksCount((TaskGraph) tasks[count], includecontrol) + 1;
} else {
taskcount++;
}
}
return taskcount;
}
/**
* @return an array of all tasks within a taskgraph and its sub taskgraphs, optionally including control tasks
*/
public static Task[] getAllTasksRecursive(TaskGraph taskGraph, boolean includecontrol) {
Vector copy = new Vector();
getAllTasksRecursive(taskGraph, copy, includecontrol);
return (Task[]) copy.toArray(new Task[copy.size()]);
}
/**
* Recursively copy all the non-group tasks into the vector
*/
public static void getAllTasksRecursive(TaskGraph taskGraph, Vector copy, boolean includecontrol) {
Task[] tasks = taskGraph.getTasks(includecontrol);
for (int i = 0; i < tasks.length; i++) {
if (tasks[i] instanceof TaskGraph) {
getAllTasksRecursive((TaskGraph) tasks[i], copy, includecontrol);
} else {
copy.add(tasks[i]);
}
}
}
/**
* @return all the data types input by the nodes on the specified tool.
*/
public static String[] getAllDataInputTypes(Tool tool) {
ArrayList typelist = new ArrayList();
String[] types = tool.getDataInputTypes(0);
int count = 0;
while (types != null) {
for (int tcount = 0; tcount < types.length; tcount++) {
if (!typelist.contains(types[tcount])) {
typelist.add(types[tcount]);
}
}
types = tool.getDataInputTypes(++count);
}
return (String[]) typelist.toArray(new String[typelist.size()]);
}
/**
* @return all the data types input by the nodes on the specified tool.
*/
public static String[] getAllDataOutputTypes(Tool tool) {
ArrayList typelist = new ArrayList();
String[] types = tool.getDataOutputTypes(0);
int count = 0;
while (types != null) {
for (int tcount = 0; tcount < types.length; tcount++) {
if (!typelist.contains(types[tcount])) {
typelist.add(types[tcount]);
}
}
types = tool.getDataOutputTypes(++count);
}
return (String[]) typelist.toArray(new String[typelist.size()]);
}
public static java.util.List<Task> getSuccessors(Task t) {
java.util.List<Task> ret = new ArrayList<Task>();
int count = t.getOutputNodeCount();
for (int i = 0; i < count; i++) {
Node node = t.getOutputNode(i);
if (node.isConnected()) {
ret.add(node.getCable().getReceivingTask());
}
}
return ret;
}
public static java.util.List<Task> getPredecessors(Task t) {
java.util.List<Task> ret = new ArrayList<Task>();
int count = t.getInputNodeCount();
for (int i = 0; i < count; i++) {
Node node = t.getInputNode(i);
if (node.isConnected()) {
ret.add(node.getCable().getSendingTask());
}
}
return ret;
}
public static java.util.List<Task> getLeafTasks(TaskGraph taskgraph) {
Task[] tasks = taskgraph.getTasks(false);
Node[] outnodes;
ArrayList endtasks = new ArrayList();
boolean endtask;
for (int count = 0; count < tasks.length; count++) {
outnodes = tasks[count].getDataOutputNodes();
endtask = true;
for (int nodecount = 0; (nodecount < outnodes.length) && endtask; nodecount++) {
if (outnodes[nodecount].isConnected()) {
endtask = false;
}
}
if (endtask) {
endtasks.add(tasks[count]);
}
}
return endtasks;
}
public static java.util.List<Task> getRootTasks(TaskGraph taskgraph) {
Task[] tasks = taskgraph.getTasks(false);
Node[] innodes;
ArrayList endtasks = new ArrayList();
boolean starttask;
for (int count = 0; count < tasks.length; count++) {
innodes = tasks[count].getDataInputNodes();
starttask = true;
for (int nodecount = 0; (nodecount < innodes.length) && starttask; nodecount++) {
if (innodes[nodecount].isConnected()) {
starttask = false;
}
}
if (starttask) {
endtasks.add(tasks[count]);
}
}
return endtasks;
}
}