package com.jqmobile.core.android.db.orm.table;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.jqmobile.core.android.db.orm.BaseDBColumn;
import com.jqmobile.core.android.db.orm.BaseDBTable;
import com.jqmobile.core.android.db.orm.ORMDBTable;
import com.jqmobile.core.android.db.orm.base.ORMFactory;
import com.jqmobile.core.orm.DBTable;
import com.jqmobile.core.orm.ORM;
import com.jqmobile.core.orm.TableUtil;
import com.jqmobile.core.orm.exception.ORMException;
import com.jqmobile.core.orm.exception.ORMNotDBTableException;
import com.jqmobile.core.orm.exception.TableExitsException;
import com.jqmobile.core.utils.plain.BeanUtils;
import com.jqmobile.core.utils.plain.GUIDUtils;
import com.jqmobile.core.utils.plain.Log;
class BaseTableUtil implements TableUtil{
private SQLiteDatabase SQLiteDatabase;
private Object lock = new Object();
private BaseTableUtil() {
}
private SQLiteDatabase getConnection() {
return SQLiteDatabase;
}
private void setConnection(SQLiteDatabase SQLiteDatabase) {
L10010: if(null == this.SQLiteDatabase || !this.SQLiteDatabase.isOpen()){
this.SQLiteDatabase = SQLiteDatabase;
}else{
synchronized (lock) {
try {
lock.wait(1000);
} catch (InterruptedException e) {
}
}
break L10010;
}
// Log.getLog(getClass()).e(e);
this.SQLiteDatabase = SQLiteDatabase;
}
private static BaseTableUtil util = new BaseTableUtil();
public static TableUtil getInstance(SQLiteDatabase conn) {
util.setConnection(conn);
return util;
}
@Override
public void createTable(Class<?> c) throws ORMException {
try {
BaseDBTable param = BaseDBTable.getInstance(c);
//当表已经存在的时候抛出异常
if(!valiTableExist(param.getTableName())){
BaseDBTable t = BaseDBTable.getInstance(c);
getConnection().execSQL(t.getCreateTableSql());
insertORMDBTable(t);
}else {
throw new TableExitsException("表已存在");
}
} catch (TableExitsException e) {
e.printStackTrace();
}
}
/**
* 获取表名
* @param c
* @return
*/
@SuppressWarnings("unused")
private String getTableName(Class<?> c) {
return c.getAnnotation(DBTable.class).name()!=null ? c.getAnnotation(DBTable.class).name() : c.getName().substring(c.getName().lastIndexOf(".")+1,c.getName().length()-1);
}
private void insertORMDBTable(BaseDBTable t) throws ORMNotDBTableException, ORMException {
if(t.getTableClass().equals(ORMDBTable.class)){
return;
}
// 修改表记录
ORM<ORMDBTable> orm = ORMFactory.instance(getConnection(),
ORMDBTable.class);
ORMDBTable sdt = new ORMDBTable();
sdt.setClassUrl(t.getTableClass().getName());
sdt.setName(t.getTableName());
sdt.setRecid(GUIDUtils.getUUIDByText(sdt.getName()));
int oldVersion=orm.find(GUIDUtils.getUUIDByText(sdt.getName())).getVersion();
int versionNum=orm.delete(GUIDUtils.getUUIDByText(sdt.getName()));
if(versionNum>0){
sdt.setVersion(oldVersion+1);
}else{
sdt.setVersion(t.getDBTable().version());
}
orm.insert(sdt);
}
@Override
public void updateTable(Class<?> c) throws ORMException {
BaseDBTable param = BaseDBTable.getInstance(c);
// if not find table, create table.
if (!valiTableExist(param.getTableName())) {
createTable(c);
} else {
Cursor rs = getConnection().rawQuery("SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE table_name = ?", new String[]{param.getTableName()});
List<String> oldColumn = new ArrayList<String>();
List<Field> newColumn = new ArrayList<Field>();
try {
for(rs.moveToFirst();!rs.isAfterLast();rs.moveToNext()){
oldColumn.add(rs.getString(0));
}
} finally {
rs.close();
}
Field[] fields = BeanUtils.getAllFields_Cache(c);
// 20130705
List<Field> oldFields = new ArrayList<Field>();
//
for (Field field : fields) {
if(field.getName().contains("$")) continue;
BaseDBColumn lable = BaseDBColumn.getInstance(field);
if(!lable.isMapping()) continue;
String columnName = lable.getColumnName();
if (!oldColumn.contains(columnName)
&& !oldColumn.contains(columnName.toUpperCase())) {
newColumn.add(field);
}
// 20130705
else {
oldFields.add(field);
}
//
}
if (!newColumn.isEmpty()) {
// (加入字段)
StringBuilder sql = new StringBuilder("ALTER TABLE ");// SaasDBTable
// ADD
// sex
// BOOLEAN
// ")
sql.append(param.getTableName());
String columnName, columnType;
for (int i = 0; i < newColumn.size(); i++) {
sql.append(" ADD ");
BaseDBColumn column = BaseDBColumn.getInstance(newColumn.get(i));
columnName = column.getColumnName();
columnType = column.getColumnType();
//
sql.append(" ");
sql.append(columnName);
sql.append(" ");
sql.append(columnType);
// sql.append(" ");
// sql.append(param.getColumnOther(newColumn.get(i),
// c, columnType, columnName));
if (i != newColumn.size() - 1)
sql.append(", \n");
}
getConnection().execSQL(sql.toString());
}
// 20130705(修改字段属性
if (!oldFields.isEmpty()) {
// alter table user MODIFY new1 VARCHAR(10);
StringBuilder sql = new StringBuilder("ALTER TABLE ");
sql.append(param.getTableName());
String columnName, columnType;
for (int i = 0; i < oldFields.size(); i++) {
sql.append(" MODIFY ");
BaseDBColumn column = BaseDBColumn.getInstance(newColumn.get(i));
columnName = column.getColumnName();
columnType = column.getColumnType();
//
sql.append(" ");
sql.append(columnName);
sql.append(" ");
sql.append(columnType);
// sql.append(" ");
// sql.append(param.getColumnOther(oldFields.get(i),
// lable, columnType, columnName));
if (i != oldFields.size() - 1)
sql.append(", \n");
}
getConnection().execSQL(sql.toString());
}
// 修改表记录
ORM<ORMDBTable> orm = ORMFactory.instance(getConnection(),
ORMDBTable.class);
ORMDBTable sdt = new ORMDBTable();
sdt.setClassUrl(c.getName());
sdt.setName(param.getTableName());
sdt.setRecid(GUIDUtils.getUUIDByText(sdt.getName()));
sdt.setVersion(param.getDBTable().version());
orm.update(sdt);
}
}
@Override
public void autoUpdateAllTables() throws ORMException {
ORM<ORMDBTable> orm = ORMFactory.instance(getConnection(),
ORMDBTable.class);
List<ORMDBTable> tables = orm.getAll();
Class<?> c;
for (ORMDBTable t : tables) {
try {
c = Class.forName(t.getClassUrl(), true, Thread
.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
Log.getLog(this).w(e);
continue;
}
if (!valiTableExist(t.getName())) {
createTable(c);
} else if (BaseDBTable.getInstance(c).getDBTable().version() > t
.getVersion()) {
updateTable(c);
}
}
}
/**
* 自动建表
*/
@Override
public void autoUpdateTable(Class<?> c) throws ORMException {
BaseDBTable param = BaseDBTable.getInstance(c);
// if not find table, create table.
if (!valiTableExist(param.getTableName())) {
createTable(c);
return;
}
// if have new version, update table.
if (param.getDBTable().version() > 0) {
ORM<ORMDBTable> orm = ORMFactory.instance(getConnection(),
ORMDBTable.class);
ORMDBTable table = orm.find(GUIDUtils
.getUUIDByText(param.getTableName()));
if (null == table) {
table = new ORMDBTable(c);
orm.insert(table);
updateTable(c);
} else if (param.getDBTable().version() > table
.getVersion()) {
updateTable(c);
}
}
}
@Override
public boolean valiTableExist(String tableName) {
Cursor rs = getConnection().rawQuery("SHOW TABLES LIKE ?", null);
try {
return 0 < rs.getCount();
} finally {
rs.close();
}
}
@Override
public void createMiddleTable(Class<?> c, Class<?> childClass)
throws ORMException {
}
}