1 2 12 package com.versant.core.jdbc.metadata; 13 14 import com.versant.core.metadata.ClassMetaData; 15 import com.versant.core.metadata.FieldMetaData; 16 17 import com.versant.core.common.Debug; 18 import com.versant.core.common.BindingSupportImpl; 19 20 import java.util.*; 21 22 45 public final class JdbcClassReferenceGraph implements Comparator { 46 private HashMap cmdToRefMap = new HashMap(); 47 private HashMap cmdToIndirectMap = new HashMap(); 48 private HashMap cmdToNonCyclicMap = new HashMap(); 49 50 public int compare(Object o1, Object o2) { 51 ClassMetaData cmd1 = ((ClassMetaData) o1).top; 52 ClassMetaData cmd2 = ((ClassMetaData) o2).top; 53 54 if (cmd1.weight != cmd2.weight) { 55 return cmd2.weight - cmd1.weight; 56 } else { 57 return cmd2.qname.compareTo(cmd1.qname); 58 } 59 } 60 61 private final ClassMetaData[] classes; 62 63 66 public JdbcClassReferenceGraph(ClassMetaData[] a) { 67 int n = a.length; 68 classes = new ClassMetaData[n]; 69 for (int i = 0; i < n; i++) { 70 classes[i] = a[i]; 71 classes[i].weight = 0; 72 } 73 } 74 75 private void addRefs(ClassMetaData cmd, HashSet set) { 76 FieldMetaData[] fields = cmd.fields; 77 if (fields == null) { 78 return; 79 } 80 for (int i = 0; i < fields.length; i++) { 81 FieldMetaData field = fields[i]; 82 if (field.isDirectRef()) { 83 set.add(field.typeMetaData.top); 84 } 85 } 86 } 87 88 private void addRefsRecursive(ClassMetaData cmd, HashSet set) { 89 addRefs(cmd, set); 90 ClassMetaData[] pcSubs = cmd.pcSubclasses; 91 if (pcSubs == null) return; 92 for (int i = 0; i < pcSubs.length; i++) { 93 addRefsRecursive(pcSubs[i], set); 94 } 95 } 96 97 private HashSet getDirectRefs(ClassMetaData cmd, HashMap refMap) { 98 return (HashSet) refMap.get(cmd.top); 99 } 100 101 private HashSet getIndirectRefs(ClassMetaData cmd, HashMap indirectRefMap) { 102 return (HashSet) indirectRefMap.get(cmd.top); 103 } 104 105 private void buildIndirectGraph() { 106 for (int i = 0; i < classes.length; i++) { 107 ClassMetaData cmd = classes[i]; 108 if (cmd.pcSuperClass == null) { 109 HashSet indirectRefSet = new HashSet(); 110 cmdToIndirectMap.put(cmd, indirectRefSet); 111 buildIndirectGraph(cmd, cmd, indirectRefSet, cmdToRefMap); 112 } 113 } 114 } 115 116 private void buildIndirectGraph(ClassMetaData rootCmd, ClassMetaData cmd, Set indirectRefs, Map directRefMap) { 117 Set directRefs = (Set) directRefMap.get(cmd); 118 for (Iterator iterator = directRefs.iterator(); iterator.hasNext();) { 119 ClassMetaData dRef = (ClassMetaData) iterator.next(); 120 if (dRef != dRef.top) BindingSupportImpl.getInstance().internal("Should be top most class"); 121 if (dRef == rootCmd) continue; 122 if (indirectRefs.contains(dRef)) continue; 123 indirectRefs.add(dRef); 124 buildIndirectGraph(rootCmd, dRef, indirectRefs, directRefMap); 125 } 126 } 127 128 private int calculateWieght(ClassMetaData cmd) { 129 if (Debug.DEBUG) { 130 if (cmd.top != cmd) throw BindingSupportImpl.getInstance().internal( 131 "Must be top of hierarchy"); 132 } 133 if (cmd.weight != 0) { 134 return cmd.weight; 136 } 137 138 HashSet noncircularRefs = (HashSet) cmdToNonCyclicMap.get(cmd); 139 int maxWeight = 0; 140 for (Iterator iterator = noncircularRefs.iterator(); iterator.hasNext();) { 141 ClassMetaData classMetaData = (ClassMetaData) iterator.next(); 142 int refWeight = calculateWieght(classMetaData); 143 if (refWeight > maxWeight) maxWeight = refWeight; 144 } 145 return cmd.weight = maxWeight + 1; 146 } 147 148 155 public void sort() { 156 buildDirectRefGraph(); 158 159 buildIndirectGraph(); 161 162 buildNonCyclicRefGraph(); 164 165 calculateWieght(); 167 168 List classList = Arrays.asList(this.classes); 169 Collections.sort(classList, this); 170 for (int i = 0; i < classList.size(); i++) { 171 ((ClassMetaData)classList.get(i)).setReferenceGraphIndex(i); 172 } 173 } 174 175 private void calculateWieght() { 176 for (int i = 0; i < classes.length; i++) { 177 ClassMetaData cmd = classes[i]; 178 if (cmd.pcSuperClass == null) { 179 calculateWieght(cmd); 180 } 181 } 182 } 183 184 private void buildNonCyclicRefGraph() { 185 for (int i = 0; i < classes.length; i++) { 186 ClassMetaData cmd = classes[i]; 187 if (cmd.pcSuperClass == null) { 188 HashSet indirectRefSet = (HashSet) cmdToIndirectMap.get(cmd); 189 HashSet nonCircularRefs = new HashSet(); 190 cmdToNonCyclicMap.put(cmd, nonCircularRefs); 191 192 for (Iterator iterator = indirectRefSet.iterator(); iterator.hasNext();) { 193 ClassMetaData refNode = (ClassMetaData) iterator.next(); 194 if (!isCircularRef(cmd, refNode)) { 195 nonCircularRefs.add(refNode); 196 } 197 } 198 } 199 } 200 } 201 202 private void buildDirectRefGraph() { 203 for (int i = 0; i < classes.length; i++) { 204 ClassMetaData cmd = classes[i]; 205 if (cmd.pcSuperClass == null) { 206 HashSet refSet = new HashSet(); 207 cmdToRefMap.put(cmd, refSet); 208 addRefsRecursive(cmd, refSet); 209 } 210 } 211 } 212 213 public boolean isCircularRef(ClassMetaData cmd1, ClassMetaData cmd2) { 214 cmd1 = cmd1.top; 215 cmd2 = cmd2.top; 216 return (getIndirectRefs(cmd1, cmdToIndirectMap).contains(cmd2) && getIndirectRefs(cmd2, cmdToIndirectMap).contains(cmd1)); 217 } 218 219 public void releaseMem() { 220 cmdToIndirectMap = null; 221 cmdToNonCyclicMap = null; 222 cmdToRefMap = null; 223 } 224 } 225 | Popular Tags |