package pt.ist.fenixframework.pstm.repository.database;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
public class SqlTable {
private static final Map<String, String> mySqlTypeTranslation = new HashMap<String, String>();
static {
mySqlTypeTranslation.put("BIT", "tinyint(1)");
mySqlTypeTranslation.put("CHAR", "char");
mySqlTypeTranslation.put("DATE", "date");
mySqlTypeTranslation.put("DOUBLE", "double");
mySqlTypeTranslation.put("FLOAT", "float(10,2)");
mySqlTypeTranslation.put("INTEGER", "int(11)");
mySqlTypeTranslation.put("LONGVARCHAR", "longtext");
mySqlTypeTranslation.put("TIME", "time");
mySqlTypeTranslation.put("TIMESTAMP", "timestamp NULL default NULL");
mySqlTypeTranslation.put("VARCHAR", "text");
mySqlTypeTranslation.put("BLOB", "longblob");
mySqlTypeTranslation.put("BIGINT", "bigint(20)");
mySqlTypeTranslation.put(null, "tinyint(1)");
}
public class Column {
final String name;
final String type;
private Column(final String name, final String type) {
this.name = name;
this.type = type;
}
public void appendCreateTableMySql(final StringBuilder stringBuilder) {
stringBuilder.append("`");
stringBuilder.append(name);
stringBuilder.append("` ");
String typeTranslated=mySqlTypeTranslation.get(type);
if(typeTranslated==null)
{
System.out.println("No mapping defined for generic type "+type+" for the current database! Assuming that the db type will be the same as the generic type... Please review the resulting sql file for the table "+SqlTable.this.tablename+" and for field "+name);
typeTranslated=type;
}
stringBuilder.append(typeTranslated);
if (name.equals("ID_INTERNAL")) {
stringBuilder.append(" NOT NULL auto_increment");
//stringBuilder.append(", OID bigint unsigned default null");
}
}
public boolean equals(Object obj) {
if (obj != null && obj instanceof Column) {
final Column column = (Column) obj;
return name.equals(column.name);
}
return false;
}
public int hashCode() {
return name.hashCode();
}
}
final String tablename;
final Set<Column> columns = new TreeSet<Column>(new Comparator() {
public int compare(Object o1, Object o2) {
final Column column1 = (Column) o1;
final Column column2 = (Column) o2;
return column1.name.compareTo(column2.name);
}
});
final Set<String> indexes = new TreeSet<String>();
String[] primaryKey = null;
/*
* The default character set for each table, unless otherwise
* specified, is "utf8".
*
* Actually, according to the description made in the comments at
* the end of the appendCreateTableMySql method, the only correct
* way of dealing with encodings in the present combination of
* technologies used is by using always UTF-8. So, this should be
* left unchanged.
*
* Yet, because of legacy reasons, the Fenix database has all its
* tables in latin1, so we must provide some way of dealing with
* that legacy. Changing this value is one such way...
*/
String defaultCharacterSet = "utf8";
public SqlTable(final String tablename) {
this.tablename = tablename;
}
public void addColumn(final String name, final String type) {
columns.add(new Column(name, type));
}
public void index(final String columnName) {
indexes.add(columnName);
}
public void primaryKey(final String[] primaryKey) {
this.primaryKey = primaryKey;
}
public void setDefaultCharacterSet(String defaultCharacterSet) {
this.defaultCharacterSet = defaultCharacterSet;
}
public void appendCreateTableMySql(final StringBuilder stringBuilder) {
stringBuilder.append("create table `");
stringBuilder.append(tablename);
stringBuilder.append("` (\n");
for (final Iterator iterator = columns.iterator(); iterator.hasNext();) {
final Column column = (Column) iterator.next();
stringBuilder.append(" ");
column.appendCreateTableMySql(stringBuilder);
if (iterator.hasNext()) {
stringBuilder.append(",");
stringBuilder.append("\n");
}
}
if (primaryKey != null) {
stringBuilder.append(",\n primary key (");
for (int i = 0; i < primaryKey.length; i++) {
if (i > 0) {
stringBuilder.append(", ");
}
stringBuilder.append(primaryKey[i]);
}
stringBuilder.append(")");
stringBuilder.append(",\n index (OID)");
} else {
System.out.println("No primary key for table " + tablename);
}
for (final String columnName : indexes) {
stringBuilder.append(",\n index (");
stringBuilder.append(columnName);
stringBuilder.append(")");
}
stringBuilder.append("\n");
/* We must ensure that the tables and the connection are in UTF-8. This is so because:
* - strings are being stored as LONGVARCHAR, which in mysql maps to TEXT
* - OJB calls setCharacterStream (in prepared statementes)
* - connector/J sends hexadecimal strings (binary-strings) when storing a character stream
* - binary-strings are not processed for enconding, being stored as they were sent
*
* -> thus, currently the format (encoding) in which we send strings must match the column's encoding
*/
stringBuilder.append(") ENGINE=InnoDB, character set ");
stringBuilder.append(defaultCharacterSet);
stringBuilder.append(" ;\n\n");
}
}