/* * Copyright 2009 Wishnu Prasetya. * * You can redistribute and/or modify this class under * the terms of the GNU General Public License (GPL) as published by the * Free Software Foundation; either version 3 of the License, or any * later version. */ package Sequenic.Graph; import java.io.Serializable; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Map.Entry; /** * Representing a node in a graph. * * @author Wishnu Prasetya * */ public class Vertex implements Serializable { private static final long serialVersionUID = 1L; /** * The node's id. */ private int id; public Vertex(){ super() ; } // public List parents = new LinkedList() ; // public List children = new LinkedList() ; private Map childEdges = new HashMap(); private Set childVertices = new HashSet(); private Set parentVertices = new HashSet(); public static final String LABEL_DEFAULT = "_"; public static final String LABEL_TRUE = "T"; public static final String LABEL_FALSE = "F"; public int outDegree(){ return childVertices.size();} public int inDegree(){ return parentVertices.size();} public Map childEdges(){ return childEdges; } public Collection children(){ return childVertices; } public Collection parents(){ return parentVertices; } public void addChild(Vertex v, String label){ if(childEdges.containsKey(label)){ if(!childEdges.get(label).equals(v)) throw new IllegalArgumentException("A single outgoing label can not point to two different vertices: label =" + label); } else { childEdges.put(label, v); childVertices.add(v); v.parentVertices.add(this); } } /** * Unlink this node: remove links to it from all of its parents and remove the links to its parents. * */ public void unlink(){ Iterator iter; for(Vertex parent : parentVertices){ parent.childVertices.remove(this); iter = parent.childEdges.values().iterator(); while(iter.hasNext()){ if(iter.next()==this) iter.remove(); } } parentVertices.clear(); } /** True if child is a child of this vertex. * * @param child * @return */ public boolean isChild(Vertex child){ return childVertices.contains(child); } /** * Returns the child that is reached when following label l from this node. * Returns null if there is no outgoing edge with label l. * * @param label * @return */ public Vertex getChild(String label){ return childEdges.get(label); } @Override public String toString() { return Integer.toString(getId()) ; } public void printEdges(StringBuffer out){ out.append(toString()).append(" --> "); String s = ""; for(Entry kv : childEdges.entrySet()){ out.append(s).append(kv.getKey().toString()).append(":").append(kv.getValue().toString()); s = ", "; } if(s=="") out.append(" no-children"); } /** Note id's are restricted to be in the range [0..65535]. * I.e. only the lower 16 bits may be set. * * TODO: Restrict further to the range [0..Short.MAX] * Also, make id a final field, that is set in the constructor. * Finally, modify CFG so that startNodes are required to have id==0. * */ public void setId(int id) { if(id >>> 16 != 0) throw new IllegalArgumentException("id must be in the range [0..65535]."); this.id = id; } public int getId() { return id; } public static String labelForSwitchCase(int i){ return Integer.toString(i); } }