1 package org.apache.ojb.broker.metadata.torque; 2 3 17 18 import org.apache.ojb.broker.metadata.ClassDescriptor; 19 import org.apache.ojb.broker.metadata.CollectionDescriptor; 20 import org.apache.ojb.broker.metadata.DescriptorRepository; 21 import org.apache.ojb.broker.metadata.FieldDescriptor; 22 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor; 23 import org.apache.ojb.broker.util.logging.Logger; 24 import org.apache.ojb.broker.util.logging.LoggerFactory; 25 26 import java.util.HashMap ; 27 import java.util.Iterator ; 28 import java.util.Vector ; 29 30 public class TorqueForeignKeyGenerator { 31 private final Logger logger = LoggerFactory.getLogger(this.getClass()); 32 private DescriptorRepository repository; 33 private HashMap mappingTables = new HashMap (); 34 private HashMap foreignKeyVectors = new HashMap (); 35 36 public TorqueForeignKeyGenerator(DescriptorRepository repository) { 37 this.repository = repository; 38 } 39 40 public void buildConstraintsMap() { 41 Iterator classDescriptorIterators = this.repository.iterator(); 42 while (classDescriptorIterators.hasNext()) { 43 ClassDescriptor cd = (ClassDescriptor) classDescriptorIterators.next(); 44 if(cd.isAbstract() || cd.isInterface()) 45 { 46 logger.debug( "Skip constraint build for abstract class/ interface " + cd.getClassNameOfObject() ); 47 } 48 else 49 { 50 buildConstraints(cd); 51 buildOneToOneConstraints(cd); 52 } 53 } 54 } 55 56 public Vector getForeignKeysForTable(String tableName) { 57 return (Vector ) this.foreignKeyVectors.get(tableName); 58 } 59 60 public HashMap getMappingTables() { 61 return this.mappingTables; 62 } 63 64 private void buildTableFieldDescriptors(FieldDescriptor fieldDescriptors[], TableDescriptor tableDescriptor) { 65 for (int i = 0; i < fieldDescriptors.length; i++) { 66 tableDescriptor.addColumn(fieldDescriptors[i]); 67 } 68 } 69 70 private void buildConstraints(ClassDescriptor cd) { 71 Vector collectionDescriptors = cd.getCollectionDescriptors(); 72 for (int i = 0; i < collectionDescriptors.size(); i++) { 73 CollectionDescriptor collectionDescriptor = (CollectionDescriptor) collectionDescriptors.get(i); 74 if (collectionDescriptor.isMtoNRelation()) { 75 buildManyToManyConstraints(cd, collectionDescriptor); 76 } else { 77 buildOneToManyReferences(cd, collectionDescriptor); 78 } 79 } 80 } 81 82 private void buildManyToManyConstraints(ClassDescriptor cd, CollectionDescriptor collectionDescriptor) { 83 Vector columns = new Vector (); 84 85 ClassDescriptor itemDescriptor = this.repository.getDescriptorFor(collectionDescriptor.getItemClass()); 86 buildManyToManyReferences(cd, collectionDescriptor, collectionDescriptor.getFksToThisClass(), columns); 87 buildManyToManyReferences(itemDescriptor, collectionDescriptor, collectionDescriptor.getFksToItemClass(), columns); 88 89 if (isImplicitlyMapped(collectionDescriptor.getIndirectionTable())) { 90 TableDescriptor mappingTable = new TableDescriptor(); 91 buildTableFieldDescriptors((FieldDescriptor[]) columns.toArray(new FieldDescriptor[0]), mappingTable); 92 mappingTable.setName(collectionDescriptor.getIndirectionTable()); 93 this.mappingTables.put(mappingTable.getName(), mappingTable); 94 } 95 } 96 97 private void buildManyToManyReferences(ClassDescriptor cd, CollectionDescriptor collectionDescriptor, 98 Object keys[], Vector columns) 99 { 100 if(cd.isAbstract() || cd.isInterface()) 101 { 102 logger.debug( "Skip foreign key build for MtoM, found abstract base class or interface " + cd.getClassNameOfObject() ); 103 return; 104 } 105 StringBuffer buffer = new StringBuffer (256); 106 buildForeignKeyHeader(cd.getFullTableName(), buffer); 107 108 for (int i = 0; i < keys.length; i++) { 109 String columnName = (String ) keys[i]; 110 111 FieldDescriptor foreignColumn = cd.getPkFields()[i]; 112 String foreignColumnName = foreignColumn.getPersistentField().getName(); 113 buildReferenceForColumn(buffer, columnName, foreignColumnName); 114 FieldDescriptor fieldDescriptor = (FieldDescriptor)foreignColumn.clone(); 115 fieldDescriptor.setColumnName(columnName); 116 columns.add(fieldDescriptor); 117 } 118 buffer.append(" </foreign-key>\n"); 119 120 addReferenceToTable(collectionDescriptor.getIndirectionTable(), buffer.toString()); 121 } 122 123 private void buildOneToManyReferences(ClassDescriptor cd, CollectionDescriptor collectionDescriptor) { 124 Vector foreignKeyIndices = collectionDescriptor.getForeignKeyFields(); 125 ClassDescriptor foreignKeyClassDescriptor = this.repository.getDescriptorFor(collectionDescriptor.getItemClass()); 126 buildForeignKey(cd, foreignKeyIndices, foreignKeyClassDescriptor); 127 } 128 129 130 private void buildOneToOneConstraints(ClassDescriptor classDescriptor) { 131 Vector referenceDescriptors = classDescriptor.getObjectReferenceDescriptors(); 132 for (int i = 0; i < referenceDescriptors.size(); i++) { 133 ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) referenceDescriptors.get(i); 134 135 Vector foreignKeyIndices = ord.getForeignKeyFields(); 136 ClassDescriptor foreignClassDescriptor = this.repository.getDescriptorFor(ord.getItemClass()); 137 buildForeignKey(foreignClassDescriptor, foreignKeyIndices, classDescriptor); 138 } 139 } 140 141 private void buildForeignKey(ClassDescriptor foreignClassDescriptor, Vector foreignKeyIndices, ClassDescriptor classDescriptor) { 142 143 if(classDescriptor.isAbstract() || classDescriptor.isInterface()) 144 { 145 logger.debug( "Skip foreign key build, found abstract base class or interface " + classDescriptor.getClassNameOfObject() ); 146 return; 147 } 148 StringBuffer buffer = new StringBuffer (256); 149 buildForeignKeyHeader(foreignClassDescriptor.getFullTableName(), buffer); 150 151 for (int i = 0; i < foreignKeyIndices.size(); i++) { 152 String columnName = null; 153 Object obj = foreignKeyIndices.get(i); 154 155 if (obj instanceof Integer ) 156 { 157 int foreignKeyIndex = ((Integer ) obj).intValue(); 158 columnName = classDescriptor.getFieldDescriptorByIndex(foreignKeyIndex).getColumnName(); 159 } 160 else 161 { 162 FieldDescriptor fld = classDescriptor.getFieldDescriptorByName((String ) obj); 163 if(fld == null) 164 { 165 logger.debug( "FieldDescriptor for foreign key parameter \n" + obj + " was not found in ClassDescriptor \n" + classDescriptor ); 166 } 167 else columnName = fld.getColumnName(); 168 } 169 170 FieldDescriptor foreignColumn = foreignClassDescriptor.getPkFields()[i]; 171 String foreignColumnName = foreignColumn.getColumnName(); 172 buildReferenceForColumn(buffer, columnName, foreignColumnName); 173 } 174 buffer.append(" </foreign-key>\n"); 175 addReferenceToTable(classDescriptor.getFullTableName(), buffer.toString()); 176 } 177 178 private void buildForeignKeyHeader(String foreignClassName, StringBuffer buffer) { 179 buffer.append(" <foreign-key foreignTable=\""); 180 buffer.append(foreignClassName); 181 buffer.append("\">\n"); 182 } 183 184 private void buildReferenceForColumn(StringBuffer buffer, String columnName, String foreignColumnName) { 185 buffer.append(" <reference local=\""); 186 buffer.append(columnName); 187 buffer.append("\" foreign=\""); 188 buffer.append(foreignColumnName); 189 buffer.append("\"/>\n"); 190 } 191 192 193 private boolean isImplicitlyMapped(String tableName) { 194 Iterator classDescriptorIterator = repository.iterator(); 195 196 while (classDescriptorIterator.hasNext()) { 197 ClassDescriptor cd = (ClassDescriptor) classDescriptorIterator.next(); 198 if (tableName.equals(cd.getFullTableName())) { 199 return false; 200 } 201 } 202 203 return true; 204 } 205 206 private void addReferenceToTable(String tableName, String reference) { 207 Vector tableReferences = (Vector ) this.foreignKeyVectors.get(tableName); 208 if (tableReferences == null) { 209 tableReferences = new Vector (); 210 this.foreignKeyVectors.put(tableName, tableReferences); 211 212 } 213 if (!tableReferences.contains(reference)) { 214 tableReferences.add(reference); 215 } 216 } 217 } 218 | Popular Tags |