1 2 12 package com.versant.core.metadata; 13 14 import com.versant.core.common.SortableBase; 15 import com.versant.core.util.IntArray; 16 17 import javax.jdo.JDOFatalUserException; 18 19 36 public final class ClassReferenceGraph extends SortableBase { 37 38 44 public static void sort(ClassMetaData[] classes) { 45 new ClassReferenceGraph(classes).sort(); 46 } 47 48 private final ClassMetaData[] classes; private final int[] depth; 50 private final int[] edgeStart; 51 private final int[] edgeCount; 52 53 56 private ClassReferenceGraph(ClassMetaData[] a) { 57 int n = a.length; 58 classes = new ClassMetaData[n]; 59 for (int i = 0; i < n; i++) { 60 ClassMetaData cmd = a[i]; 61 if (cmd.pcSuperMetaData == null) classes[size++] = cmd; 62 } 63 depth = new int[size]; 64 edgeStart = new int[size]; 65 edgeCount = new int[size]; 66 } 67 68 72 protected int compare(int a, int b) { 73 int diff = depth[b] - depth[a]; 74 if (diff != 0) return diff; 75 return classes[a].index - classes[b].index; 76 } 77 78 81 protected void swap(int i1, int i2) { 82 int t = depth[i1]; 83 depth[i1] = depth[i2]; 84 depth[i2] = t; 85 ClassMetaData cmd = classes[i1]; 86 classes[i1] = classes[i2]; 87 classes[i2] = cmd; 88 } 89 90 96 public void sort() { 97 for (int i = size - 1; i >= 0; i--) { 98 classes[i].setReferenceGraphCycle(false); 99 } 100 int[] visited = new int[size]; 101 int[] edges = findEdges(); 102 for (int i = 0; i < size; i++) { 104 topsort(i, edges, visited, 0); 105 } 106 super.sort(); 107 for (int i = size - 1; i >= 0; i--) { 108 classes[i].setReferenceGraphIndex(i); 109 } 110 } 112 113 private void dumpGraph() { 114 for (int i = 0; i < size; i++) { 115 ClassMetaData cmd = classes[i]; 116 System.out.println("[" + i + "] = " + cmd.qname + 117 " depth " + depth[i] + 118 " cycle " + cmd.referenceGraphCycle); 119 } 120 System.out.println("---"); 121 } 122 123 private void dumpEdges(int[] edges) { 124 for (int i = 0; i < size; i++) { 125 StringBuffer s = new StringBuffer (); 126 s.append("[" + i + "] = " + classes[i].qname + " edges"); 127 for (int j = 0; j < edgeCount[i]; j++) { 128 s.append(' '); 129 s.append(edges[edgeStart[i] + j]); 130 } 131 System.out.println(s); 132 } 133 System.out.println("---"); 134 } 135 136 139 private int topsort(int index, int[] edges, int[] visited, 140 int pathlen) throws JDOFatalUserException { 141 if (visited[index] > 0) { 142 int v = visited[index]; 144 for (int i = size - 1; i >= 0; i--) { 145 if (visited[i] >= v) classes[i].setReferenceGraphCycle(true); 146 } 147 return 0; 148 } 149 int ec = edgeCount[index]; 150 if (ec == 0) return 0; visited[index] = ++pathlen; int d = 0; 153 int t = 0; 154 while (ec > 0) { 155 t = topsort(edges[edgeStart[index] + (--ec)], 156 edges, visited, pathlen); 157 d = t > d ? t : d; 158 } 159 d = d + 1; if (depth[index] < d) depth[index] = d; 161 visited[index] = 0; return d; 163 } 164 165 168 private int[] findEdges() { 169 IntArray edges = new IntArray(size); 170 for (int i = 0; i < size; i++) { 171 int start = edgeStart[i] = edges.size(); 172 findEdges(classes[i], edges); 173 edgeCount[i] = edges.size() - start; 174 } 175 return edges.toArray(); 176 } 177 178 182 private void findEdges(ClassMetaData cmd, IntArray edges) { 183 FieldMetaData[] a = cmd.fields; 184 for (int j = a.length - 1; j >= 0; j--) { 185 FieldMetaData f = a[j]; 186 if (!f.isDirectRef()) continue; 187 edges.add(indexOf(f.typeMetaData)); 188 } 189 if (cmd.pcSubclasses != null) { 190 for (int i = cmd.pcSubclasses.length - 1; i >= 0; i--) { 191 findEdges(cmd.pcSubclasses[i], edges); 192 } 193 } 194 } 195 196 private int indexOf(ClassMetaData cmd) { 197 for (; cmd.pcSuperMetaData != null; ) cmd = cmd.pcSuperMetaData; 198 for (int i = size - 1; i >= 0; i--) { 199 if (classes[i] == cmd) return i; 200 } 201 return -1; 202 } 203 204 } 205 | Popular Tags |