Quadcap Embeddable Server

com/quadcap/util/collections/DiGraph.java

Go to the documentation of this file.
00001 package com.quadcap.util.collections; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 //-//#ifdef JDK11 00042 //-import com.sun.java.util.collections.ArrayList; 00043 //-import com.sun.java.util.collections.Comparable; 00044 //-import com.sun.java.util.collections.HashMap; 00045 //-import com.sun.java.util.collections.HashSet; 00046 //-import com.sun.java.util.collections.Iterator; 00047 //-import com.sun.java.util.collections.Map; 00048 //-import com.sun.java.util.collections.Set; 00049 //#else 00050 import java.util.ArrayList; 00051 import java.util.HashMap; 00052 import java.util.HashSet; 00053 import java.util.Iterator; 00054 import java.util.Map; 00055 import java.util.Set; 00056 //#endif 00057 00058 import com.quadcap.util.Debug; 00059 00060 /** 00061 * A simple implementation of a directed graph of Objects. Each node 00062 * is represented using HashSets of incoming and outgoing arcs. 00063 * 00064 * @author Stan Bailes 00065 */ 00066 public class DiGraph { 00067 // Could replace by any Map 00068 final HashMap nodes = new HashMap(); 00069 00070 public DiGraph() {} 00071 00072 public void addNode(Object obj) { 00073 mapNode(obj); 00074 } 00075 00076 public final Iterator getNodes() { 00077 return new NodeIterator(nodes.values().iterator()); 00078 } 00079 00080 public void addArc(Object from, Object to) { 00081 Node f = mapNode(from); 00082 Node t = mapNode(to); 00083 f.addTo(t); 00084 t.addFrom(f); 00085 } 00086 00087 public final boolean hasChildren(Object obj) { 00088 return mapNode(obj).toSize() > 0; 00089 } 00090 00091 public final boolean hasParents(Object obj) { 00092 return mapNode(obj).fromSize() > 0; 00093 } 00094 00095 public boolean hasNode(Object obj) { 00096 Node node = (Node)nodes.get(obj); 00097 return node != null; 00098 } 00099 00100 public final Iterator getParents(Object to) { 00101 return new NodeIterator(mapNode(to).iterateFrom()); 00102 } 00103 00104 public final Iterator getChildren(Object from) { 00105 return new NodeIterator(mapNode(from).iterateTo()); 00106 } 00107 00108 public void removeNode(Object obj, boolean force) { 00109 Node node = mapNode(obj); 00110 if (!force) { 00111 if (node.toSize() != 0 || node.fromSize() != 0) { 00112 throw new RuntimeException("node has links"); 00113 } 00114 } else { 00115 Iterator iter = node.iterateTo(); 00116 while (iter.hasNext()) { 00117 Node to = (Node)iter.next(); 00118 node.removeTo(to); 00119 to.removeFrom(node); 00120 } 00121 iter = node.iterateFrom(); 00122 while (iter.hasNext()) { 00123 Node from = (Node)iter.next(); 00124 node.removeFrom(from); 00125 from.removeTo(node); 00126 } 00127 } 00128 nodes.remove(obj); 00129 } 00130 00131 public void removeArc(Object from, Object to) { 00132 Node f = mapNode(from); 00133 Node t = mapNode(to); 00134 f.removeTo(t); 00135 t.removeFrom(f); 00136 } 00137 00138 public Iterator levelize() { 00139 return levelize(false); 00140 } 00141 00142 public Iterator levelize(boolean cyclesOK) { 00143 ArrayList v = new ArrayList(); 00144 Iterator iter = nodes.values().iterator(); 00145 while (iter.hasNext()) { 00146 Node node = (Node)iter.next(); 00147 node.level = -1; 00148 node.visitCnt = 0; 00149 if (node.fromSize() == 0) { 00150 node.level = 0; 00151 v.add(node); 00152 } 00153 } 00154 for (int i = 0; i < v.size(); i++) { 00155 Node node = (Node)v.get(i); 00156 Iterator t = node.iterateTo(); 00157 while (t.hasNext()) { 00158 Node to = (Node)t.next(); 00159 if (++to.visitCnt == to.fromSize()) { 00160 to.level = node.level + 1; 00161 v.add(to); 00162 } 00163 } 00164 } 00165 if (!cyclesOK && v.size() != nodes.size()) { 00166 throw new RuntimeException("can't levelize, contains cycles"); 00167 } 00168 return new NodeIterator(v.iterator()); 00169 } 00170 00171 public String toString() { 00172 StringBuffer sb = new StringBuffer(); 00173 Iterator iter = getNodes(); 00174 String ldelim = ""; 00175 while (iter.hasNext()) { 00176 sb.append(ldelim); 00177 ldelim = "\n"; 00178 Object obj = iter.next(); 00179 Iterator i2 = getParents(obj); 00180 String delim = ""; 00181 sb.append("("); 00182 while (i2.hasNext()) { 00183 sb.append(delim); 00184 delim = " "; 00185 sb.append(i2.next().toString()); 00186 } 00187 sb.append(") "); 00188 sb.append(obj.toString()); 00189 sb.append(" ("); 00190 i2 = getChildren(obj); 00191 delim = ""; 00192 while (i2.hasNext()) { 00193 sb.append(delim); 00194 delim = " "; 00195 sb.append(i2.next().toString()); 00196 } 00197 sb.append(") "); 00198 } 00199 return sb.toString(); 00200 } 00201 00202 final Node mapNode(Object obj) { 00203 Node node = (Node)nodes.get(obj); 00204 if (node == null) { 00205 node = new Node(obj); 00206 nodes.put(obj, node); 00207 } 00208 return node; 00209 } 00210 00211 class Node implements Comparable { 00212 Object obj; 00213 00214 final HashSet to = new HashSet(); 00215 final HashSet from = new HashSet(); 00216 int level = 0; 00217 int visitCnt = 0; 00218 00219 Node(Object obj) { this.obj = obj; } 00220 void addTo(Node node) { 00221 to.add(node); 00222 } 00223 void addFrom(Node node) { 00224 from.add(node); 00225 } 00226 void removeTo(Node obj) { to.remove(obj); } 00227 void removeFrom(Node obj) { from.remove(obj); } 00228 00229 int toSize() { return to.size(); } 00230 int fromSize() { return from.size(); } 00231 00232 Iterator iterateTo() { return to.iterator(); } 00233 Iterator iterateFrom() { return from.iterator(); } 00234 00235 public int compareTo(Object other) { 00236 Node no = (Node)other; 00237 return ((Comparable)obj).compareTo(no.obj); 00238 } 00239 00240 public int hashCode() { return obj.hashCode(); } 00241 00242 public boolean equals(Object obj) { 00243 return 0 == compareTo(obj); 00244 } 00245 public String toString() { 00246 return obj.toString(); 00247 } 00248 } 00249 00250 class NodeIterator implements Iterator { 00251 Iterator iter; 00252 NodeIterator(Iterator iter) { this.iter = iter; } 00253 public boolean hasNext() { return iter.hasNext(); } 00254 public Object next() { 00255 Node node = (Node)iter.next(); 00256 return node.obj; 00257 } 00258 public void remove() {} 00259 } 00260 } 00261