1 19 20 package org.netbeans.modules.j2ee.persistence.entitygenerator; 21 22 import java.util.ArrayList ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 import java.util.Map ; 28 import org.netbeans.modules.dbschema.ColumnElement; 29 import org.netbeans.modules.dbschema.ColumnPairElement; 30 import org.netbeans.modules.dbschema.DBIdentifier; 31 import org.netbeans.modules.dbschema.ForeignKeyElement; 32 import org.netbeans.modules.dbschema.SchemaElement; 33 import org.netbeans.modules.dbschema.TableElement; 34 import org.netbeans.modules.dbschema.UniqueKeyElement; 35 36 42 public class DbSchemaEjbGenerator { 43 44 private GeneratedTables genTables; 45 private Map beans = new HashMap (); 46 private List relations = new ArrayList (); 47 private SchemaElement schemaElement; 48 49 55 public DbSchemaEjbGenerator(GeneratedTables genTables, SchemaElement schemaElement) { 56 this.schemaElement = schemaElement; 57 this.genTables = genTables; 58 59 buildCMPSet(); 60 } 61 62 67 public static boolean isJoinTable(TableElement e) { 68 ForeignKeyElement[] foreignKeys = e.getForeignKeys(); 69 if (foreignKeys == null || 70 foreignKeys.length != 2) { 71 return false; 72 } 73 74 int foreignKeySize = foreignKeys[0].getColumns().length + 75 foreignKeys[1].getColumns().length; 76 77 if (foreignKeySize < e.getColumns().length) { 78 return false; 79 } 80 81 String tableName = e.getName().getName(); 83 for (int i = 0; i < 2; i++) { 84 if (tableName.equals(foreignKeys[i].getReferencedTable().getName().getName())) { 85 return false; 86 } 87 } 88 89 if (isFkUnique(foreignKeys[0]) || isFkUnique(foreignKeys[1])) { 91 return false; 92 } 93 94 return true; 95 } 96 97 private boolean isForeignKey(ForeignKeyElement[] fks, 98 ColumnElement col) { 99 if (fks == null) { 100 return false; 101 } 102 103 for (int i = 0; i < fks.length; i++) { 104 if (fks[i].getColumn(col.getName()) != null) { 105 return true; 106 } 107 } 108 109 return false; 110 } 111 112 public EntityClass[] getBeans() { 113 return (EntityClass[])beans.values().toArray(new EntityClass[beans.size()]); 114 } 115 116 public EntityRelation[] getRelations() { 117 return (EntityRelation[])relations.toArray(new EntityRelation[relations.size()]); 118 } 119 120 121 private EntityClass getBean(String tableName) { 122 return (EntityClass)beans.get(tableName); 123 } 124 125 private EntityClass addBean(String tableName) { 126 EntityClass bean = getBean(tableName); 127 if (bean != null) { 128 return bean; 129 } 130 131 bean = new EntityClass(tableName, 132 genTables.getRootFolder(tableName), 133 genTables.getPackageName(tableName), 134 genTables.getClassName(tableName)); 135 beans.put(tableName, bean); 136 137 return bean; 138 } 139 140 private void addAllTables() { 141 List <TableElement> joinTables = new LinkedList <TableElement>(); 142 for (String tableName : genTables.getTableNames()) { 143 TableElement tableElement = 144 schemaElement.getTable(DBIdentifier.create(tableName)); 145 if (isJoinTable(tableElement)) { 146 joinTables.add(tableElement); 147 } else { 148 addBean(tableName); 149 } 150 } 151 for (TableElement joinTable : joinTables) { 152 addJoinTable(joinTable); 153 } 154 } 155 156 private String [] localColumnNames(ForeignKeyElement key) { 157 ColumnPairElement[] pkPairs = key.getColumnPairs(); 158 String [] localColumns = new String [pkPairs.length]; 159 for (int i = 0; i < pkPairs.length; i++) { 160 localColumns[i] = 161 pkPairs[i].getLocalColumn().getName().getName(); 162 } 163 return localColumns; 164 } 165 166 private String [] referencedColumnNames(ForeignKeyElement key) { 167 ColumnPairElement[] pkPairs = key.getColumnPairs(); 168 String [] refColumns = new String [pkPairs.length]; 169 for (int i = 0; i < pkPairs.length; i++) { 170 refColumns[i] = 171 pkPairs[i].getReferencedColumn().getName().getName(); 172 } 173 return refColumns; 174 } 175 179 private String getRoleName(ForeignKeyElement fk, String defaultName) { 180 ColumnPairElement[] pkPairs = fk.getColumnPairs(); 181 if (pkPairs == null || pkPairs.length > 1) { 182 return defaultName; 183 } 184 return EntityMember.makeClassName( 185 pkPairs[0].getLocalColumn().getName().getName()); 186 } 187 188 private void addJoinTable(TableElement table) { 189 ForeignKeyElement[] foreignKeys = table.getForeignKeys(); 190 191 EntityClass roleAHelper = getBean( 193 foreignKeys[0].getReferencedTable().getName().getName()); 194 EntityClass roleBHelper = getBean( 195 foreignKeys[1].getReferencedTable().getName().getName()); 196 197 String roleAname = getRoleName(foreignKeys[0], roleAHelper.getClassName()); 198 String roleBname = getRoleName(foreignKeys[1], roleBHelper.getClassName()); 199 200 String roleACmr = EntityMember.makeRelationshipFieldName(roleBname, true); 201 String roleBCmr = EntityMember.makeRelationshipFieldName(roleAname, true); 202 203 roleACmr = uniqueAlgorithm(getFieldNames(roleAHelper), roleACmr, null); 204 roleBCmr = uniqueAlgorithm(getFieldNames(roleBHelper), roleBCmr, null); 205 206 RelationshipRole roleA = new RelationshipRole( 207 roleAname, 208 roleAHelper.getClassName(), 209 roleACmr, 210 true, 211 true, 212 false); 213 roleAHelper.addRole(roleA); 214 215 RelationshipRole roleB = new RelationshipRole( 216 roleBname, 217 roleBHelper.getClassName(), 218 roleBCmr, 219 true, 220 true, 221 false); 222 roleBHelper.addRole(roleB); 223 224 EntityRelation relation = new EntityRelation(roleA, roleB); 225 relations.add(relation); 226 227 relation.setRelationName(EntityMember.makeClassName(table.getName().getName())); 228 229 roleAHelper.getCMPMapping().getJoinTableMapping().put(roleACmr, table.getName().getName()); 230 CMPMappingModel.JoinTableColumnMapping joinColMapA = new CMPMappingModel.JoinTableColumnMapping(); 231 joinColMapA.setColumns(getColumnNames(foreignKeys[0].getColumns())); 232 joinColMapA.setReferencedColumns(getColumnNames(foreignKeys[0].getReferencedColumns())); 233 joinColMapA.setInverseColumns(getColumnNames(foreignKeys[1].getColumns())); 234 joinColMapA.setReferencedInverseColumns(getColumnNames(foreignKeys[1].getReferencedColumns())); 235 roleAHelper.getCMPMapping().getJoinTableColumnMppings().put(roleACmr, joinColMapA); 236 237 roleBHelper.getCMPMapping().getJoinTableMapping().put(roleBCmr, table.getName().getName()); 238 CMPMappingModel.JoinTableColumnMapping joinColMapB = new CMPMappingModel.JoinTableColumnMapping(); 239 joinColMapB.setColumns(getColumnNames(foreignKeys[1].getColumns())); 240 joinColMapB.setReferencedColumns(getColumnNames(foreignKeys[1].getReferencedColumns())); 241 joinColMapB.setInverseColumns(getColumnNames(foreignKeys[0].getColumns())); 242 joinColMapB.setReferencedInverseColumns(getColumnNames(foreignKeys[0].getReferencedColumns())); 243 roleBHelper.getCMPMapping().getJoinTableColumnMppings().put(roleBCmr, joinColMapB); 244 245 } 246 247 private String [] getColumnNames(ColumnElement[] cols) { 248 String [] names = new String [cols.length]; 249 for (int i = 0; i < cols.length; i++) { 250 names [i] = cols[i].getName().getName(); 251 } 252 return names; 253 } 254 255 private static boolean containsSameColumns(ColumnElement[] fkColumns, 256 UniqueKeyElement uk) { 257 if (fkColumns.length == uk.getColumns().length) { 258 for (int i = 0; i < fkColumns.length; i++) { 259 if (uk.getColumn(fkColumns[i].getName())==null) { 260 return false; 261 } 262 } 263 return true; 264 } 265 return false; 266 } 267 268 private boolean containsColumns(ColumnElement[] fkColumns, 269 UniqueKeyElement uk) { 270 if (uk == null) { 271 return false; 272 } 273 274 for (int i = 0; i < fkColumns.length; i++) { 275 if (uk.getColumn(fkColumns[i].getName())!=null) { 276 return true; 277 } 278 } 279 return false; 280 } 281 282 private static boolean isFkUnique(ForeignKeyElement key) { 283 UniqueKeyElement[] uk = key.getDeclaringTable().getUniqueKeys(); 284 if (uk == null) { 285 return false; 286 } 287 288 ColumnElement[] columns = key.getColumns(); 289 for (int uin=0; uin < uk.length; uin++) { 290 if (containsSameColumns(columns, uk[uin])) { 291 return true; 292 } 293 } 294 295 return false; 296 } 297 298 private boolean isNullable(ForeignKeyElement key) { 300 ColumnElement[] columns = key.getColumns(); 301 int i, count = ((columns != null) ? columns.length : 0); 302 303 for (i=0; i < count; i++) { 304 if (!columns[i].isNullable()) { 305 return false; 306 } 307 } 308 309 return true; 310 } 311 312 private static UniqueKeyElement getPrimaryOrCandidateKey(TableElement table) { 313 UniqueKeyElement pk = table.getPrimaryKey(); 314 if (pk != null) { 315 return pk; 316 } 317 318 UniqueKeyElement[] keys = table.getUniqueKeys(); 319 if (keys == null || keys.length == 0) { 320 return null; 321 } 322 323 pk = keys[0]; 324 for (int i = 1; i < keys.length; i++) { 325 if (keys[i].getColumns().length < pk.getColumns().length) { 326 pk = keys[i]; 327 } 328 } 329 return pk; 330 } 331 332 private void generatePkField(ColumnElement column, boolean inPk, boolean pkField) { 333 EntityMember m = EntityMember.create(column); 334 m.setPrimaryKey(inPk, pkField); 335 EntityClass bean = getBean(column.getDeclaringTable().getName().getName()); 336 m.setMemberName(uniqueAlgorithm(getFieldNames(bean), m.getMemberName(), null)); 337 bean.getFields().add(m); 338 } 339 340 private void generateRelationship(ForeignKeyElement key) { 341 String keyTableName = key.getDeclaringTable().getName().getName(); 342 String keyRefName = key.getReferencedTable().getName().getName(); 343 boolean oneToOne = isFkUnique(key); 344 345 EntityClass roleBHelper = getBean(keyRefName); 346 if (roleBHelper == null) { 347 return; 348 } 349 EntityClass roleAHelper = getBean(keyTableName); 350 if (roleAHelper == null) { 351 return; 352 } 353 354 String roleBCmr = EntityMember.makeRelationshipFieldName( 356 roleAHelper.getClassName(), !oneToOne); 357 roleBCmr = uniqueAlgorithm(getFieldNames(roleBHelper), roleBCmr, null); 358 RelationshipRole roleB = new RelationshipRole( 359 getRoleName(key, roleBHelper.getClassName()), 361 roleBHelper.getClassName(), 362 roleBCmr, 363 false, 364 !oneToOne, 365 !isNullable(key)); 366 roleBHelper.addRole(roleB); 367 368 String roleACmr = EntityMember.makeRelationshipFieldName( 370 roleBHelper.getClassName(), false); 371 372 378 if (!containsColumns(key.getColumns(), getPrimaryOrCandidateKey(key.getDeclaringTable()))) { 379 roleACmr = EntityMember.makeRelationshipFieldName(roleB.getRoleName(), false); 380 } 381 382 roleACmr = uniqueAlgorithm(getFieldNames(roleAHelper), roleACmr, null); 383 384 RelationshipRole roleA = new RelationshipRole( 385 getRoleName(key, roleAHelper.getClassName()), 387 roleAHelper.getClassName(), 388 roleACmr, 389 !oneToOne, 390 false, 391 false); 392 roleAHelper.addRole(roleA); 393 394 EntityRelation relation = new EntityRelation(roleA, roleB); 395 relation.setRelationName(roleA.getEntityName() + '-' + roleB.getEntityName()); relations.add(relation); 397 398 roleAHelper.getCMPMapping().getCmrFieldMapping().put(roleACmr, localColumnNames(key)); 399 roleBHelper.getCMPMapping().getCmrFieldMapping().put(roleBCmr, referencedColumnNames(key)); 400 } 401 402 private void reset() { 403 beans.clear(); 404 relations.clear(); 405 } 406 407 private void buildCMPSet() { 408 reset(); 409 addAllTables(); 410 for (Iterator it = beans.keySet().iterator(); it.hasNext();) { 411 String tableName = it.next().toString(); 412 TableElement table = schemaElement.getTable(DBIdentifier.create(tableName)); 413 ColumnElement[] cols = table.getColumns(); 414 UniqueKeyElement pk = getPrimaryOrCandidateKey(table); 415 ForeignKeyElement[] fkeys = table.getForeignKeys(); 416 for (int col = 0; col < cols.length; col++) { 417 if (pk != null && 418 pk.getColumn(cols[col].getName()) != null) { 419 generatePkField(cols[col],true, pk.getColumns().length==1); 420 } else { 421 if (!isForeignKey(fkeys, cols[col])){ 423 generatePkField(cols[col], false, false); 424 } 425 } 426 } 427 428 for (int fk = 0 ; fkeys != null && fkeys.length > fk; fk++) { 429 generateRelationship(fkeys[fk]); 430 } 431 EntityClass helperData = getBean(tableName); 432 helperData.usePkField(pk!= null && pk.getColumns().length == 1); 433 } 434 makeRelationsUnique(); 435 } 436 437 private List getFieldNames(EntityClass bean) { 438 List result = new ArrayList (); 439 for (Iterator i = bean.getFields().iterator(); i.hasNext();) { 440 EntityMember member = (EntityMember)i.next(); 441 result.add(member.getMemberName()); 442 } 443 for (Iterator i = bean.getRoles().iterator(); i.hasNext();) { 444 RelationshipRole role = (RelationshipRole)i.next(); 445 result.add(role.getFieldName()); 446 } 447 return result; 448 } 449 450 453 private EntityRelation[] makeRelationsUnique() { 454 EntityRelation[] r = getRelations(); 455 List relationNames = new ArrayList (r.length); 456 for (int i = 0; i < r.length; i++) { 457 r[i].makeRoleNamesUnique(); 458 String baseName = r[i].getRelationName(); 459 r[i].setRelationName(uniqueAlgorithm(relationNames, baseName, "-")); } 461 return r; 462 } 463 464 467 private static String uniqueAlgorithm(List names, String baseName, String sep) { 468 String newName = baseName; 469 int unique = 0; 470 while (names.contains(newName)) { 471 String ins = (sep == null? "":sep); newName = baseName + ins + String.valueOf(++unique); 473 } 474 names.add(newName); 475 return newName; 476 } 477 } 478 | Popular Tags |