/** * 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.partitioner.graph; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; import edu.isi.pegasus.planner.classes.Data; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * Data class that allows us to construct information about the nodes * in the abstract graph. Contains for each node the references to it's * parents and children. The direction of the edges is usually following the * children from a node. Parents are kept to facilitate bottom up traversals. * * @author Karan Vahi * @version $Revision$ */ public class GraphNode extends Data { //the constants for the color of the nodes public static final int WHITE_COLOR = 0; public static final int GRAY_COLOR = 1; public static final int BLACK_COLOR = 2; /** * The logical id of the job as identified in the dax. */ private String mLogicalID; /** * The logical name of the node as identified in the dax. */ private String mLogicalName; /** * The depth of the node from the root or any arbitary node. */ private int mDepth; /** * The color the node is colored. */ private int mColor; /** * The list of parents of the job/node in the abstract graph. Each element * of the list is a <code>GraphNode</code> object. */ private Set<GraphNode> mParents; /** * The list of children of the job/node in the abstract graph. Each element * of the list is a <code>GraphNode</code> object. */ private Set<GraphNode> mChildren; /** * The content associated with this node. */ @Expose @SerializedName( "content" ) private GraphNodeContent mContent; /** * A Bag of objects that maybe associated with the node. * * @see Bag */ private Bag mBag; /** * The default constructor. */ public GraphNode() { mLogicalID = ""; this.resetEdges(); mDepth = -1; mLogicalName = ""; mColor = this.WHITE_COLOR; mBag = null; } /** * The overloaded constructor. * * @param id the id of the node in the graph. */ public GraphNode( String id ){ this(); mLogicalID = id; } /** * The overloaded constructor. * * @param id the id of the node in the graph. * @param content the content to be associated with the node. */ public GraphNode( String id, GraphNodeContent content ){ this(); mLogicalID = id; mContent = content; mContent.setGraphNodeReference(this); } /** * The overloaded constructor. * * @param id the logical id of the node. * @param name the name of the node. */ public GraphNode(String id, String name) { mLogicalID = id; mParents = new HashSet(); mChildren = new HashSet(); mDepth = -1; mLogicalName = name; mColor = this.WHITE_COLOR; } /** * Sets the bag of objects associated with the node. Overwrite the previous * bag if existing. * * @param bag the <code>Bag</code> to be associated with the node. */ public void setBag( Bag bag ) { mBag = bag; } /** * Sets the content associated with the node. Overwrites the previous * content if existing. * * @param content the <code>GraphNodeContent</code> to be associated with the node. */ public void setContent( GraphNodeContent content ) { mContent = content; mContent.setGraphNodeReference( this ); } /** * It adds the parents to the node. It ends up overwriting all the existing * parents if some already exist. * @param parents */ public void setParents( Collection<GraphNode> parents ) { mParents = ( parents instanceof Set)? (Set)parents:new HashSet(parents); } /** * It sets the children to the node. It ends up overwriting all the existing * parents if some already exist. * @param children */ public void setChildren( Collection<GraphNode> children ) { mChildren = ( children instanceof Set)? (Set)children: new HashSet(children); } /** * Sets the depth associated with the node. * @param depth */ public void setDepth( int depth ) { mDepth = depth; } /** * Returns the bag of objects associated with the node. * * @return the bag or null if no bag associated */ public Bag getBag(){ return mBag; } /** * Returns the content associated with the node. * * @return the content or null if no content associated */ public GraphNodeContent getContent(){ return mContent; } /** * Returns a list of <code>GraphNode</code> objects that are parents of the node. * * @return list of <code>GraphNode</code> objects. */ public Collection<GraphNode> getParents() { return mParents; } /** * Returns a list of <code>GraphNode</code> objects that are children of the * node. * * @return list of <code>GraphNode</code> objects. */ public Collection<GraphNode> getChildren() { return mChildren; } /** * Adds a child to end of the child list. * * @param child adds a child to the node. */ public void addChild( GraphNode child ) { mChildren.add( child ); } /** * Adds a parent to end of the parent list. * * @param parent adds a parent to the node. */ public void addParent( GraphNode parent ) { mParents.add( parent ); } /** * Removes a child linkage to the node. * * @param child child to be removed. */ public void removeChild( GraphNode child ){ mChildren.remove( child ); } /** * Removes a parent linkage to the node. * * @param parent parent to be removed. */ public void removeParent( GraphNode parent ){ mParents.remove( parent ); } /** * Reset all the edges associated with this node. */ public final void resetEdges() { mParents = new HashSet(); mChildren = new HashSet(); } /** * Returns the logical id of the graph node. */ public String getID() { return mLogicalID; } /** * Returns the logical name of the graph node. */ public String getName() { return mLogicalName; } /** * Returns the depth of the node in the graph. */ public int getDepth() { return mDepth; } /** * Returns if the color of the node is as specified. * * @param color color that node should be. */ public boolean isColor( int color ){ return (mColor == color)?true:false; } /** * Sets the color of the node to the color specified * * @param color color that node should be. */ public void setColor( int color ){ mColor = color; } /** * Gets the color of the node to the color specified * * @return */ public int getColor( ){ return mColor; } /** * Returns if all the parents of that node have the color that is specified. * * @param color the color of the node. * * @return true if there are no parents or all parents are of the color. * false in all other cases. */ public boolean parentsColored( int color ) { boolean colored = true; GraphNode par; if (mParents == null) { return colored; } Iterator it = mParents.iterator(); while (it.hasNext() && colored) { par = (GraphNode) it.next(); colored = par.isColor(color); } return colored; } /** * Returns if all the children of the node have the color that is specified. * * @param color the color of the node. * * @return true if there are no children or all children are of the color. * false in all other cases. */ public boolean childrenColored( int color ) { boolean colored = true; GraphNode child; if (mChildren == null) { return colored; } Iterator<GraphNode> it = mChildren.iterator(); while (it.hasNext() && colored) { child = (GraphNode) it.next(); colored = child.isColor(color); } return colored; } /** * A convenience methods that generates a comma separated list of parents * as String * * @return String */ public String parentsToString(){ StringBuffer sb = new StringBuffer(); sb.append( "{" ); for( GraphNode n : this.getParents() ){ sb.append( n.getID() ).append( "," ); } sb.append( "}" ); return sb.toString(); } /** * A convenience methods that generates a comma separated list of children * as String * * @return String */ public String childrenToString(){ StringBuffer sb = new StringBuffer(); sb.append( "{" ); for( GraphNode n : this.getChildren() ){ sb.append( n.getID() ).append( "," ); } sb.append( "}" ); return sb.toString(); } /** * The textual representation of the graph node. * * @return textual description. */ public String toString() { StringBuffer sb = new StringBuffer(); Iterator it; sb.append( "ID->" ).append(mLogicalID).append( " name->" ). append( mLogicalName ).append( " parents->" ). append( this.parentsToString() ); sb.append( "} children->" ).append( this.childrenToString() ); sb.append( " Content-{" ).append( getContent() ).append( "}" ); sb.append( " Bag-{" ).append( getBag() ).append( "}" ); return sb.toString(); } /** * Matches two GraphNode objects. A GraphNode object is considered * equal to another if there id's match. * * @param obj the reference object with which to compare. * @return true, if the primary keys match, false otherwise. */ public boolean equals(Object obj) { // ward against null if ( obj == null ) { return false; } // shortcut if ( obj == this ) { return true; } // don't compare apples with oranges if ( ! (obj instanceof GraphNode) ){ return false; } // now we can safely cast GraphNode d = (GraphNode) obj; return this.getID().equals( d.getID() ); } /** * Calculate a hash code value for the object to support hash based Collections. * * @return a hash code value for the object. */ public int hashCode() { return this.getID().hashCode(); } /** * Returns a copy of the object. */ public Object clone(){ return new java.lang.CloneNotSupportedException( "Clone() not implemented in GraphNode"); } }