|                                                                                                              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                                                                                                                                                                                              |