package com.openerp.orm;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.openerp.base.ir.Ir_model;
import com.openerp.orm.OEM2MIds.Operation;
import com.openerp.receivers.DataSetChangeReceiver;
import com.openerp.support.OEUser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public abstract class OEDatabase extends OESQLiteHelper implements OEDBHelper {
public static final String TAG = "com.openerp.orm.OEDatabase";
protected Context mContext = null;
OEDBHelper mDBHelper = null;
OEUser mUser = null;
List<OEDataRow> mRemovedRecords = new ArrayList<OEDataRow>();
public OEDatabase(Context context) {
super(context);
mContext = context;
mUser = OEUser.current(mContext);
mDBHelper = this;
}
public String modelName() {
return mDBHelper.getModelName();
}
public String tableName() {
return mDBHelper.getModelName().replaceAll("\\.", "_");
}
//获取简单表名,比如hr.expense.expense 得到expense
public String simpTableName() {
String[] arr = mDBHelper.getModelName().split("\\.");
return arr[arr.length - 1];
}
public void setAccountUser(OEUser user) {
mUser = user;
}
public int count() {
return count(null, null);
}
public int count(String where, String[] whereArgs) {
int count = 0;
if (where == null) {
where = " oea_name = ?";
whereArgs = new String[]{mUser.getAndroidName()};
} else {
where += " and oea_name = ?";
List<String> tmpWhereArgs = new ArrayList<String>();
tmpWhereArgs.addAll(Arrays.asList(whereArgs));
tmpWhereArgs.add(mUser.getAndroidName());
whereArgs = tmpWhereArgs.toArray(new String[tmpWhereArgs.size()]);
}
SQLiteDatabase db = getReadableDatabase();
Cursor cr = db.query(tableName(), new String[]{"count(*) as total"},
where, whereArgs, null, null, null);
if (cr.moveToFirst()) {
count = cr.getInt(0);
}
cr.close();
db.close();
return count;
}
public int update(OEValues values, int id) {
int ret = update(values, "id = ?", new String[]{id + ""});
if (ret > 0)
broadcastInfo(id);
return ret;
}
public void updateManyToManyRecords(String column, Operation operation,
int id, int rel_id) {
List<Integer> ids = new ArrayList<Integer>();
ids.add(rel_id);
updateManyToManyRecords(column, operation, id, ids);
}
public void updateManyToManyRecords(String column, Operation operation,
int id, List<Integer> ids) {
OEDBHelper m2mObj = findFieldModel(column);
manageMany2ManyRecords(m2mObj, operation, (long) id, ids);
}
public int update(OEValues values, String where, String[] whereArgs) {
if (where == null) {
where = " oea_name = ?";
whereArgs = new String[]{mUser.getAndroidName()};
} else {
where += " and oea_name = ?";
List<String> tmpWhereArgs = new ArrayList<String>();
tmpWhereArgs.addAll(Arrays.asList(whereArgs));
tmpWhereArgs.add(mUser.getAndroidName());
whereArgs = tmpWhereArgs.toArray(new String[tmpWhereArgs.size()]);
}
if (!values.contains("oea_name")) {
values.put("oea_name", mUser.getAndroidName());
}
SQLiteDatabase db = getWritableDatabase();
HashMap<String, Object> res = getContentValues(values);
ContentValues cValues = (ContentValues) res.get("cValues");
int count = db.update(tableName(), cValues, where, whereArgs);
db.close();
if (res.containsKey("m2mObjects")) {
@SuppressWarnings("unchecked")
List<HashMap<String, Object>> objectList = (List<HashMap<String, Object>>) res.get("m2mObjects");
for (HashMap<String, Object> obj : objectList) {
OEDBHelper m2mDb = (OEDBHelper) obj.get("m2mObject");
for (OEDataRow row : select(where, whereArgs, null, null, null)) {
manageMany2ManyRecords(m2mDb, Operation.REPLACE, row.getInt("id"), obj.get("m2mRecordsObj"));
}
}
}
return count;
}
public List<Long> createORReplace(List<OEValues> listValues) {
return createORReplace(listValues, false);
}
public List<Long> createORReplace(List<OEValues> listValues, boolean canDeleteLocalIfNotExists) {
List<Long> ids = new ArrayList<Long>();
for (OEValues values : listValues) {
long id = values.getInt("id");
if (id == -1)
continue;
int count = count("id = ?", new String[]{values.getString("id")});
if (count == 0) {
ids.add(id);
create(values);
} else {
ids.add(id);
update(values, values.getInt("id"));
}
}
if (canDeleteLocalIfNotExists) {
mRemovedRecords = new ArrayList<OEDataRow>();
for (OEDataRow row : select()) {
if (!ids.contains(Long.parseLong(row.getString("id")))) {
delete(row.getInt("id"));
mRemovedRecords.add(row);
}
}
}
return ids;
}
public List<OEDataRow> getRemovedRecords() {
return mRemovedRecords;
}
public long create(OEValues values) {
long newId = 0;
if (!values.contains("oea_name")) {
values.put("oea_name", mUser.getAndroidName());
}
SQLiteDatabase db = getWritableDatabase();
HashMap<String, Object> res = getContentValues(values);
ContentValues cValues = (ContentValues) res.get("cValues");
db.insert(tableName(), null, cValues);
newId = cValues.getAsInteger("id");
broadcastInfo(newId);
db.close();
//插入many2many表的值
if (res.containsKey("m2mObjects")) {
@SuppressWarnings("unchecked")
List<HashMap<String, Object>> objectList = (List<HashMap<String, Object>>) res.get("m2mObjects");
for (HashMap<String, Object> obj : objectList) {
OEDBHelper m2mDb = (OEDBHelper) obj.get("m2mObject");
manageMany2ManyRecords(m2mDb, Operation.ADD, newId, obj.get("m2mRecordsObj"));
}
}
return newId;
}
private HashMap<String, Object> getContentValues(OEValues values) {
HashMap<String, Object> result = new HashMap<String, Object>();
ContentValues cValues = new ContentValues();
List<HashMap<String, Object>> m2mObjectList = new ArrayList<HashMap<String, Object>>();
List<OEColumn> cols = mDBHelper.getModelColumns();
cols.addAll(getDefaultCols());
for (OEColumn col : cols) {
String key = col.getName();
if (values.contains(key)) {
if (values.get(key) instanceof OEM2MIds) {
HashMap<String, Object> m2mObjects = new HashMap<String, Object>();
OEDBHelper m2mDb = findFieldModel(key);
m2mObjects.put("m2mObject", m2mDb);
m2mObjects.put("m2mRecordsObj", values.get(key));
m2mObjectList.add(m2mObjects);
continue;
}
//如果是o2m字段,则直接跳过
if (values.get(key) instanceof OEO2MIds) {
continue;
}
cValues.put(key, values.get(key).toString());
}
}
result.put("m2mObjects", m2mObjectList);
result.put("cValues", cValues);
return result;
}
@SuppressWarnings("unchecked")
private void manageMany2ManyRecords(OEDBHelper relDb, Operation operation,
long id, Object idsObj) {
String first_table = tableName();
String second_table = relDb.getModelName().replaceAll("\\.", "_");
String rel_table = first_table + "_" + second_table + "_rel";
List<Integer> ids = new ArrayList<Integer>();
if (idsObj instanceof OEM2MIds) {
OEM2MIds idsObject = (OEM2MIds) idsObj;
operation = idsObject.getOperation();
ids = idsObject.getIds();
}
if (idsObj instanceof List) {
ids = (List<Integer>) idsObj;
}
SQLiteDatabase db = null;
String col_first = first_table + "_id";
String col_second = second_table + "_id";
if (operation == Operation.REPLACE) {
db = getWritableDatabase();
db.delete(rel_table, col_first + " = ? AND oea_name = ?",
new String[]{id + "", mUser.getAndroidName()});
db.close();
}
for (Integer rId : ids) {
ContentValues values = new ContentValues();
values.put(col_first, id);
values.put(col_second, rId);
values.put("oea_name", mUser.getAndroidName());
switch (operation) {
case ADD:
case APPEND:
case REPLACE:
Log.d(TAG,
"manageMany2ManyRecords() ADD, APPEND, REPLACE called");
if (!hasRecord(rel_table, col_first + " = ? AND " + col_second
+ " = ? AND oea_name = ?", new String[]{id + "",
rId + "", mUser.getAndroidName()})) {
db = getWritableDatabase();
db.insert(rel_table, null, values);
db.close();
}
break;
case REMOVE:
Log.d(TAG, "createMany2ManyRecords() REMOVE called");
db = getWritableDatabase();
db.delete(rel_table, col_first + " = ? AND " + col_second
+ " = ? AND oea_name = ?", new String[]{id + "",
rId + "", mUser.getAndroidName()});
db.close();
break;
}
}
}
private boolean hasRecord(String table, String where, String[] whereArgs) {
boolean flag = false;
if (where == null) {
where = " oea_name = ?";
whereArgs = new String[]{mUser.getAndroidName()};
} else {
where += " and oea_name = ?";
List<String> tmpWhereArgs = new ArrayList<String>();
tmpWhereArgs.addAll(Arrays.asList(whereArgs));
tmpWhereArgs.add(mUser.getAndroidName());
whereArgs = tmpWhereArgs.toArray(new String[tmpWhereArgs.size()]);
}
SQLiteDatabase db = getReadableDatabase();
Cursor cr = db.query(table, new String[]{"count(*) as total"},
where, whereArgs, null, null, null);
cr.moveToFirst();
int count = cr.getInt(0);
cr.close();
db.close();
if (count > 0) {
flag = true;
}
return flag;
}
private OEDBHelper findFieldModel(String field) {
for (OEColumn col : mDBHelper.getModelColumns()) {
if (field.equals(col.getName()) && col.getType() instanceof OEManyToMany) {
OEManyToMany m2m = (OEManyToMany) col.getType();
return m2m.getDBHelper();
}
}
return null;
}
public int delete() {
return delete(null, null);
}
public int delete(String table) {
return delete(table, null, null);
}
public int delete(int id) {
return delete("id = ?", new String[]{id + ""});
}
public int delete(String where, String[] whereArgs) {
return delete(tableName(), where, whereArgs);
}
private int delete(String table, String where, String[] whereArgs) {
if (where == null) {
where = "oea_name = ?";
whereArgs = new String[]{mUser.getAndroidName()};
} else {
where += " AND oea_name = ?";
List<String> tmpWhereArgs = new ArrayList<String>();
tmpWhereArgs.addAll(Arrays.asList(whereArgs));
tmpWhereArgs.add(mUser.getAndroidName());
whereArgs = tmpWhereArgs.toArray(new String[tmpWhereArgs.size()]);
}
int count = 0;
if (deleteMany2ManyRecord(select(where, whereArgs))) {
SQLiteDatabase db = getWritableDatabase();
count = db.delete(table, where, whereArgs);
db.close();
}
return count;
}
private boolean deleteMany2ManyRecord(List<OEDataRow> records) {
for (OEDataRow rec : records) {
int id = rec.getInt("id");
for (OEColumn col : getModelColumns()) {
if (col.getType() instanceof OEManyToMany) {
OEDatabase m2mDB = (OEDatabase) ((OEManyToMany) col
.getType()).getDBHelper();
List<Integer> idsObj = new ArrayList<Integer>();
for (OEDataRow m2mRec : rec.getM2MRecord(col.getName())
.browseEach())
idsObj.add(m2mRec.getInt("id"));
manageMany2ManyRecords(m2mDB, Operation.REMOVE, id, idsObj);
}
}
}
return true;
}
public List<OEDataRow> select() {
return select(null, null, null, null, null);
}
public OEDataRow select(int id) {
List<OEDataRow> rows = select("id = ?", new String[]{id + ""}, null,
null, null);
if (rows.size() > 0) {
return rows.get(0);
}
return null;
}
public List<OEDataRow> select(String where, String[] whereArgs) {
return select(where, whereArgs, null, null, null);
}
public List<Integer> ids() {
List<Integer> ids = new ArrayList<Integer>();
for (OEDataRow row : select()) {
ids.add(row.getInt("id"));
}
return ids;
}
public List<OEDataRow> select(String where, String[] whereArgs,
String groupBy, String having, String orderBy) {
if (where == null) {
where = "oea_name = ?";
whereArgs = new String[]{mUser.getAndroidName()};
} else {
where += " AND oea_name = ?";
List<String> tmpWhereArgs = new ArrayList<String>();
tmpWhereArgs.addAll(Arrays.asList(whereArgs));
tmpWhereArgs.add(mUser.getAndroidName());
whereArgs = tmpWhereArgs.toArray(new String[tmpWhereArgs.size()]);
}
List<OEDataRow> rows = new ArrayList<OEDataRow>();
SQLiteDatabase db = getReadableDatabase();
String[] cols = getColumns();
Cursor cr = db.query(tableName(), cols, where, whereArgs, groupBy,
having, orderBy);
List<OEColumn> mCols = mDBHelper.getModelColumns();
mCols.addAll(getDefaultCols());
if (cr.moveToFirst()) {
do {
OEDataRow row = new OEDataRow();
for (OEColumn col : mCols) {
row.put(col.getName(), createRowData(col, cr));
}
rows.add(row);
} while (cr.moveToNext());
}
cr.close();
db.close();
return rows;
}
public List<OEDataRow> selectM2M(OEDBHelper rel_db, String where,
String[] whereArgs) {
if (where == null) {
where = "oea_name = ?";
whereArgs = new String[]{mUser.getAndroidName()};
} else {
where += " AND oea_name = ?";
List<String> tmpWhereArgs = new ArrayList<String>();
tmpWhereArgs.addAll(Arrays.asList(whereArgs));
tmpWhereArgs.add(mUser.getAndroidName());
whereArgs = tmpWhereArgs.toArray(new String[tmpWhereArgs.size()]);
}
List<OEDataRow> rows = new ArrayList<OEDataRow>();
HashMap<String, Object> mRelObj = relTableColumns(rel_db);
@SuppressWarnings("unchecked")
List<OEColumn> mCols = (List<OEColumn>) mRelObj.get("columns");
List<String> cols = new ArrayList<String>();
for (OEColumn col : mCols) {
cols.add(col.getName());
}
SQLiteDatabase db = getReadableDatabase();
Cursor cr = db.query(mRelObj.get("rel_table").toString(),
cols.toArray(new String[cols.size()]), where, whereArgs, null,
null, null);
OEDatabase rel_db_obj = (OEDatabase) rel_db;
String rel_col_name = rel_db_obj.tableName() + "_id";
if (cr.moveToFirst()) {
do {
int id = cr.getInt(cr.getColumnIndex(rel_col_name));
rows.add(rel_db_obj.select(id));
} while (cr.moveToNext());
}
cr.close();
db.close();
return rows;
}
//获取o2m字段的值
public List<OEDataRow> selectO2M(OEDBHelper rel_db, String where,
String[] whereArgs) {
if (where == null) {
where = "oea_name = ?";
whereArgs = new String[]{mUser.getAndroidName()};
} else {
where += " AND oea_name = ?";
List<String> tmpWhereArgs = new ArrayList<String>();
tmpWhereArgs.addAll(Arrays.asList(whereArgs));
tmpWhereArgs.add(mUser.getAndroidName());
whereArgs = tmpWhereArgs.toArray(new String[tmpWhereArgs.size()]);
}
List<OEDataRow> rows = ((OEDatabase) rel_db).select(where, whereArgs, null, null, null);
return rows;
}
private Object createRowData(OEColumn col, Cursor cr) {
if (col.getType() instanceof String) {
return cr.getString(cr.getColumnIndex(col.getName()));
}
if (col.getType() instanceof OEManyToOne) {
return new OEM2ORecord(col, cr.getString(cr.getColumnIndex(col
.getName())));
}
if (col.getType() instanceof OEManyToMany) {
return new OEM2MRecord(this, col,
cr.getInt(cr.getColumnIndex("id")));
}
if (col.getType() instanceof OEOneToMany) {
return new OEO2MRecord(this, col,
cr.getInt(cr.getColumnIndex("id")));
}
return null;
}
private String[] getColumns() {
List<String> cols = new ArrayList<String>();
cols.add("id");
for (OEColumn col : mDBHelper.getModelColumns()) {
if (col.getType() instanceof String
|| col.getType() instanceof OEManyToOne) {
cols.add(col.getName());
}
}
cols.add("oea_name");
return cols.toArray(new String[cols.size()]);
}
public OEHelper getOEInstance() {
OEHelper openerp = null;
try {
openerp = new OEHelper(mContext, mUser, this);
} catch (Exception e) {
Log.d(TAG, "OEDatabase->getOEInstance()");
Log.e(TAG, e.getMessage() + ". No connection with OpenERP server");
}
return openerp;
}
public boolean isInstalledOnServer() {
OEHelper oe = getOEInstance();
boolean installed = false;
if (oe != null) {
installed = oe.isModelInstalled(getModelName());
} else {
Ir_model ir = new Ir_model(mContext);
List<OEDataRow> rows = ir.select("model = ?",
new String[]{getModelName()});
if (rows.size() > 0) {
installed = rows.get(0).getBoolean("is_installed");
}
}
return installed;
}
public boolean truncateTable(String table) {
if (delete(table) > 0) {
return true;
}
return false;
}
public boolean truncateTable() {
if (delete() > 0) {
return true;
}
return false;
}
public boolean isEmptyTable() {
boolean flag = true;
if (count() > 0) {
flag = false;
}
return flag;
}
public HashMap<String, Object> relTableColumns(OEDBHelper relDB) {
List<OEColumn> mCols = new ArrayList<OEColumn>();
HashMap<String, Object> res = new HashMap<String, Object>();
String main_table = tableName();
String ref_table = relDB.getModelName().replaceAll("\\.", "_");
String rel_table = main_table + "_" + ref_table + "_rel";
res.put("rel_table", rel_table);
mCols.add(new OEColumn(main_table + "_id", "Main ID", OEFields
.integer()));
mCols.add(new OEColumn(ref_table + "_id", "Ref ID", OEFields.integer()));
mCols.add(new OEColumn("oea_name", "Android name", OEFields.text()));
res.put("columns", mCols);
return res;
}
public List<OEColumn> getDefaultCols() {
List<OEColumn> cols = new ArrayList<OEColumn>();
cols.add(new OEColumn("id", "id", OEFields.integer()));
cols.add(new OEColumn("oea_name", "android name", OEFields.varchar(50),
false));
return cols;
}
public List<OEColumn> getDatabaseColumns() {
return mDBHelper.getModelColumns();
}
public List<OEColumn> getDatabaseServerColumns() {
List<OEColumn> cols = new ArrayList<OEColumn>();
for (OEColumn col : mDBHelper.getModelColumns()) {
if (col.canSync()) {
cols.add(col);
}
}
return cols;
}
public int lastId() {
int last_id = 0;
SQLiteDatabase db = getReadableDatabase();
Cursor cr = db.query(tableName(), new String[]{"MAX(id) as id"},
"oea_name = ?", new String[]{mUser.getAndroidName()}, null,
null, null);
if (cr.moveToFirst())
last_id = cr.getInt(0);
cr.close();
db.close();
return last_id;
}
private void broadcastInfo(long newId) {
Intent intent = new Intent();
intent.setAction(DataSetChangeReceiver.DATA_CHANGED);
intent.putExtra("id", String.valueOf(newId));
intent.putExtra("model", modelName());
mContext.sendBroadcast(intent);
}
}