package org.trianacode.shiwaall.dax; import org.apache.commons.logging.Log; import org.trianacode.config.TrianaProperties; import org.trianacode.enactment.logging.Loggers; import org.trianacode.taskgraph.*; import org.trianacode.taskgraph.imp.ToolImp; import org.trianacode.taskgraph.proxy.Proxy; import org.trianacode.taskgraph.proxy.ProxyFactory; import org.trianacode.taskgraph.proxy.ProxyInstantiationException; import org.trianacode.taskgraph.proxy.java.JavaProxy; import org.trianacode.taskgraph.tool.Tool; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Vector; // TODO: Auto-generated Javadoc /** * Created by IntelliJ IDEA. * User: Ian Harvey * Date: Aug 18, 2010 * Time: 2:07:26 PM * To change this template use File | Settings | File Templates. */ public class DaxReader { /** The file. */ private File file = null; /** The doc. */ private Document doc = null; /** The tool vector. */ private ArrayList<DaxJobHolder> toolVector = new ArrayList<DaxJobHolder>(); /** The files. */ private ArrayList<DaxFileHolder> files = new ArrayList<DaxFileHolder>(); /** The dax package. */ private String daxPackage = "org.trianacode.shiwaall.gui.guiUnits"; /** The dax file unit name. */ private String daxFileUnitName = "DaxFile"; /** The dax job unit name. */ private String daxJobUnitName = "DaxJob"; /** The dev log. */ private static Log devLog = Loggers.DEV_LOGGER; /** The Constant ORIGINAL_DAX_FILE. */ public static final String ORIGINAL_DAX_FILE = "originalDaxFile"; /** * Instantiates a new dax reader. */ public DaxReader() { } /** * The main method. * * @param args the arguments */ public static void main(String[] args) { String filename = ""; if (args.length > 0) { filename = args[0]; new DaxReader(filename); } else { devLog.debug("Set an XML file for input."); } } /** * Instantiates a new dax reader. * * @param filename the filename */ public DaxReader(String filename) { setFile(new File(filename)); getJobInfo(); } /** * Instantiates a new dax reader. * * @param daxPackage the dax package * @param file the file * @param job the job */ public DaxReader(String daxPackage, String file, String job) { this.daxPackage = daxPackage; this.daxFileUnitName = file; this.daxJobUnitName = job; } /** * Reset. */ private void reset() { file = null; doc = null; toolVector = new ArrayList<DaxJobHolder>(); files = new ArrayList<DaxFileHolder>(); } /** * Import workflow. * * @param file the file * @param properties the properties * @return the task graph * @throws TaskGraphException the task graph exception * @throws IOException Signals that an I/O exception has occurred. */ public TaskGraph importWorkflow(File file, TrianaProperties properties) throws TaskGraphException, IOException { devLog.debug("importWorkflow called."); setFile(file); NodeList jobList = getJobInfo(); if (jobList != null) { Vector<DaxJobHolder> jobHolders = getJobHoldersFromNodeList(jobList); listAllJobs(jobHolders); TaskGraph tg = null; if (jobList != null) { tg = createTaskGraph(jobList, properties); tg.setToolName(file.getName()); } tg.setParameter(DaxReader.ORIGINAL_DAX_FILE, file.getAbsolutePath()); return tg; } else { return null; } } /** * List all jobs. * * @param jobs the jobs */ private void listAllJobs(Vector<DaxJobHolder> jobs) { for (DaxJobHolder job : jobs) { devLog.debug("Found job : " + job.getToolname()); if (job.isCollection()) { devLog.debug("Is collection"); } else { devLog.debug("Is not a collection"); } } } /** * set the DAX file to create the workflow from. * * @param file the new file */ public void setFile(File file) { reset(); this.file = file; devLog.debug("Set dax input file as : " + getFileName()); setDoc(); } /** * Returns a list of all the nodes labelled "job". * * @return the job info */ private NodeList getJobInfo() { NodeList jobList = null; if (isValidDax()) { jobList = getNodeListFromTag("job"); devLog.debug("There are " + jobList.getLength() + " jobs listed in the DAX"); } else { devLog.debug("XML does not contain job items, is this a valid dax?"); return null; } return jobList; } /** * Gets the job holders from node list. * * @param jobList the job list * @return the job holders from node list */ public Vector<DaxJobHolder> getJobHoldersFromNodeList(NodeList jobList) { Vector<DaxJobHolder> sortedJobs = new Vector<DaxJobHolder>(); for (int i = 0; i < jobList.getLength(); i++) { Node node = jobList.item(i); NamedNodeMap map = node.getAttributes(); devLog.debug("Job " + i + " has " + map.getLength() + " attributes : " + listAllAttributes(map)); DaxJobHolder newJob = new DaxJobHolder(); String name = getNodeAttributeValue(node, "name"); newJob.setToolname(name); boolean repeatedJob = false; for (DaxJobHolder holder : sortedJobs) { if (holder.getToolname().equals(name)) { devLog.debug("SortedJobs already contains : " + name + ", so it will be a collection."); repeatedJob = true; holder.setCollection(true); } } if (!repeatedJob) { sortedJobs.add(newJob); devLog.debug("Added : " + name); } } return sortedJobs; } /** * Creates the task graph. * * @param jobList the job list * @param properties the properties * @return the task graph */ private TaskGraph createTaskGraph(NodeList jobList, TrianaProperties properties) { TaskGraph tg = null; try { // tg = GUIEnv.getApplicationFrame().addParentTaskGraphPanel(TaskGraphManager.createTaskGraph()); tg = TaskGraphManager.createTaskGraph(); } catch (TaskException e) { e.printStackTrace(); } findFiles(); for (Iterator iter = files.iterator(); iter.hasNext(); ) { DaxFileHolder dfh = (DaxFileHolder) (iter.next()); ToolImp tool = new ToolImp(properties); initFileTool(tool, dfh); try { tg.createTask(tool); } catch (TaskException e) { e.printStackTrace(); } } for (int i = 0; i < jobList.getLength(); i++) { Node node = jobList.item(i); NamedNodeMap map = node.getAttributes(); devLog.debug("Job " + i + " has " + map.getLength() + " attributes : " + listAllAttributes(map)); ToolImp tool = new ToolImp(properties); initJobTool(tool, node); try { Task task = tg.createTask(tool); JavaProxy jp = (JavaProxy) tool.getProxy(); } catch (Exception e) { e.printStackTrace(); } } for (Iterator iter = toolVector.iterator(); iter.hasNext(); ) { DaxJobHolder djh = (DaxJobHolder) (iter.next()); for (int i = 0; i < djh.getNumInputNodes(); i++) { devLog.debug("Job : " + djh.getToolname() + " has file : " + djh.getLinkAtInNode(i) + " at input node " + i); } for (int i = 0; i < djh.getNumOutputNodes(); i++) { devLog.debug("Job : " + djh.getToolname() + " has file : " + djh.getLinkAtOutNode(i) + " at output node " + i); } } attachCables(tg); devLog.debug("Attached Cables. Trying to organize taskgraph."); // tg = combineUnits(tg); return tg; } /** * Combine units. * * @param tg the tg * @return the task graph */ private TaskGraph combineUnits(TaskGraph tg) { Task[] tasks = tg.getTasks(false); for (Task task : tasks) { if (task.getDataInputNodeCount() > 3) { devLog.debug("Task : " + task.getToolName() + " has : " + task.getDataInputNodeCount() + " input nodes."); } if (task.getDataOutputNodeCount() > 3) { devLog.debug("Task : " + task.getToolName() + " has : " + task.getDataOutputNodeCount() + " output nodes."); } } for (DaxJobHolder djh : toolVector) { if (djh.getNumInputNodes() > 3) { devLog.debug("Job : " + djh.getToolname() + " has : " + djh.getNumInputNodes() + " input nodes."); HashMap inHash = djh.getFilesIn(); devLog.debug("Hash has : " + inHash.toString()); // for(int i = 0; i < inHash.size(); i++){ // for(int j = 0; j < inHash.size(); j++){ // devLog.debug("******* Found + " + lcs((String)inHash.get(i), (String)inHash.get(j))); // } // } } if (djh.getNumOutputNodes() > 3) { devLog.debug("Job : " + djh.getToolname() + " has : " + djh.getNumOutputNodes() + " output nodes."); HashMap outHash = djh.getFilesOut(); devLog.debug("Hash has : " + outHash.toString()); // for(int i = 0; i < outHash.size(); i++){ // for(int j = 0; j < outHash.size(); j++){ // devLog.debug(lcs((String)outHash.get(i), (String)outHash.get(j))); // } // } } } return tg; } /** * Lcs. * * @param a the a * @param b the b * @return the string */ public static String lcs(String a, String b) { devLog.debug("s.a : " + a + " s.b : " + b); int aLen = a.length(); int bLen = b.length(); if (aLen == 0 || bLen == 0) { return ""; } else if (a.charAt(aLen - 1) == b.charAt(bLen - 1)) { return lcs(a.substring(0, aLen - 1), b.substring(0, bLen - 1)) + a.charAt(aLen - 1); } else { String x = lcs(a, b.substring(0, bLen - 1)); String y = lcs(a.substring(0, aLen - 1), b); return (x.length() > y.length()) ? x : y; } } /** * Gets the task from tool. * * @param tool the tool * @return the task from tool */ private Task getTaskFromTool(Tool tool) { Task task = null; /* try { Proxy p = tool.getProxy(); devLog.debug("Got Proxy from Tool : " + p.toString()); if(p instanceof JavaProxy){ JavaProxy jp = (JavaProxy)p; devLog.debug("Cast Proxy to JavaProxy : " + jp.toString()); Unit unit = jp.getUnit(); devLog.debug("Got unit from proxy : " + unit.toString()); task = unit.getTask(); devLog.debug("Got task from unit." + task.toString()); } } catch (Exception e) { e.printStackTrace(); } */ return task; } /** * Takes an (largely unconnected) taskgraph and loops through the Vector of tools (JobUnits) * Loops through jobs input nodes, then output nodes. * Attaches jobs input and output nodes to the next available node from a files "DaxFileHolder" getUnconnected(In-Out)Node() * * @param tg the tg */ private void attachCables(TaskGraph tg) { for (Iterator iter = toolVector.iterator(); iter.hasNext(); ) { DaxJobHolder djh = (DaxJobHolder) iter.next(); Task jobTask = getTaskFromTool(djh.getTool()); if (jobTask == null) { jobTask = tg.getTask(djh.getJobID()); } for (int i = 0; i < djh.getNumInputNodes(); i++) { String link = djh.getLinkAtInNode(i); org.trianacode.taskgraph.Node fileNode = null; for (Iterator iter2 = files.iterator(); iter2.hasNext(); ) { DaxFileHolder dfh = (DaxFileHolder) iter2.next(); if (dfh.getFilename().equals(link)) { // String filesJobID = dfh.getJobAtOutNode(0); // String jobsID = djh.getJobID(); // if(!(filesJobID == null) && filesJobID.equals(jobsID)){ Task fileTask = tg.getTask(dfh.getFilename()); fileNode = fileTask.getOutputNode(dfh.getUnconnectedOutNode()); devLog.debug("Job : " + djh.getJobID() + " will connect input node " + i + " to file " + dfh.getFilename()); break; } } try { tg.connect(fileNode, jobTask.getDataInputNode(i)); } catch (CableException e) { e.printStackTrace(); } } for (int i = 0; i < djh.getNumOutputNodes(); i++) { String link = djh.getLinkAtOutNode(i); org.trianacode.taskgraph.Node fileNode = null; for (Iterator iter2 = files.iterator(); iter2.hasNext(); ) { DaxFileHolder dfh = (DaxFileHolder) iter2.next(); if (dfh.getFilename().equals(link)) { // String filesJobID = dfh.getJobAtInNode(0); // String jobsID = djh.getJobID(); // if(!(filesJobID == null) && filesJobID.equals(jobsID)){ Task fileTask = tg.getTask(dfh.getFilename()); fileNode = fileTask.getInputNode(dfh.getUnconnectedInNode()); devLog.debug("Job : " + djh.getJobID() + " will connect output node " + i + " to file " + dfh.getFilename()); break; } } try { tg.connect(jobTask.getDataOutputNode(i), fileNode); } catch (CableException e) { e.printStackTrace(); } } } } /** * Finds all nodes labelled "job" in DAX,. */ private void findFiles() { NodeList jobLst = doc.getElementsByTagName("job"); Vector<String> filenames = new Vector<String>(); for (int j = 0; j < jobLst.getLength(); j++) { Node jobNode = jobLst.item(j); NodeList nodeLst = jobNode.getChildNodes(); for (int i = 0; i < nodeLst.getLength(); i++) { Node node = nodeLst.item(i); if (node.getNodeName().equals("uses")) { // NamedNodeMap map = node.getAttributes(); // String fileName = map.getNamedItem("file").getNodeValue(); String fileName = getNodeAttributeValue(node, "file"); if (fileName == null) { fileName = getNodeAttributeValue(node, "name"); } // devLog.debug("Getting info for file : " + fileName); if (!filenames.contains(fileName)) { filenames.add(fileName); DaxFileHolder dfh = new DaxFileHolder(); dfh.setFilename(fileName); String parentID = getNodeAttributeValue(jobNode, "id"); //devLog.debug("Files parent is job : " + parentID); if (getNodeAttributeValue(node, "link").equals("input")) { int nodeNumber = dfh.getFreeOutNode(); dfh.addJobOut(nodeNumber, parentID); devLog.debug("File " + fileName + " has job " + parentID + " attached to output node : " + nodeNumber); } if (getNodeAttributeValue(node, "link").equals("output")) { int nodeNumber = dfh.getFreeInNode(); dfh.addJobIn(nodeNumber, parentID); devLog.debug("File " + fileName + " has job " + parentID + " attached to input node : " + nodeNumber); } files.add(dfh); } else { for (Iterator iter = files.iterator(); iter.hasNext(); ) { DaxFileHolder dfh = (DaxFileHolder) iter.next(); if (dfh.getFilename().equals(fileName)) { String parentID = getNodeAttributeValue(jobNode, "id"); devLog.debug("Files parent is job : " + parentID); if (getNodeAttributeValue(node, "link").equals("input")) { int nodeNumber = dfh.getFreeOutNode(); dfh.addJobOut(nodeNumber, parentID); devLog.debug("File " + fileName + " has job " + parentID + " attached to output node : " + nodeNumber); } if (getNodeAttributeValue(node, "link").equals("output")) { int nodeNumber = dfh.getFreeInNode(); dfh.addJobIn(nodeNumber, parentID); devLog.debug("File " + fileName + " has job " + parentID + " attached to input node : " + nodeNumber); } } } } } } } listKnownFileData(); } /** * Method to list the jobs associated with certain nodes of each file found so far. */ private void listKnownFileData() { devLog.debug("\n**** System knows this about files:"); for (Iterator i = files.iterator(); i.hasNext(); ) { DaxFileHolder dfh = (DaxFileHolder) (i.next()); for (int j = 0; j < dfh.getNumInputNodes(); j++) { devLog.debug("File : " + dfh.getFilename() + " has job : " + dfh.getJobAtInNode(j) + " at input node " + j); } for (int j = 0; j < dfh.getNumOutputNodes(); j++) { devLog.debug("File : " + dfh.getFilename() + " has job : " + dfh.getJobAtOutNode(j) + " at output node " + j); } } } /** * Fills the tool with information taken from the job node of a DAX * All tools created are of type "JobUnit". * Created tool should have the correct number of input and output nodes * * @param tool the tool * @param node the node */ private void initJobTool(ToolImp tool, Node node) { DaxJobHolder djh = new DaxJobHolder(); String toolname = getNodeAttributeValue(node, "id"); tool.setParameter("name", getNodeAttributeValue(node, "name")); tool.setToolName(toolname); tool.setSubTitle((String) tool.getParameter("name")); devLog.debug("Subtitle set to : " + tool.getSubTitle()); int inputNodes = 0; int outputNodes = 0; NodeList nl = node.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node childNode = nl.item(i); if (childNode.getNodeName().equals("uses")) { NamedNodeMap map = childNode.getAttributes(); // devLog.debug("Job uses : " + listAllAttributes(map)); if (map.getNamedItem("link").getNodeValue().equals("input")) { String fileName; if (map.getNamedItem("file") != null) { fileName = map.getNamedItem("file").getNodeValue(); } else { fileName = map.getNamedItem("name").getNodeValue(); } djh.addFileIn(inputNodes, fileName); inputNodes++; } if (map.getNamedItem("link").getNodeValue().equals("output")) { String fileName; if (map.getNamedItem("file") != null) { fileName = map.getNamedItem("file").getNodeValue(); } else { fileName = map.getNamedItem("name").getNodeValue(); } djh.addFileOut(outputNodes, fileName); outputNodes++; } } if (childNode.getNodeName().equals("argument")) { tool.setParameter("args", childNode.getTextContent().trim()); devLog.debug("Job tool will have args : " + childNode.getTextContent()); } } try { tool.setDataInputNodeCount(inputNodes); tool.setDataOutputNodeCount(outputNodes); tool.setToolPackage(daxPackage); tool.setProxy(makeProxy(daxJobUnitName, daxPackage)); } catch (Exception e) { e.printStackTrace(); } djh.setToolname(toolname); djh.setJobID(getNodeAttributeValue(node, "id")); djh.setTrianaToolName("T-" + toolname); djh.setNumInputNodes(inputNodes); djh.setNumOutputNodes(outputNodes); djh.setTool(tool); devLog.debug("Job " + toolname + " has " + inputNodes + " inputNodes, and " + outputNodes + " outputNodes."); String inputs = ""; String outputs = ""; for (int i = 0; i < djh.getNumInputNodes(); i++) { inputs += "Node " + i + " : " + djh.getLinkAtInNode(i) + " "; } for (int i = 0; i < djh.getNumOutputNodes(); i++) { outputs += "Node " + i + " : " + djh.getLinkAtOutNode(i) + " "; } devLog.debug("It has " + inputs + " as input, and " + outputs + " as output.\n"); toolVector.add(djh); } /** * Inits the file tool. * * @param tool the tool * @param dfh the dfh */ private void initFileTool(ToolImp tool, DaxFileHolder dfh) { tool.setToolName(dfh.getFilename()); tool.setParameter("fileName", dfh.getFilename()); int inputNodes = dfh.getNumInputNodes(); int outputNodes = dfh.getNumOutputNodes(); devLog.debug("Creating file : " + dfh.getFilename() + " with " + inputNodes + " inputnodes and " + outputNodes + " outputnodes."); try { tool.setDataInputNodeCount(inputNodes); tool.setDataOutputNodeCount(outputNodes); tool.setToolPackage(daxPackage); tool.setProxy(makeProxy(daxFileUnitName, daxPackage)); } catch (TaskException e) { e.printStackTrace(); } } /** * Make proxy. * * @param filename the filename * @param packageLocation the package location * @return the proxy */ private Proxy makeProxy(String filename, String packageLocation) { HashMap details = new HashMap(); details.put("unitName", (filename)); details.put("unitPackage", (packageLocation)); Proxy proxy = null; try { proxy = ProxyFactory.createProxy("Java", details); } catch (ProxyInstantiationException e) { e.printStackTrace(); } return proxy; } /** * Gets the node attribute value. * * @param node the node * @param name the name * @return the node attribute value */ private String getNodeAttributeValue(Node node, String name) { Node child = node.getAttributes().getNamedItem(name); if (child != null) { return node.getAttributes().getNamedItem(name).getNodeValue(); } else { return null; } } /** * Gets the file. * * @return the file */ public File getFile() { return file; } /** * Gets the file name. * * @return the file name */ public String getFileName() { return file.getName(); } /** * Sets the doc variable which will be used as the root node when building tools from the DAX. */ private void setDoc() { try { BufferedInputStream bufferedInput = new BufferedInputStream(new FileInputStream(file)); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); doc = db.parse(bufferedInput); doc.getDocumentElement().normalize(); } catch (Exception e) { } } /** * Checks if the first string in the file is "adag". * * @return true, if is valid dax */ private boolean isValidDax() { String rootString = doc.getDocumentElement().getNodeName(); devLog.debug("Root element : " + rootString); if (rootString.equals("adag")) { devLog.debug("File " + getFileName() + " is a valid DAX"); return true; } else { devLog.debug("File " + getFileName() + " is not a valid DAX"); return false; } } /** * Gets the node list from tag. * * @param tagName the tag name * @return the node list from tag */ private NodeList getNodeListFromTag(String tagName) { NodeList nodeLst = doc.getElementsByTagName(tagName); return nodeLst; } /** * Lists all the attributes in the NamedNodeMap. * * @param map the map * @return the string */ private String listAllAttributes(NamedNodeMap map) { String listString = ""; for (int i = 0; i < map.getLength(); i++) { Node node = map.item(i); listString += node.getNodeName(); listString += " = " + node.getNodeValue() + " : "; } return listString; } }