blob: 1f933c1fa87a8886f5d5b9ffa9d2de895b3a18f1 [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.workbench.views.results.workflow;
import static javax.swing.SwingUtilities.invokeLater;
import static net.sf.taverna.t2.workbench.views.results.workflow.WorkflowResultTreeNode.ResultTreeNodeState.RESULT_LIST;
import static net.sf.taverna.t2.workbench.views.results.workflow.WorkflowResultTreeNode.ResultTreeNodeState.RESULT_REFERENCE;
import static net.sf.taverna.t2.workbench.views.results.workflow.WorkflowResultTreeNode.ResultTreeNodeState.RESULT_WAITING;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import javax.swing.tree.DefaultTreeModel;
import net.sf.taverna.t2.workbench.views.results.workflow.WorkflowResultTreeNode.ResultTreeNodeState;
import org.apache.log4j.Logger;
import uk.org.taverna.databundle.DataBundles;
import uk.org.taverna.platform.report.ReportListener;
import uk.org.taverna.platform.report.State;
public class WorkflowResultTreeModel extends DefaultTreeModel implements ReportListener {
private static final long serialVersionUID = 7154527821423588046L;
private static final Logger logger = Logger.getLogger(WorkflowResultTreeModel.class);
/** Name of the output port this class models results for */
private String portName;
int depthSeen = -1;
public WorkflowResultTreeModel(String portName) {
super(new WorkflowResultTreeNode(ResultTreeNodeState.RESULT_TOP));
this.portName = portName;
}
@Override
public void outputAdded(final Path path, final String portName, final int[] index) {
// Don't slow down workflow execution, do it in GUI thread
invokeLater(new Runnable() {
@Override
public void run() {
resultTokenProducedGui(path, portName, index);
}
});
}
@Override
public void stateChanged(State oldState, State newState) {
// TODO Auto-generated method stub
}
public void resultTokenProducedGui(Path path, String portName, int[] index) {
if (!this.portName.equals(portName))
return;
if (depthSeen == -1)
depthSeen = index.length;
else if (index.length < depthSeen)
return;
Path reference = path;
if (!DataBundles.isList(reference)) {
insertNewDataTokenNode(reference, index);
return;
}
try {
WorkflowResultTreeNode parent = (WorkflowResultTreeNode) getRoot();
parent = getChildAt(parent,0);
changeState(parent, RESULT_LIST);
for (int i = 0; i < index.length; i++) {
parent = getChildAt(parent, index[i]);
changeState(parent, RESULT_LIST);
}
List<Path> list = DataBundles.getList(reference);
int[] elementIndex = new int[index.length + 1];
for (int indexElement = 0; indexElement < index.length; indexElement++)
elementIndex[indexElement] = index[indexElement];
int c = 0;
for (Path id : list) {
elementIndex[index.length] = c;
resultTokenProducedGui(id, portName, elementIndex);
c++;
}
//if (c == 0) {
// parent.setUserObject("Empty list (depth=" + reference.getDepth() + ")" + reference.getLocalPart());
// nodeChanged(parent);
//}
} catch (NullPointerException | IOException e) {
logger.error("Error resolving data entity list " + reference, e);
}
}
public void insertNewDataTokenNode(Path reference, int[] index) {
WorkflowResultTreeNode parent = (WorkflowResultTreeNode) getRoot();
if (DataBundles.isError(reference)) {
parent = getChildAt(parent, 0);
for (int i = 0; i < index.length - 1; i++) {
parent = getChildAt(parent, index[i]);
parent = getChildAt(parent, 0);
changeState(parent, RESULT_LIST);
}
if (index.length > 0) {
WorkflowResultTreeNode child = getChildAt(parent,
index[index.length - 1]);
updateNodeWithData(child, reference);
} else
updateNodeWithData(parent, reference);
} else {
int depth = index.length;
if (depth == 0) {
WorkflowResultTreeNode child = getChildAt(parent, 0);
updateNodeWithData(child, reference);
} else {
parent = getChildAt(parent, 0);
changeState(parent, RESULT_LIST);
for (int indexElement = 0; indexElement < depth; indexElement++) {
WorkflowResultTreeNode child = getChildAt(parent,
index[indexElement]);
if (indexElement == depth - 1) // leaf
updateNodeWithData(child, reference);
else { // list
child.setState(RESULT_LIST);
nodeChanged(child);
}
parent = child;
}
}
}
}
private void updateNodeWithData(WorkflowResultTreeNode node, Path reference) {
node.setState(RESULT_REFERENCE);
node.setReference(reference);
nodeChanged(node);
}
private WorkflowResultTreeNode getChildAt(WorkflowResultTreeNode parent,
int i) {
int childCount = getChildCount(parent);
if (childCount <= i)
for (int x = childCount; x <= i; x++)
insertNodeInto(new WorkflowResultTreeNode(RESULT_WAITING),
parent, x);
return (WorkflowResultTreeNode) parent.getChildAt(i);
}
private void changeState(WorkflowResultTreeNode node, ResultTreeNodeState state) {
if (!node.isState(state)) {
node.setState(state);
nodeChanged(node);
}
}
// Normally used for past workflow runs where data is obtained from provenance
public void createTree(Path path, WorkflowResultTreeNode parentNode){
// If reference contains a list of data references
if (DataBundles.isList(path))
// insert list node
try {
List<Path> list = DataBundles.getList(path);
WorkflowResultTreeNode listNode = new WorkflowResultTreeNode(
path, RESULT_LIST);
insertNodeInto(listNode, parentNode, parentNode.getChildCount());
for (Path ref : list)
createTree(ref, listNode);
} catch (IOException e) {
logger.error("Error resolving data entity list " + path, e);
}
else { // reference to single data or an error
// insert data node
WorkflowResultTreeNode dataNode = new WorkflowResultTreeNode(path,
RESULT_REFERENCE);
insertNodeInto(dataNode, parentNode, parentNode.getChildCount());
}
}
}