Package siena.jdbc.ddl

Source Code of siena.jdbc.ddl.DdlGenerator

package siena.jdbc.ddl;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.sql.Types;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.IndexColumn;
import org.apache.ddlutils.model.NonUniqueIndex;
import org.apache.ddlutils.model.Table;
import org.apache.ddlutils.model.UniqueIndex;

import siena.ClassInfo;
import siena.DateTime;
import siena.Generator;
import siena.Id;
import siena.Index;
import siena.Json;
import siena.Max;
import siena.NotNull;
import siena.SienaRestrictedApiException;
import siena.SimpleDate;
import siena.Text;
import siena.Time;
import siena.Unique;
import siena.core.DecimalPrecision;
import siena.core.Polymorphic;
import siena.embed.Embedded;

public class DdlGenerator {
  public String DB = "mysql";

  private Map<String, Table> tables = new HashMap<String, Table>();
  private Database database = new Database();
 
  public DdlGenerator(){
  }
 
  public DdlGenerator(String db){
    this.DB = db;
  }
 
  public Table getTable(String name) {
    return tables.get(name);
  }
 
  public Database getDatabase() {
    return database;
  }
 
  public Table addTable(Class<?> clazz) {
    if(Modifier.isAbstract(clazz.getModifiers())){
      return null;
    }
    Table table = new Table();
    ClassInfo info = ClassInfo.getClassInfo(clazz);
    table.setName(info.tableName);
    table.setType("MyISAM");
    database.addTable(table);
   
    Map<String, UniqueIndex> uniques = new HashMap<String, UniqueIndex>();
    Map<String, NonUniqueIndex> indexes = new HashMap<String, NonUniqueIndex>();
   
    /* columns */
    for (Field field : info.allFields) {
      String[] columns = ClassInfo.getColumnNames(field);
      boolean notNull = field.getAnnotation(NotNull.class) != null;
     
      Class<?> type = field.getType();
      if(!ClassInfo.isModel(type) || (ClassInfo.isModel(type) && ClassInfo.isEmbedded(field))) {
        Column column = createColumn(clazz, field, columns[0]);
       
        if(notNull || type.isPrimitive()) {
          column.setRequired(true);
         
          if(type.isPrimitive() && !ClassInfo.isId(field)) { // TODO: add also Boolean, Long, Double,... ?
            if(type == Boolean.TYPE) {
              column.setDefaultValue("false");
            } else {
              column.setDefaultValue("0");
            }
          }
        }
       
        Id id = field.getAnnotation(Id.class);
        if(id != null) {
          column.setPrimaryKey(true);
          column.setRequired(true);
         
          // auto_increments managed ONLY for long
          if(id.value() == Generator.AUTO_INCREMENT
              && (Long.TYPE == type || Long.class.isAssignableFrom(type)))
            column.setAutoIncrement(true);
         
          // adds index on primary key
          /*UniqueIndex i = uniques.get(columns[0]);
          if(i == null) {
            i = new UniqueIndex();
            i.setName(columns[0]);
            uniques.put(columns[0], i);
            table.addIndex(i);
          }
          fillIndex(i, field);*/
        }
       
        table.addColumn(column);
      } else {
        List<Field> keys = ClassInfo.getClassInfo(type).keys;
       
        for (int i = 0; i < columns.length; i++) {
          Field f = keys.get(i);
          Column column = createColumn(clazz, f, columns[i]);

          if(notNull)
            column.setRequired(true);
         
          table.addColumn(column);
        }
      }
    }

    /* indexes */
    for (Field field : info.updateFields) {
      Index index = field.getAnnotation(Index.class);
      if(index != null) {
        String[] names = index.value();
        for (String name : names) {
          NonUniqueIndex i = indexes.get(name);
          if(i == null) {
            i = new NonUniqueIndex();
            i.setName(name);
            indexes.put(name, i);
            table.addIndex(i);
          }
          fillIndex(i, field);
        }
      }
     
      Unique unique = field.getAnnotation(Unique.class);
      if(unique != null) {
        String[] names = unique.value();
        for (String name : names) {
          UniqueIndex i = uniques.get(name);
          if(i == null) {
            i = new UniqueIndex();
            i.setName(name);
            uniques.put(name, i);
            table.addIndex(i);
          }
          fillIndex(i, field);
        }
      }
    }
   
    tables.put(table.getName(), table);
    return table;
  }
 
  private void fillIndex(org.apache.ddlutils.model.Index i, Field field) {
    String[] columns = ClassInfo.getColumnNames(field);
    for (String string : columns) {
      IndexColumn ic = new IndexColumn(string);
      i.addColumn(ic);
    }
  }
 
  private Column createColumn(Class<?> clazz, Field field, String col) {
    Class<?> type = field.getType();
    Column column = new Column();
    column.setName(col);

    int columnType;
   
    if(type == Byte.class         || type == Byte.TYPE)    columnType = Types.TINYINT;
    else if(type == Short.class   || type == Short.TYPE)   columnType = Types.SMALLINT;
    else if(type == Integer.class || type == Integer.TYPE) columnType = Types.INTEGER;
    else if(type == Long.class    || type == Long.TYPE)    columnType = Types.BIGINT;
    else if(type == Float.class   || type == Float.TYPE)   columnType = Types.FLOAT; // TODO verify
    else if(type == Double.class  || type == Double.TYPEcolumnType = Types.DOUBLE; // TODO verify
    else if(type == String.class) {
      if(field.getAnnotation(Text.class) != null) {
        columnType = Types.LONGVARCHAR;
      } else {
        columnType = Types.VARCHAR;
       
        Max max = field.getAnnotation(Max.class);
        if(max == null){
          //throw new SienaRestrictedApiException(DB, "createColumn", "Field "+field.getName()+" in class "
          //    +clazz.getName()+" doesn't have a @Max annotation");
          // default is 255 chars as in hibernate
          column.setSize("255");
        }
        else column.setSize(""+max.value());
      }
    }
    else if(type == Boolean.class || type == Boolean.TYPE) columnType = Types.BOOLEAN;
    else if(type == Date.class) {
      if(field.getAnnotation(DateTime.class) != null)
        columnType = Types.TIMESTAMP;
      else if(field.getAnnotation(Time.class) != null)
        columnType = Types.TIME;
      else if(field.getAnnotation(SimpleDate.class) != null)
        columnType = Types.DATE;
      else
        columnType = Types.TIMESTAMP;
    } else if(type == Json.class) {
      columnType = Types.LONGVARCHAR;
    } else if(type == byte[].class){
      columnType = Types.BLOB;
    } else if(Enum.class.isAssignableFrom(type)){
      // enums are stored as string
      columnType = Types.VARCHAR;
      Max max = field.getAnnotation(Max.class);
      if(max == null)
        column.setSize(""+255); // fixes by default to this value in order to prevent alter tables every time
      else column.setSize(""+max.value());
    } else if(type == BigDecimal.class){           
      DecimalPrecision an = field.getAnnotation(DecimalPrecision.class);
      if(an == null) {
        columnType = Types.DECIMAL;
        column.setSizeAndScale(19, 2);
      }
      else {
        if(an.storageType() == DecimalPrecision.StorageType.NATIVE){
          columnType = Types.DECIMAL;
          column.setSizeAndScale(an.size(), an.scale());
        }else if(an.storageType() == DecimalPrecision.StorageType.STRING) {
          columnType = Types.VARCHAR;
          // should be an.size+"."+sign
          column.setSize((an.size()+2)+"");
        }else if(an.storageType() == DecimalPrecision.StorageType.DOUBLE) {
          columnType = Types.DOUBLE;         
        }else {
          columnType = Types.DECIMAL;
          column.setSizeAndScale(19, 2);
        }
      }
    }
    else {
      Embedded embedded = field.getAnnotation(Embedded.class);
      if(embedded != null) {
        if("h2".equals(DB)){
          columnType = Types.CLOB;
        }
        else {
          columnType = Types.LONGVARCHAR;
        }
      } else if(field.isAnnotationPresent(Polymorphic.class)){
            columnType = Types.BLOB;
        }else {       
        throw new SienaRestrictedApiException(DB, "createColumn", "Unsupported type for field "
            +clazz.getName()+"."+field.getName());
      }
    }

    column.setTypeCode(columnType);
    return column;
  }

}
TOP

Related Classes of siena.jdbc.ddl.DdlGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.