/* The contents of this file are subject to the license and copyright terms * detailed in the license directory at the root of the source tree (also * available online at http://fedora-commons.org/license/). */ package fedora.server.utilities; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * A DDLConverter that works with Derby. * * <pre> * The type-mapping from default-db-spec to Derby internal types is as follows: * * db-spec Derby-type * ------- ---------- * int(11) INT [4-bytes] * varchar(x) VARCHAR(x) * varchar(x)-binary VARCHAR(x) FOR BIT DATA // binary setting ignored * smallint(6) SMALLINT [2-bytes] * bigint BIGINT [8-bytes] * text CLOB [default: 2GB] * </pre> * * @author Andrew Woods */ public class DerbyDDLConverter implements DDLConverter { public DerbyDDLConverter() { } public List<String> getDDL(TableSpec spec) { ArrayList<String> l = new ArrayList<String>(); StringBuilder out = new StringBuilder(); out.append("CREATE TABLE " + spec.getName() + " (\n"); Iterator<ColumnSpec> csi = spec.columnSpecIterator(); int csNum = 0; while (csi.hasNext()) { if (csNum > 0) { out = removeTrailingWhitespace(out); out.append(",\n"); } csNum++; ColumnSpec cs = csi.next(); out.append(getColumnName(cs)); out.append(getDataType(cs)); out.append(getColumnConstraint(cs)); out.append(getDefaultValue(cs)); if (cs.getIndexName() != null) { l.add(createIndexStatement(spec, cs)); } } out = removeTrailingWhitespace(out); if (spec.getPrimaryColumnName() != null) { out.append(",\n"); out.append(getTableConstraint(spec)); } out.append(')'); l.add(0, out.toString()); return l; } private StringBuilder removeTrailingWhitespace(StringBuilder out) { while (out.charAt(out.length() - 1) == ' ') { out.deleteCharAt(out.length() - 1); } return out; } private StringBuilder getColumnName(ColumnSpec cs) { StringBuilder out = new StringBuilder(); out.append(" "); out.append(cs.getName()); out.append(' '); return out; } private Object getDataType(ColumnSpec cs) { StringBuilder out = new StringBuilder(); if (isNumberType(cs)) { out.append(getTypeWithoutByteLength(cs)); } else { if (cs.getType().equalsIgnoreCase("text")) { out.append("CLOB"); } else { out.append(cs.getType()); } } out.append(' '); return out; } private boolean isNumberType(ColumnSpec cs) { return cs.getType().toLowerCase().indexOf("int") != -1; } private String getTypeWithoutByteLength(ColumnSpec cs) { int end = cs.getType().indexOf('('); if (end == -1) end = cs.getType().length(); return cs.getType().substring(0, end); } private Object getColumnConstraint(ColumnSpec cs) { StringBuilder out = new StringBuilder(); if (cs.isUnique()) { out.append("UNIQUE "); } if (cs.isNotNull()) { out.append("NOT NULL "); } // only NUMBER types can auto-increment. if (cs.isAutoIncremented() && isNumberType(cs)) { out.append("GENERATED ALWAYS AS IDENTITY "); } return out; } private StringBuilder getDefaultValue(ColumnSpec cs) { StringBuilder out = new StringBuilder(); if (cs.getDefaultValue() != null) { out.append("DEFAULT "); if (!isNumberType(cs)) { out.append("'"); } out.append(cs.getDefaultValue()); if (!isNumberType(cs)) { out.append("'"); } out.append(' '); } return out; } private StringBuilder getTableConstraint(TableSpec ts) { StringBuilder out = new StringBuilder(); if (ts.getPrimaryColumnName() != null) { out.append(" PRIMARY KEY ("); out.append(ts.getPrimaryColumnName()); out.append(")"); } return out; } private String createIndexStatement(TableSpec ts, ColumnSpec cs) { StringBuilder out = new StringBuilder(); if (cs.getIndexName() != null) { out.append("CREATE INDEX " + ts.getName() + "_" + cs.getName() + " ON " + ts.getName() + " (" + cs.getName() + ")"); } return out.toString(); } }