/* * 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.tool.Tool; import java.util.ArrayList; import java.util.Iterator; /** * A set of utils for manipulating the location of tasks (as stored in their GUI_XPOS and DEPRECATED_GUI_YPOS * parameters). Note that the methods here assume that visually all the tasks are zero width and height! The actual * width and heigth of tasks should be factored in by the graphical engine. * * @author Ian Wang * @version $Revision: 4048 $ */ public class TaskLayoutUtils { /** * @return the position of the specfied task in the triana co-ordinate system */ public static TPoint getPosition(Tool task) { if (task.isParameterName(Task.GUI_X) && task.isParameterName(Task.GUI_Y)) { return new TPoint(Double.parseDouble((String) task.getParameter(Task.GUI_X)), Double.parseDouble((String) task.getParameter(Task.GUI_Y))); } else if (task.isParameterName(Task.DEPRECATED_GUI_XPOS) && task.isParameterName(Task.DEPRECATED_GUI_YPOS)) { updateDeprecatedPosition(task); return getPosition(task); } else { return new TPoint(); } } /** * @return the position of the specfied task on the triana workspace using the specified task layout details */ public static TPoint getPosition(Tool task, TaskLayoutDetails layout) { if (task.isParameterName(Task.GUI_X) && task.isParameterName(Task.GUI_Y)) { TPoint pos = getPosition(task); int x = (int) (pos.getX() * layout.getTaskDimensions().getWidth()) + layout.getLeftBorder(); int y = (int) (pos.getY() * layout.getTaskDimensions().getHeight()) + layout.getTopBorder(); return new TPoint(x, y); } else if (task.isParameterName(Task.DEPRECATED_GUI_XPOS) && task.isParameterName(Task.DEPRECATED_GUI_YPOS)) { updateDeprecatedPosition(task); return getPosition(task, layout); } else { return new TPoint(); } } private static void updateDeprecatedPosition(Tool task) { if (task.isParameterName(Task.DEPRECATED_GUI_XPOS) && task.isParameterName(Task.DEPRECATED_GUI_YPOS)) { int xpos = Integer.parseInt((String) task.getParameter(Task.DEPRECATED_GUI_XPOS)); int ypos = Integer.parseInt((String) task.getParameter(Task.DEPRECATED_GUI_YPOS)); setPosition(task, new TPoint((xpos) / 80, (ypos) / 34)); } } /** * Sets the position of the specified task using Triana's co-ordinate system. */ public static void setPosition(Task task, TPoint pos) { task.setParameterType(Task.GUI_X, Tool.GUI); task.setParameterType(Task.GUI_Y, Tool.GUI); task.setParameter(Task.GUI_X, String.valueOf(pos.getX())); task.setParameter(Task.GUI_Y, String.valueOf(pos.getY())); } /** * Sets the position of the specified task on the triana workspace using the specified task layout details. */ public static void setPosition(Task task, TPoint pos, TaskLayoutDetails details) { TPoint point = new TPoint(((pos.getX() - details.getLeftBorder())) / details.getTaskDimensions().getWidth(), ((pos.getY() - details.getTopBorder())) / details.getTaskDimensions().getHeight()); setPosition(task, point); } /** * Sets the position of the specified task using Triana's co-ordinate system. */ public static void setPosition(Tool tool, TPoint pos) { tool.setParameterType(Task.GUI_X, Tool.GUI); tool.setParameterType(Task.GUI_Y, Tool.GUI); tool.setParameter(Task.GUI_X, String.valueOf(pos.getX())); tool.setParameter(Task.GUI_Y, String.valueOf(pos.getY())); } /** * Sets the position of the specified task on the triana workspace using the specified task layout details. */ public static void setPosition(Tool tool, TPoint pos, TaskLayoutDetails details) { TPoint point = new TPoint(((pos.getX() - details.getLeftBorder())) / details.getTaskDimensions().getWidth(), ((pos.getY() - details.getTopBorder())) / details.getTaskDimensions().getHeight()); setPosition(tool, point); } /** * Translates the task by the specified x and y distances */ public static void translate(Task task, double xdist, double ydist) { TPoint point = getPosition(task); setPosition(task, new TPoint(point.getX() + xdist, point.getY() + ydist)); } /** * Translates the specified tasks by the specified x and y distances */ public static void translate(Task[] tasks, double xdist, double ydist) { TPoint point; for (int count = 0; count < tasks.length; count++) { point = getPosition(tasks[count]); setPosition(tasks[count], new TPoint(point.getX() + xdist, point.getY() + ydist)); } } /** * Translates the specified tasks by the specified x and y distances */ public static void translate(Task[] tasks, int xdist, int ydist, TaskLayoutDetails details) { TPoint taskpos; for (int count = 0; count < tasks.length; count++) { taskpos = getPosition(tasks[count], details); taskpos = new TPoint(taskpos.getX() + xdist, taskpos.getY() + ydist); setPosition(tasks[count], taskpos, details); } } /** * Translates the specified tasks so that the top lefthand corner is at the origin (x=0, y=0). */ public static void translateToOrigin(Task[] tasks) { TRectangle grouppos = getBoundingBox(tasks); TPoint taskpos; for (int count = 0; count < tasks.length; count++) { taskpos = getPosition(tasks[count]); setPosition(tasks[count], new TPoint(taskpos.getX() - grouppos.getX(), taskpos.getY() - grouppos.getY())); } } public static void translateToOrigin(Task[] tasks, int border) { TRectangle grouppos = getBoundingBox(tasks); TPoint taskpos; for (int count = 0; count < tasks.length; count++) { taskpos = getPosition(tasks[count]); setPosition(tasks[count], new TPoint((taskpos.getX() - grouppos.getX()) + border, (taskpos.getY() - grouppos.getY()) + border)); } } /** * Translates the specified tasks so that the top lefthand corner is at the specified point */ public static void translateTo(Task[] tasks, TPoint point) { TRectangle grouppos = getBoundingBox(tasks); TPoint taskpos; for (int count = 0; count < tasks.length; count++) { taskpos = getPosition(tasks[count]); setPosition(tasks[count], new TPoint(taskpos.getX() - grouppos.getX() + point.getX(), taskpos.getY() - grouppos.getY() + point.getY())); } } /** * @return the bounding box surrounding the specified tasks */ public static TRectangle getBoundingBox(Task[] tasks) { double minx = Double.POSITIVE_INFINITY; double miny = Double.POSITIVE_INFINITY; double maxx = Double.NEGATIVE_INFINITY; double maxy = Double.NEGATIVE_INFINITY; TPoint pos; for (int count = 0; count < tasks.length; count++) { pos = getPosition(tasks[count]); if (pos.getX() < minx) { minx = pos.getX(); } if (pos.getY() < miny) { miny = pos.getY(); } if (pos.getX() > maxx) { maxx = pos.getX(); } if (pos.getY() > maxy) { maxy = pos.getY(); } } if ((minx != Double.POSITIVE_INFINITY) && (miny != Double.POSITIVE_INFINITY) && (maxx != Double.NEGATIVE_INFINITY) && (maxy != Double.NEGATIVE_INFINITY)) { return new TRectangle(minx, miny, maxx - minx + 1, maxy - miny + 1); } else { return new TRectangle(); } } /** * 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 { Task t = TaskGraphUtils.replaceTask(curtask, newtool, rename, preserveinst); TPoint pos = getPosition(curtask); setPosition(newtool, pos); return t; } /** * Sets unconnected task nodes as group input/output nodes. */ public static void resolveGroupNodes(TaskGraph taskgraph) throws TaskGraphException { if (taskgraph.isControlTaskConnected()) { TaskGraphUtils.disconnectControlTask(taskgraph); resolveGroupNodesNoControlTask(taskgraph); try { TaskGraphUtils.connectControlTask(taskgraph); } catch (TaskGraphException except) { except.printStackTrace(); taskgraph.removeControlTask(); } } else { resolveGroupNodesNoControlTask(taskgraph); } } /** * Sets unconnected task nodes as group input/output nodes when there is no looping task connected */ private static void resolveGroupNodesNoControlTask(TaskGraph taskgraph) throws NodeException { Task[] tasks = taskgraph.getTasks(false); TaskGraph grouptask = taskgraph; Node[] nodes; ArrayList nodelist = new ArrayList(); for (int count = 0; count < tasks.length; count++) { nodes = tasks[count].getInputNodes(); for (int nodecount = 0; nodecount < nodes.length; nodecount++) { if ((!nodes[nodecount].isConnected()) && (nodes[nodecount].getChildNode() == null)) { addToNodeList(nodelist, nodes[nodecount]); } } } for (Iterator iter = nodelist.iterator(); iter.hasNext(); ) { System.out.println("Resolving " + grouptask.addDataInputNode((Node) iter.next())); } nodelist.clear(); for (int count = 0; count < tasks.length; count++) { nodes = tasks[count].getOutputNodes(); for (int nodecount = 0; nodecount < nodes.length; nodecount++) { if ((!nodes[nodecount].isConnected()) && (nodes[nodecount].getChildNode() == null)) { addToNodeList(nodelist, nodes[nodecount]); } } for (Iterator iter = nodelist.iterator(); iter.hasNext(); ) { grouptask.addDataOutputNode((Node) iter.next()); } } } /** * Adds the specified node to the nodelist maintaining the nodelist in ascenting yposition order */ private static void addToNodeList(ArrayList nodelist, Node newnode) { boolean insert = false; Node curnode; TPoint newpoint = getPosition(newnode.getTask()); TPoint curpoint; for (int count = 0; (count < nodelist.size()) && (!insert); count++) { curnode = (Node) nodelist.get(count); curpoint = getPosition(curnode.getTask()); if (newpoint.getY() < curpoint.getY()) { nodelist.add(count, newnode); insert = true; } else if ((newpoint.getY() == curpoint.getY()) && (newnode.getAbsoluteNodeIndex() < curnode .getAbsoluteNodeIndex())) { nodelist.add(count, newnode); insert = true; } } if (!insert) { nodelist.add(newnode); } } }