Package com.j256.ormlite.table

Source Code of com.j256.ormlite.table.DatabaseTableConfig

package com.j256.ormlite.table;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.j256.ormlite.db.DatabaseType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.field.DatabaseFieldConfig;
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.misc.JavaxPersistence;
import com.j256.ormlite.support.ConnectionSource;

/**
* Database table configuration information either supplied by Spring or direct Java wiring or from a
* {@link DatabaseTable} annotation.
*
* @author graywatson
*/
public class DatabaseTableConfig<T> {

  private Class<T> dataClass;
  private String tableName;
  private List<DatabaseFieldConfig> fieldConfigs;
  private FieldType[] fieldTypes;
  private Constructor<T> constructor;

  public DatabaseTableConfig() {
    // for spring
  }

  /**
   * Setup a table config associated with the dataClass and field configurations. The table-name will be extracted
   * from the dataClass.
   */
  public DatabaseTableConfig(Class<T> dataClass, List<DatabaseFieldConfig> fieldConfigs) {
    this(dataClass, extractTableName(dataClass), fieldConfigs);
  }

  /**
   * Setup a table config associated with the dataClass, table-name, and field configurations.
   */
  public DatabaseTableConfig(Class<T> dataClass, String tableName, List<DatabaseFieldConfig> fieldConfigs) {
    this.dataClass = dataClass;
    this.tableName = tableName;
    this.fieldConfigs = fieldConfigs;
  }

  private DatabaseTableConfig(Class<T> dataClass, String tableName, FieldType[] fieldTypes) {
    this.dataClass = dataClass;
    this.tableName = tableName;
    this.fieldTypes = fieldTypes;
  }

  /**
   * Initialize the class if this is being called with Spring.
   */
  public void initialize() {
    if (dataClass == null) {
      throw new IllegalStateException("dataClass was never set on " + getClass().getSimpleName());
    }
    if (tableName == null) {
      tableName = extractTableName(dataClass);
    }
  }

  public Class<T> getDataClass() {
    return dataClass;
  }

  // @Required
  public void setDataClass(Class<T> dataClass) {
    this.dataClass = dataClass;
  }

  public String getTableName() {
    return tableName;
  }

  /**
   * Set the table name. If not specified then the name is gotten from the class name.
   */
  public void setTableName(String tableName) {
    this.tableName = tableName;
  }

  public void setFieldConfigs(List<DatabaseFieldConfig> fieldConfigs) {
    this.fieldConfigs = fieldConfigs;
  }

  /**
   * Extract the field types from the fieldConfigs if they have not already been configured.
   */
  public void extractFieldTypes(ConnectionSource connectionSource) throws SQLException {
    if (fieldTypes == null) {
      if (fieldConfigs == null) {
        fieldTypes = extractFieldTypes(connectionSource, dataClass, tableName);
      } else {
        fieldTypes = convertFieldConfigs(connectionSource, tableName, fieldConfigs);
      }
    }
  }

  /**
   * Return the field types associated with this configuration.
   */
  public FieldType[] getFieldTypes(DatabaseType databaseType) throws SQLException {
    if (fieldTypes == null) {
      throw new SQLException("Field types have not been extracted in table config");
    }
    return fieldTypes;
  }

  public List<DatabaseFieldConfig> getFieldConfigs() {
    return fieldConfigs;
  }

  /**
   * Return the constructor for this class. If not constructor has been set on the class then it will be found on the
   * class through reflection.
   */
  public Constructor<T> getConstructor() {
    if (constructor == null) {
      constructor = findNoArgConstructor(dataClass);
    }
    return constructor;
  }

  // @NotRequired
  public void setConstructor(Constructor<T> constructor) {
    this.constructor = constructor;
  }

  /**
   * Extract the DatabaseTableConfig for a particular class by looking for class and field annotations. This is used
   * by internal classes to configure a class.
   */
  public static <T> DatabaseTableConfig<T> fromClass(ConnectionSource connectionSource, Class<T> clazz)
      throws SQLException {
    String tableName = extractTableName(clazz);
    if (connectionSource.getDatabaseType().isEntityNamesMustBeUpCase()) {
      tableName = tableName.toUpperCase();
    }
    return new DatabaseTableConfig<T>(clazz, tableName, extractFieldTypes(connectionSource, clazz, tableName));
  }

  /**
   * Extract and return the table name for a class.
   */
  public static <T> String extractTableName(Class<T> clazz) {
    DatabaseTable databaseTable = clazz.getAnnotation(DatabaseTable.class);
    String name = null;
    if (databaseTable != null && databaseTable.tableName() != null && databaseTable.tableName().length() > 0) {
      name = databaseTable.tableName();
    } else {
      /*
       * NOTE: to remove javax.persistence usage, comment the following line out
       */
      name = JavaxPersistence.getEntityName(clazz);
      if (name == null) {
        // if the name isn't specified, it is the class name lowercased
        name = clazz.getSimpleName().toLowerCase();
      }
    }
    return name;
  }

  /**
   * Find and return the field-type of the id field in this class.
   */
  public static <T> FieldType extractIdFieldType(ConnectionSource connectionSource, Class<T> clazz, String tableName)
      throws SQLException {
    for (Class<?> classWalk = clazz; classWalk != null; classWalk = classWalk.getSuperclass()) {
      for (Field field : classWalk.getDeclaredFields()) {
        FieldType fieldType = FieldType.createFieldType(connectionSource, tableName, field, clazz);
        if (fieldType != null
            && (fieldType.isId() || fieldType.isGeneratedId() || fieldType.isGeneratedIdSequence())) {
          return fieldType;
        }
      }
    }
    return null;
  }

  /**
   * Locate the no arg constructor for the class.
   */
  public static <T> Constructor<T> findNoArgConstructor(Class<T> dataClass) {
    Constructor<T>[] constructors;
    try {
      @SuppressWarnings("unchecked")
      Constructor<T>[] consts = (Constructor<T>[]) dataClass.getDeclaredConstructors();
      // i do this [grossness] to be able to move the Suppress inside the method
      constructors = consts;
    } catch (Exception e) {
      throw new IllegalArgumentException("Can't lookup declared constructors for " + dataClass, e);
    }
    for (Constructor<T> con : constructors) {
      if (con.getParameterTypes().length == 0) {
        return con;
      }
    }
    if (dataClass.getEnclosingClass() == null) {
      throw new IllegalArgumentException("Can't find a no-arg constructor for " + dataClass);
    } else {
      throw new IllegalArgumentException("Can't find a no-arg constructor for " + dataClass
          + ".  Missing static on inner class?");
    }
  }

  private static <T> FieldType[] extractFieldTypes(ConnectionSource connectionSource, Class<T> clazz, String tableName)
      throws SQLException {
    List<FieldType> fieldTypes = new ArrayList<FieldType>();
    for (Class<?> classWalk = clazz; classWalk != null; classWalk = classWalk.getSuperclass()) {
      for (Field field : classWalk.getDeclaredFields()) {
        FieldType fieldType = FieldType.createFieldType(connectionSource, tableName, field, clazz);
        if (fieldType != null) {
          fieldTypes.add(fieldType);
        }
      }
    }
    if (fieldTypes.isEmpty()) {
      throw new IllegalArgumentException("No fields have a " + DatabaseField.class.getSimpleName()
          + " annotation in " + clazz);
    }
    return fieldTypes.toArray(new FieldType[fieldTypes.size()]);
  }

  private FieldType[] convertFieldConfigs(ConnectionSource connectionSource, String tableName,
      List<DatabaseFieldConfig> fieldConfigs) throws SQLException {
    List<FieldType> fieldTypes = new ArrayList<FieldType>();
    for (DatabaseFieldConfig fieldConfig : fieldConfigs) {
      FieldType fieldType = null;
      // walk up the classes until we find the field
      for (Class<?> classWalk = dataClass; classWalk != null; classWalk = classWalk.getSuperclass()) {
        Field field;
        try {
          field = classWalk.getDeclaredField(fieldConfig.getFieldName());
        } catch (NoSuchFieldException e) {
          // we ignore this and just loop hopefully finding it in a upper class
          continue;
        }
        if (field != null) {
          fieldType = new FieldType(connectionSource, tableName, field, fieldConfig, dataClass);
          break;
        }
      }

      if (fieldType == null) {
        throw new SQLException("Could not find declared field with name '" + fieldConfig.getFieldName()
            + "' for " + dataClass);
      }
      fieldTypes.add(fieldType);
    }
    if (fieldTypes.isEmpty()) {
      throw new SQLException("No fields were configured for class " + dataClass);
    }
    return fieldTypes.toArray(new FieldType[fieldTypes.size()]);
  }
}
TOP

Related Classes of com.j256.ormlite.table.DatabaseTableConfig

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.