package pt.ist.fenixframework.pstm.repository.database;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.CollectionDescriptor;
import org.apache.ojb.broker.metadata.DescriptorRepository;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.metadata.MetadataManager;
import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
public class DatabaseDescriptorFactory {
private DatabaseDescriptorFactory() {
}
public static Map<String, SqlTable> getSqlTables() {
final Map<String, SqlTable> sqlTables = newSqlTableMap();
final Map<String, ClassDescriptor> classDescriptorMap = getDescriptorTable();
for (final ClassDescriptor classDescriptor : classDescriptorMap.values()) {
addSqlTableDescription(sqlTables, classDescriptor);
}
return sqlTables;
}
private static final Map<String, SqlTable> newSqlTableMap() {
return new TreeMap<String, SqlTable>(new Comparator() {
public int compare(Object o1, Object o2) {
final String tablename1 = (String) o1;
final String tablename2 = (String) o2;
return tablename1.compareTo(tablename2);
}
});
}
public static Map<String, ClassDescriptor> getDescriptorTable() {
final MetadataManager metadataManager = MetadataManager.getInstance();
final DescriptorRepository descriptorRepository = metadataManager.getGlobalRepository();
return descriptorRepository.getDescriptorTable();
}
private static void addSqlTableDescription(final Map<String, SqlTable> sqlTables,
final ClassDescriptor classDescriptor) {
final String tablename = classDescriptor.getFullTableName();
final String classname = classDescriptor.getClassNameOfObject();
if (!classname.startsWith("pt.utl.ist.berserk")
&& tablename != null
&& !tablename.startsWith("OJB")
/*
&& !tablename.equals("ROLE")
&& !tablename.equals("ROOT_DOMAIN_OBJECT")*/) {
final SqlTable sqlTable = obtainSQLTable(sqlTables, tablename);
addColumns(sqlTable, classDescriptor.getFieldDescriptions());
setPrimaryKey(sqlTable, classDescriptor.getPkFields());
processCollectionDescriptors(sqlTables, classDescriptor);
}
}
private static SqlTable obtainSQLTable(final Map<String, SqlTable> sqlTables, final String tablename) {
final SqlTable sqlTable;
if (sqlTables.containsKey(tablename)) {
sqlTable = sqlTables.get(tablename);
} else {
sqlTable = new SqlTable(tablename);
sqlTables.put(tablename, sqlTable);
}
return sqlTable;
}
private static void addColumns(final SqlTable sqlTable, final FieldDescriptor[] fieldDescriptions) {
if (fieldDescriptions != null) {
for (final FieldDescriptor fieldDescriptor : fieldDescriptions) {
sqlTable.addColumn(fieldDescriptor.getColumnName(), fieldDescriptor.getColumnType());
}
}
}
private static void setPrimaryKey(final SqlTable sqlTable, final FieldDescriptor[] pkFields) {
final String[] primaryKey = new String[pkFields.length];
for (int i = 0; i < pkFields.length; i++) {
primaryKey[i] = pkFields[i].getColumnName();
}
sqlTable.primaryKey(primaryKey);
}
private static void processCollectionDescriptors(Map<String, SqlTable> sqlTables, ClassDescriptor classDescriptor) {
for (CollectionDescriptor cod : (Iterable<CollectionDescriptor>)classDescriptor.getCollectionDescriptors()) {
if (cod.getIndirectionTable() != null) {
// many-to-many relation
addSqlIndirectionTableDescription(sqlTables, cod);
} else {
// one-to-many means that we should index the foreign key in the other table
ClassDescriptor otherClass = classDescriptor.getRepository().getDescriptorFor(cod.getItemClass());
FieldDescriptor[] foreignKeys = cod.getForeignKeyFieldDescriptors(otherClass);
SqlTable otherSqlTable = obtainSQLTable(sqlTables, otherClass.getFullTableName());
// add index
otherSqlTable.index(foreignKeys[0].getColumnName());
}
}
}
private static void addSqlIndirectionTableDescription(final Map<String, SqlTable> sqlTables,
final CollectionDescriptor collectionDescriptor) {
final String indirectionTablename = collectionDescriptor.getIndirectionTable();
final SqlTable indirectionSqlTable = obtainSQLTable(sqlTables, indirectionTablename);
final String foreignKeyToThis = collectionDescriptor.getFksToThisClass()[0];
final String foreignKeyToOther = collectionDescriptor.getFksToItemClass()[0];
indirectionSqlTable.addColumn(foreignKeyToThis, "BIGINT");
indirectionSqlTable.addColumn(foreignKeyToOther, "BIGINT");
indirectionSqlTable.primaryKey(new String[] { foreignKeyToThis, foreignKeyToOther });
}
}