package pt.ist.fenixframework.pstm.repository; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.commons.lang.StringUtils; import org.apache.ojb.broker.metadata.ClassDescriptor; import org.apache.ojb.broker.metadata.CollectionDescriptor; import org.apache.ojb.broker.metadata.FieldDescriptor; import pt.ist.fenixframework.pstm.repository.SQLTableInfo.Column; import dml.Role; public class SQLTableChangeSet { private static final String DEFAULT_CHARSET = "utf8"; private final SQLTableInfo table; private final Map<String, Column> fields = new HashMap<String, Column>(); private final Set<Set<String>> indexes = new HashSet<Set<String>>(); private int concreteClasses = 0; public SQLTableChangeSet(SQLTableInfo table) { this.table = table; } public void addClassDescriptor(ClassDescriptor clazz) { for (FieldDescriptor field : clazz.getFieldDescriptions()) { fields.put(field.getColumnName(), new Column(field.getColumnName(), field.getColumnType())); } concreteClasses++; } public void addCollectionDescriptor(CollectionDescriptor collectionDescriptor) { String thisClass = collectionDescriptor.getFksToThisClass()[0]; String itemClass = collectionDescriptor.getFksToItemClass()[0]; fields.put(thisClass, new Column(thisClass, null)); fields.put(itemClass, new Column(itemClass, null)); indexes.add(Collections.singleton(thisClass)); indexes.add(Collections.singleton(itemClass)); } public void addIndex(Role role) { if (role.getMultiplicityUpper() == 1 && role.getName() != null) { indexes.add(Collections.singleton(DbUtil.getFkName(role.getName()))); } } public String generateSqlUpdates(boolean genDrops, String tableCharset) { if (concreteClasses > 1) { fields.put("OJB_CONCRETE_CLASS", new Column("OJB_CONCRETE_CLASS", null)); } StringBuilder updates = new StringBuilder(); updates.append(table.exists ? "alter" : "create"); updates.append(" table " + escapeName(table.tablename)); updates.append(table.exists ? " " : " ("); List<String> definitions = new ArrayList<String>(); if (genDrops) { for (Entry<String, Set<String>> key : table.indexes.entrySet()) { if (!fields.keySet().containsAll(key.getValue())) { definitions.add("drop key " + key.getKey()); } } for (Column column : table.columns) { if (!fields.containsKey(column.getName())) { definitions.add("drop " + column.getName()); } } } for (String field : fields.keySet()) { if (!table.containsColumn(field)) { definitions.add((table.exists ? "add " : "") + fields.get(field).toSqlColumnDefinition()); } } if (table.primaryKey.isEmpty()) { if (fields.containsKey("ID_INTERNAL")) { definitions.add((table.exists ? "add " : "") + "primary key (ID_INTERNAL)"); } else { definitions.add((table.exists ? "add " : "") + "primary key (" + StringUtils.join(fields.keySet(), ", ") + ")"); } } if (fields.containsKey("OID") && !indexes.contains(Collections.singleton("OID"))) { indexes.add(Collections.singleton("OID")); } for (Set<String> index : indexes) { if (!table.containsIndex(index)) { definitions.add((table.exists ? "add " : "") + "index (" + StringUtils.join(index.toArray(), ", ") + ")"); } } if (!definitions.isEmpty()) { updates.append(StringUtils.join(definitions, ", ")); if (!table.exists) { updates.append(") ENGINE=InnoDB, character set "); updates.append(tableCharset != null ? tableCharset : DEFAULT_CHARSET); } updates.append(";\n"); return updates.toString(); } else { return ""; } } private static String escapeName(String name) { if (name == null || name.length() == 0) return name; if (name.charAt(0) == '`') return name; // already escaped return "`" + name + "`"; } }