/** * Copyright 2007-2008 University Of Southern California * * 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 edu.isi.pegasus.planner.parser.dax; import edu.isi.pegasus.common.logging.LogManagerFactory; import edu.isi.pegasus.planner.catalog.transformation.TransformationCatalogEntry; import edu.isi.pegasus.planner.classes.CompoundTransformation; import edu.isi.pegasus.planner.classes.Job; import edu.isi.pegasus.planner.classes.ReplicaLocation; import edu.isi.pegasus.planner.partitioner.graph.GraphNode; import edu.isi.pegasus.planner.common.PegasusProperties; import edu.isi.pegasus.planner.dax.Invoke; import edu.isi.pegasus.common.logging.LogManager; import edu.isi.pegasus.planner.classes.PegasusBag; import edu.isi.pegasus.planner.classes.Profile; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * This callback implementation ends up building a detailed structure of the * graph referred to by the abstract plan in dax, that should make the graph * traversals easier. Later on this graph representation would be used * uniformly in the Pegasus code base. * * @author Karan Vahi * @version $Revision$ */ public class DAX2Graph implements Callback { /** * The id of the dummy root node added on the top of the graph. Makes * easier the starting of the traversal. */ public static final String DUMMY_NODE_ID = "dummy"; /** * The map containing the a graph node for each of the jobs referred to in * the dax. The key is the logical id of the job. */ protected Map mAbstractGraph; /** * A flag to specify whether the graph has been generated for the partition * or not. */ protected boolean mDone; /** * The label of the abstract dax as set by Chimera. */ protected String mLabel; /** * The root node for the graph that is constructed. */ protected GraphNode mRoot; /** * The handle to the properties object. */ protected PegasusProperties mProps; /** * The logging object. */ protected LogManager mLogger; /** * The overloaded constructor. * * @param bag the bag of initialization objects containing the properties * and the logger * @param dax the path to the DAX file. */ public void initialize( PegasusBag bag, String dax ){ mProps = bag.getPegasusProperties(); mAbstractGraph = new java.util.HashMap(); mLogger = bag.getLogger(); mDone = false; mLabel = null; mRoot = null; } /** * Returns a Map indexed by the logical ID of the jobs, and each value being * a GraphNode object. * * @return ADag object containing the abstract plan referred in the dax. */ public Object getConstructedObject() { if(!mDone) throw new RuntimeException("Method called before the abstract dag " + " for the partition was fully generated"); return mAbstractGraph; } /** * Callback when the opening tag was parsed. This contains all * attributes and their raw values within a map. It ends up storing * the attributes with the adag element in the internal memory structure. * * @param attributes is a map of attribute key to attribute value */ public void cbDocument(Map attributes) { /**@todo Implement this org.griphyn.cPlanner.parser.Callback method*/ if( attributes == null || (mLabel = (String)attributes.get("name")) == null){ mLabel = "test"; } } /** * Callback when a invoke entry is encountered in the top level inside the adag element in the DAX. * * @param invoke the invoke object */ public void cbWfInvoke(Invoke invoke){ throw new UnsupportedOperationException("Not supported yet."); } /** * Callback when a metadata element is encountered in the adag element. * * @param profile profile element of namespace metadata */ public void cbMetadata( Profile p ){ throw new UnsupportedOperationException("Not supported yet."); } /** * This constructs a graph node for the job and ends up storing it in the * internal map. * * @param job the job that was parsed. */ public void cbJob( Job job ) { GraphNode gn = new GraphNode( job.getLogicalID(), job.getTXName() ); mLogger.log( "Adding job to graph " + job.getName() , LogManager.DEBUG_MESSAGE_LEVEL ); put( job.logicalId, gn ); } /** * This updates the internal graph nodes of child with references to it's * parents referred to by the list of parents passed. It gets the handle * to the parents graph nodes from it's internal map. * * @param child the logical id of the child node. * @param parents list containing the logical id's of the parents of the * child nodes. */ public void cbParents(String child, List parents) { GraphNode childNode = (GraphNode)get(child); Iterator it = parents.iterator(); String parentId; ArrayList parentList = new ArrayList(parents.size()); mLogger.log( "Adding parents for child " + child, LogManager.DEBUG_MESSAGE_LEVEL ); //construct the references to the parent nodes while(it.hasNext()){ parentId = (String)it.next(); GraphNode parentNode = (GraphNode)get(parentId); parentList.add(parentNode); //add the child to the parent's child list parentNode.addChild(childNode); } childNode.setParents(parentList); } /** * Returns the name of the dax. * * @return name of dax */ public String getNameOfDAX(){ return mLabel; } /** * Callback to signal that traversal of the DAX is complete. At this point a * dummy root node is added to the graph, that is the parents to all the root * nodes in the existing DAX. */ public void cbDone() { //the abstract graph is fully generated mDone = true; //just print out the graph that is generated internally. //find the root nodes from where to start the breadth first //search Iterator it = mAbstractGraph.entrySet().iterator(); List rootNodes = new LinkedList(); while(it.hasNext()){ GraphNode gn = (GraphNode)((java.util.Map.Entry)it.next()).getValue(); if(gn.getParents() == null || gn.getParents().isEmpty()){ rootNodes.add(gn); } //System.out.println(gn); } //add a dummy node that is a root to all these nodes. String rootId = this.DUMMY_NODE_ID; mRoot = new GraphNode(rootId,rootId); mRoot.setChildren(rootNodes); put(rootId,mRoot); //System.out.println(dummyNode); } /** * It puts the key and the value in the internal map. * * @param key the key to the entry in the map. * @param value the entry in the map. */ protected void put(Object key, Object value){ mAbstractGraph.put(key,value); } /** * It returns the value associated with the key in the map. * * @param key the key to the entry in the map. * * @return the object */ public Object get(Object key){ return mAbstractGraph.get(key); } /** * Callback when a compound transformation is encountered in the DAX * * @param compoundTransformation the compound transforamtion */ public void cbCompoundTransformation( CompoundTransformation compoundTransformation ){ throw new UnsupportedOperationException("Not supported yet."); } /** * Callback when a replica catalog entry is encountered in the DAX * * @param rl the ReplicaLocation object */ public void cbFile( ReplicaLocation rl ){ throw new UnsupportedOperationException("Not supported yet."); } /** * Callback when a transformation catalog entry is encountered in the DAX * * @param tce the transformation catalog entry object. */ public void cbExecutable( TransformationCatalogEntry tce ){ throw new UnsupportedOperationException("Not supported yet."); } }