1 19 package org.openide.util; 20 21 import java.util.*; 22 23 24 32 public final class TopologicalSortException extends Exception { 33 34 private Collection vertexes; 35 36 37 private Map edges; 38 39 40 private Set[] result; 41 42 43 private int counter; 44 45 46 private Stack<Vertex> dualGraph = new Stack<Vertex>(); 47 48 TopologicalSortException(Collection vertexes, Map edges) { 49 this.vertexes = vertexes; 50 this.edges = edges; 51 } 52 53 58 public final List partialSort() { 59 Set[] all = topologicalSets(); 60 61 ArrayList<Object > res = new ArrayList<Object >(vertexes.size()); 62 63 for (int i = 0; i < all.length; i++) { 64 for (Object e : all[i]) { 65 res.add(e); 66 } 67 } 68 69 return res; 70 } 71 72 83 public final Set[] unsortableSets() { 84 Set[] all = topologicalSets(); 85 86 ArrayList<Set> unsort = new ArrayList<Set>(); 87 88 for (int i = 0; i < all.length; i++) { 89 if ((all[i].size() > 1) || !(all[i] instanceof HashSet)) { 90 unsort.add(all[i]); 91 } 92 } 93 94 return unsort.toArray(new Set[0]); 95 } 96 97 100 public final void printStackTrace(java.io.PrintWriter w) { 101 w.print("TopologicalSortException - Collection: "); w.print(vertexes); 103 w.print(" with edges "); w.print(edges); 105 w.println(" cannot be sorted"); 107 Set[] bad = unsortableSets(); 108 109 for (int i = 0; i < bad.length; i++) { 110 w.print(" Conflict #"); w.print(i); 112 w.print(": "); w.println(bad[i]); 114 } 115 116 super.printStackTrace(w); 117 } 118 119 122 public final void printStackTrace(java.io.PrintStream s) { 123 java.io.PrintWriter w = new java.io.PrintWriter (s); 124 this.printStackTrace(w); 125 w.flush(); 126 } 127 128 143 public final Set[] topologicalSets() { 144 if (result != null) { 145 return result; 146 } 147 148 HashMap<Object ,Vertex> vertexInfo = new HashMap<Object ,Vertex>(); 149 150 counter = 0; 152 153 Iterator it = vertexes.iterator(); 154 155 while (it.hasNext()) { 156 constructDualGraph(counter, it.next(), vertexInfo); 157 } 158 159 Map<Object ,Set> objectsToSets = new HashMap<Object ,Set>(); 163 164 ArrayList<Set> sets = new ArrayList<Set>(); 165 166 while (!dualGraph.isEmpty()) { 167 Vertex v = dualGraph.pop(); 168 169 if (!v.visited) { 170 Set<Object > set = new HashSet<Object >(); 171 visitDualGraph(v, set); 172 173 if ((set.size() == 1) && v.edgesFrom.contains(v)) { 174 set = Collections.singleton(v.object); 181 } 182 183 sets.add(set); 184 185 it = set.iterator(); 187 188 while (it.hasNext()) { 189 objectsToSets.put(it.next(), set); 190 } 191 } 192 } 193 194 HashMap<Set,Collection<Set>> edgesBetweenSets = new HashMap<Set,Collection<Set>>(); 197 it = edges.entrySet().iterator(); 198 199 while (it.hasNext()) { 200 Map.Entry entry = (Map.Entry) it.next(); 201 Collection leadsTo = (Collection) entry.getValue(); 202 203 if ((leadsTo == null) || leadsTo.isEmpty()) { 204 continue; 205 } 206 207 Set from = objectsToSets.get(entry.getKey()); 208 209 Collection<Set> setsTo = edgesBetweenSets.get(from); 210 211 if (setsTo == null) { 212 setsTo = new ArrayList<Set>(); 213 edgesBetweenSets.put(from, setsTo); 214 } 215 216 Iterator convert = leadsTo.iterator(); 217 218 while (convert.hasNext()) { 219 Set to = objectsToSets.get(convert.next()); 220 221 if (from != to) { 222 setsTo.add(to); 224 } 225 } 226 } 227 228 try { 230 List<Set> listResult = Utilities.topologicalSort(sets, edgesBetweenSets); 231 result = listResult.toArray(new Set[0]); 232 } catch (TopologicalSortException ex) { 233 throw new IllegalStateException ("Cannot happen"); } 235 236 return result; 237 } 238 239 244 private Vertex constructDualGraph(int counter, Object vertex, HashMap<Object ,Vertex> vertexInfo) { 245 Vertex info = vertexInfo.get(vertex); 246 247 if (info == null) { 248 info = new Vertex(vertex, counter++); 249 vertexInfo.put(vertex, info); 250 } else { 251 return info; 253 } 254 255 Collection c = (Collection) edges.get(vertex); 257 258 if (c != null) { 259 Iterator it = c.iterator(); 260 261 while (it.hasNext()) { 262 Vertex next = constructDualGraph(counter, it.next(), vertexInfo); 263 next.edgesFrom.add(info); 264 } 265 } 266 267 info.y = counter++; 269 270 dualGraph.push(info); 271 272 return info; 273 } 274 275 281 private void visitDualGraph(Vertex vertex, Collection<Object > visited) { 282 if (vertex.visited) { 283 return; 284 } 285 286 visited.add(vertex.object); 287 vertex.visited = true; 288 289 Iterator it = vertex.edges(); 290 291 while (it.hasNext()) { 292 Vertex v = (Vertex) it.next(); 293 visitDualGraph(v, visited); 294 } 295 } 296 297 301 private static final class Vertex implements Comparable <Vertex> { 302 303 public Object object; 304 305 306 public List<Vertex> edgesFrom = new ArrayList<Vertex>(); 307 308 309 public final int x; 310 311 312 public int y; 313 314 315 public boolean sorted; 316 317 318 public boolean visited; 319 320 public Vertex(Object obj, int x) { 321 this.x = x; 322 this.object = obj; 323 } 324 325 328 public Iterator edges() { 329 if (!sorted) { 330 Collections.sort(edgesFrom); 331 sorted = true; 332 } 333 334 return edgesFrom.iterator(); 335 } 336 337 343 public int compareTo(Vertex o) { 344 return o.y - y; 345 } 346 } 347 } 348 | Popular Tags |