/* * Copyright 2004 - 2009 University of Cardiff. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.trianacode.taskgraph; import org.apache.commons.logging.Log; import org.trianacode.enactment.logging.Loggers; import org.trianacode.taskgraph.clipin.ClipInStore; import org.trianacode.taskgraph.service.ControlInterface; import org.trianacode.taskgraph.service.RunnableInterface; import org.trianacode.taskgraph.tool.Tool; import org.trianacode.taskgraph.tool.ToolTable; import java.util.HashMap; import java.util.Map; /** * Class Description Here... * * @author Andrew Harrison * @version $Revision:$ */ public abstract class Unit { static Log log = Loggers.PROCESS_LOGGER; /** * Parameter types */ // Internal parameter not exposed to user public static final String INTERNAL = Tool.INTERNAL; // Internal parameter not exposed to user or serialized in tool XML public static final String TRANSIENT = Tool.TRANSIENT; // Internal parameter only initialized on first getParameter call public static final String LATE_INITIALIZE = Tool.LATE_INITIALIZE; // User accessible parameter public static final String USER_ACCESSIBLE = Tool.USER_ACCESSIBLE; // User accessible parameter not serialized in tool XML public static final String TRANSIENT_ACCESSIBLE = Tool.TRANSIENT_ACCESSIBLE; /** * Parameter update polices */ public static final String IMMEDIATE_UPDATE = Tool.IMMEDIATE_UPDATE; public static final String PROCESS_UPDATE = Tool.PROCESS_UPDATE; public static final String NO_UPDATE = Tool.NO_UPDATE; /** * Parameter panel instatiation options */ public static final String ON_USER_ACCESS = Tool.ON_USER_ACCESS; public static final String ON_TASK_INSTANTATION = Tool.ON_TASK_INSTANTIATION; /** * Output polices */ public static final String COPY_OUTPUT = Tool.COPY_OUTPUT; public static final String CLONE_MULTIPLE_OUTPUT = Tool.CLONE_MULTIPLE_OUTPUT; public static final String CLONE_ALL_OUTPUT = Tool.CLONE_ALL_OUTPUT; /** * Node requirements */ public static final String ESSENTIAL = Task.ESSENTIAL; public static final String ESSENTIAL_IF_CONNECTED = Task.ESSENTIAL_IF_CONNECTED; public static final String OPTIONAL = Task.OPTIONAL; /** * Use to access functions within RunnableTask */ private RunnableInterface runnableTask; /** * used to send display/hide messages to the unit's parameter panel */ private int displayCounter; private String toolName = "unknown"; private String toolPackage = "unknown"; private String displayName = "unknown"; private String displayPackage = "unknown"; private Map<String, Object[]> definedParams = new HashMap<String, Object[]>(); public Unit() { setToolName(getClass().getSimpleName()); setToolPackage(getPackageName(getClass().getName())); setDisplayName(getToolName()); setDisplayPackage(getToolPackage()); } public Unit(String name, String pkge) { setToolName(getClass().getSimpleName()); setToolPackage(getPackageName(getClass().getName())); setDisplayName(name); setDisplayPackage(pkge); } protected String getPackageName(String fullname) { if (fullname.endsWith(".class")) { fullname = fullname.substring(0, fullname.length() - 6); } int index = fullname.indexOf("."); if (index > 0) { return fullname.substring(0, fullname.lastIndexOf(".")); } return fullname; } /** * Set the access to a RunnableTask */ public void setRunnableInterface(RunnableInterface runnableTask) { this.runnableTask = runnableTask; } /** * Use to access functions within RunnableTask */ protected RunnableInterface getRunnableInterface() { return runnableTask; } /** * Use to access functions within the Task Interface */ public Task getTask() { return runnableTask.getTask(); } /** * Use to access functions within the Control Interface. */ public ControlInterface getControlInterface() { return runnableTask.getControlInterface(); } /** * @return the name of this tool. */ public String getToolName() { return toolName; } public String getToolPackage() { return toolPackage; } public void setToolPackage(String toolPackage) { this.toolPackage = toolPackage; } public void setToolName(String toolName) { this.toolName = toolName; } public String getDisplayName() { return displayName; } public void setDisplayName(String displayName) { this.displayName = displayName; } public String getDisplayPackage() { return displayPackage; } public void setDisplayPackage(String displayPackage) { this.displayPackage = displayPackage.replace("/", "."); } /** * This method should return an array of the data types accepted by specific nodes, with the node index providing * the index for the array. For nodes not covered by the array, the types specified by getInputTypes() are assumed. * * @return an array of the input types for this unit */ public String[][] getNodeInputTypes() { return new String[0][0]; } /** * This method should return an array of the data types accepted by nodes not specified in getNodeInputTypes (e.g. * triana.types.VectorType). If no package is specified then triana.types is assumed. * * @return an array of the input types for this unit */ public abstract String[] getInputTypes(); /** * This method should return an array of the data types output by specific nodes, with the node index providing the * index for the array. For nodes not covered by the array, the types specified by getOutputTypes() are assumed. * * @return an array of the input types for this unit */ public String[][] getNodeOutputTypes() { return new String[0][0]; } /** * This method should return an array of the data types output by nodes not specified in getNodeOutputTypes() (e.g. * triana.types.VectorType). If no package is specified then triana.types is assumed. * * @return an array of the output types for this unit */ public abstract String[] getOutputTypes(); /** * This function is called when the unit is first created. It should be over-ridden to initialise the tool * properties (e.g. default number of nodes) and tool parameters. */ public void init() { } /** * This function is called when the reset is pressed on the gui. It restore the unit to its pre-start state. */ public void reset() { } /** * This function is called when the unit is deleted. It should be over-ridden to clean up the unit (e.g. close open * files). */ public void dispose() { } public void parameterUpdate(String paramname, Object value) { } public final void parameterUpdated(String paramname, Object value) { Object[] existing = definedParams.get(paramname); debug("param:" + paramname + "" + "new value:" + value + "" + "existing type for param: " + getTask().getParameterType(paramname)); if (existing != null && existing.length == 2 && existing[0] != null && !existing[0].equals(value)) { debug("setting new type for param " + paramname + " : " + (String) existing[1]); getTask().setParameterType(paramname, (String) existing[1]); } parameterUpdate(paramname, value); } /** * The main unit algorithm. This method should be implemented with the appropriate algorihtm for the unit (if no * algorithm is implemented deadlock occurs). */ public abstract void process() throws Exception; /** * This is called when the network is forcably stopped by the user. This should be over-ridden with the desired * tasks. */ public void stopping() { } /** * Stops the network running */ public final void notifyError(String message, Throwable throwable) { getRunnableInterface().notifyError(message); } public final void notifyError(String message) { notifyError(message, null); } /** * @return the value of a task parameter. (null if not set) */ public Object getParameter(String paramname) { return getTask().getParameter(paramname); } /** * @return the type of a task parameter */ public Object getParameterType(String paramname) { return getTask().getParameterType(paramname); } /** * Defines the initial value and type of a parameter. If the parameter is already defined, such as when the unit is * recreated from a serialized version, then nothing happens. This method should generally only be used in the init * method. Note that a parameterUpdate call is not generated. * <p/> * The type of the parameter can either be: * <p/> * USER_ACCESSIBLE - The user is allowed to dynamically update the value INTERNAL - The parameter is hidden from the * user TRANSIENT - The parameter is hidden from the user and does not get saved when the taskgraph is serialized * * @param paramname the name of the parameter * @param initvalue the value of the parameter (null if not defined) * @param type see above */ public void defineParameter(String paramname, Object initvalue, String type) { Task task = getTask(); if (!task.isParameterName(paramname)) { if (initvalue != null) { String reset = addDefinedParam(paramname, initvalue, type); getTask().setParameter(paramname, initvalue); getTask().setParameterType(paramname, reset); } } } private String addDefinedParam(String name, Object value, String type) { String reset = type; if (type.equals(INTERNAL)) { reset = TRANSIENT; } /*if (type.equals(USER_ACCESSIBLE)) { reset = TRANSIENT_ACCESSIBLE; }*/ definedParams.put(name, new Object[]{value, type}); return reset; } /** * @return true if a parameter with the specified name is set */ public boolean isParameter(String paramname) { return getTask().isParameterName(paramname); } /** * Sets the value of a task parameter */ public void setParameter(String paramname, Object value) { getTask().setParameter(paramname, value); } /** * Removes a task parameter */ public void removeParameter(String paramname) { getTask().removeParameter(paramname); } /** * @return the number of data input nodes. */ public int getInputNodeCount() { return getTask().getDataInputNodeCount(); } /** * @return the number of data output nodes. */ public int getOutputNodeCount() { return getTask().getDataOutputNodeCount(); } /** * @return true if there is data waiting on the specified node */ public boolean isInputAtNode(int nodeNumber) { return getRunnableInterface().isInput(nodeNumber); } /** * Returns the data at input node <i>nodeNumber</i>. If data is not ready, NOT_READY triana type is returned. If * there is no cable connected to the input node the NOT_CONNECTED triana type is returned. * * @param nodeNumber the particular node you want to get the data from. */ public Object getInputAtNode(int nodeNumber) { return getRunnableInterface().getInput(nodeNumber); } /** * Outputs the data across all nodes. This passses the given data set to the first output node and then makes copies * for any other output nodes. This method blocks until the data is successfully sent. * * @param data the data to be sent */ public void output(Object data) { getRunnableInterface().output(data); } /** * Outputs the data to the given node <i>outputNode</i>.. This method is used to set the data at each particular * output node if this is necessary, otherwise use output to copy the data across all nodes. This method blocks * until the data is successfully sent. * * @param outputNode the output node you wish to set * @param data the data to be sent */ public void outputAtNode(int outputNode, Object data) { getRunnableInterface().output(outputNode, data, true); } /** * Outputs the data to the given node <i>outputNode</i>. If specified this method blocks until the data is * successfully sent (usual behaviour), otherwise, if non-blocking, isOutputSent() can be used to poll whether the * data has been successfully sent. * * @param outputNode the output node you wish to set * @param data the data to be sent * @param blocking true if this method should block until the data is sent */ public void outputAtNode(int outputNode, Object data, boolean blocking) { getRunnableInterface().output(outputNode, data, blocking); } /** * @return true if the data sent with an output call has reached its destination * @see public void outputAtNode(int outputNode, Object data, boolean blocking) */ public boolean isOutputSent(int outputNode) { return getRunnableInterface().isOutputSent(outputNode); } /** * @return the clip-in with the specified name that came attached to the the specified data item (null if not * present). Only clip-ins for data that has been input in the current process can be retrieved. */ public Object getClipIn(Object data, String name) { return getRunnableInterface().getClipIn(data, name); } /** * @return the clip-in attached to this task with the specified name (null if not present) */ public Object getClipIn(String name) { return getRunnableInterface().getClipIn(name); } /** * Put the specified clip-in into this task's clip-in bucket */ public void putClipIn(String name, Object clipin) { getRunnableInterface().putClipIn(name, clipin); } /** * Remove the clip-in with the specified name from this task's clip-in bucket. * * @return the removed clip-in (or null if unknown) */ public Object removeClipIn(String name) { return getRunnableInterface().removeClipIn(name); } /** * @return true if a clip-in with the specified name exists in this task's clip-in bucket */ public boolean isClipInName(String name) { return getRunnableInterface().isClipInName(name); } /** * @return a store of the state of the current clip-in bucket */ public ClipInStore extractClipInState() { return getRunnableInterface().extractClipInState(); } /** * Restores a previously stored clip-in bucket state */ public void restoreClipInState(ClipInStore store) { getRunnableInterface().restoreClipInState(store); } /** * @return the tool table */ public ToolTable getToolTable() { return getRunnableInterface().getToolTable(); } /** * Convienience method for retrieving maximum number of input nodes for this unit. */ public int getMaximumInputNodes() { return getTask().getMaxDataInputNodes(); } /** * Convienience method for setting the maximum number of input nodes for this unit. This method should only be * called from within the init() method. */ public void setMaximumInputNodes(int inodes) { defineParameter(Tool.MAX_INPUT_NODES, String.valueOf(inodes), Tool.INTERNAL); } /** * Convienience method for retrieving minimum number of input nodes for this unit. */ public int getMinimumInputNodes() { return getTask().getMinDataInputNodes(); } /** * Convienience method for setting the minimum number of input nodes for this unit. This method should only be * called from within the init() method. */ public void setMinimumInputNodes(int inodes) { defineParameter(Tool.MIN_INPUT_NODES, String.valueOf(inodes), Tool.INTERNAL); } /** * Convienience method for retrieving default number of output nodes for this unit. */ public int getDefaultInputNodes() { return getTask().getDefaultDataInputNodes(); } /** * Convienience method for setting the default number of input nodes for this unit. This method should only be * called from within the init() method. */ public void setDefaultInputNodes(int inodes) { defineParameter(Tool.DEFAULT_INPUT_NODES, String.valueOf(inodes), Tool.INTERNAL); } /** * Convienience method for retrieving maximum number of output nodes for this unit. */ public int getMaximumOutputNodes() { return getTask().getMaxDataOutputNodes(); } /** * Convienience method for setting the maximum number of output nodes for this unit. This method should only be * called from within the init() method. */ public void setMaximumOutputNodes(int onodes) { defineParameter(Tool.MAX_OUTPUT_NODES, String.valueOf(onodes), Tool.INTERNAL); } /** * Convienience method for retrieving minimum number of output nodes for this unit. */ public int getMinimumOutputNodes() { return getTask().getMinDataOutputNodes(); } /** * Convienience method for setting the minimum number of output nodes for this unit. This method should only be * called from within the init() method. */ public void setMinimumOutputNodes(int onodes) { defineParameter(Tool.MIN_OUTPUT_NODES, String.valueOf(onodes), Tool.INTERNAL); } /** * Convienience method for retrieving default number of output nodes for this unit. */ public int getDefaultOutputNodes() { return getTask().getDefaultDataOutputNodes(); } /** * Convienience method for setting the default number of output nodes for this unit. This method should only be * called from within the init() method. */ public void setDefaultOutputNodes(int onodes) { defineParameter(Tool.DEFAULT_OUTPUT_NODES, String.valueOf(onodes), Tool.INTERNAL); } /** * Convienience method for retrieving the default pop-up description for this unit. */ public String getPopUpDescription() { return getTask().getPopUpDescription(); } /** * Stops the network running */ // public void stop() { // getRunnableInterface().notifyError(null); // } /** * Convienience method for setting the default pop-up description. */ public void setPopUpDescription(String location) { getTask().removeParameter(Task.POP_UP_DESCRIPTION); defineParameter(Task.POP_UP_DESCRIPTION, location, Tool.INTERNAL); } /** * Convienience method for retrieving default help file location for this unit. */ public String getHelpFileLocation() { return getTask().getHelpFile(); } /** * Convienience method for setting the default help file location. If only a filename is specified then the toolbox * location + /help is assumed. All tools should have help files, which should be written in HTML. */ public void setHelpFileLocation(String location) { defineParameter(Task.HELP_FILE_PARAM, location, Tool.INTERNAL); } /** * Covienience method that returns the parameter update policy for this unit. */ public String getParameterUpdatePolicy() { return (String) getTask().getParameter(Tool.PARAM_UPDATE_POLICY); } /** * Convienience method that sets the parameter update policy for this unit. This method should only be called from * within the init() method. */ public void setParameterUpdatePolicy(String policy) { defineParameter(Tool.PARAM_UPDATE_POLICY, policy, Tool.INTERNAL); } /** * Covienience method that returns the output policy for this unit. */ public String getOutputPolicy() { return (String) getTask().getParameter(Tool.OUTPUT_POLICY); } /** * Convienience method that sets the output policy for this unit. This method should only be called from within the * init() method. */ public void setOutputPolicy(String policy) { defineParameter(Tool.OUTPUT_POLICY, policy, Tool.INTERNAL); } /** * Convienience method that sets the information used to create a GUI with GUI Builder V2. This method should only * be called from within the init() method. */ public void setGUIBuilderV2Info(String info) { getTask().removeParameter(Tool.OLD_GUI_BUILDER); defineParameter(Tool.GUI_BUILDER, info, Tool.INTERNAL); getTask().removeParameter(Tool.PARAM_PANEL_CLASS); } /** * Convienience method that returns the information used to create a GUI with GUI Builder V2 */ public String getGUIBuilderV2Info() { return (String) getTask().getParameter(Tool.GUI_BUILDER); } /** * Convienience method that sets the custom parameter panel used. This method should only be called from within the * init() method. */ public void setParameterPanelClass(String classname) { defineParameter(Tool.PARAM_PANEL_CLASS, classname, Tool.INTERNAL); getTask().removeParameter(Tool.GUI_BUILDER); getTask().removeParameter(Tool.OLD_GUI_BUILDER); } /** * Covienience method that returns the custom parameter panel class used */ public String getParameterPanelClass() { return (String) getTask().getParameter(Tool.PARAM_PANEL_CLASS); } /** * Convienience method that sets the when the parameter panel is instantiated, either ON_USER_ACCESS or * ON_TASK_INSTANTIATION. This method should only be called from within the init() method. */ public void setParameterPanelInstantiate(String policy) { defineParameter(Tool.PARAM_PANEL_INSTANTIATE, policy, Tool.INTERNAL); } /** * Covienience method that returns the custom parameter panel class used */ public String getParameterPanelInstantiate() { return (String) getTask().getParameter(Tool.PARAM_PANEL_INSTANTIATE); } /** * Sets the default node requirements for this unit (ESSENTIAL, ESSENTIAL_IF_CONNECTED or OPTIONAL) */ public void setDefaultNodeRequirement(String requirement) { getTask().setDefaultNodeRequirement(requirement); } /** * @return the default node requirements for this unit (ESSENTIAL, ESSENTIAL_IF_CONNECTED or OPTIONAL) */ public String getDefaultNodeRequirement() { return getTask().getDefaultNodeRequirement(); } /** * Display the parameter panel for this unit. Equivalent to the user double clicking. */ public void showParameterPanel() { String value = String.valueOf(++displayCounter); if (!isParameter(Tool.PARAM_PANEL_SHOW)) { defineParameter(Tool.PARAM_PANEL_SHOW, value, Tool.GUI); } else { getTask().setParameter(Tool.PARAM_PANEL_SHOW, value); } } public void hideParameterPanel() { String value = String.valueOf(++displayCounter); if (!isParameter(Tool.PARAM_PANEL_HIDE)) { defineParameter(Tool.PARAM_PANEL_HIDE, value, Tool.GUI); } else { getTask().setParameter(Tool.PARAM_PANEL_HIDE, value); } } public TaskGraphContext getTaskGraphContext() { return getTask().getContext(); } public void setVersion(String version) { getTask().setVersion(version); } public String getVersion() { return getTask().getVersion(); } public void log(String msg) { log.info(msg); } public void debug(String msg) { log.debug(msg); } public void log(String msg, Throwable t) { log.info(msg, t); } public void debug(String msg, Throwable t) { log.debug(msg, t); } }