package org.kvj.lima1.sync.controller.data;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
import org.kvj.bravo7.ApplicationContext;
import org.kvj.bravo7.SuperActivity;
import android.text.TextUtils;
import android.util.Log;
public class AppInfo {
private static final String TAG = "AppInfo";
public AppDBHelper db = null;
public String name = null;
private long id = 0;
public JSONObject schema = null;
public SchemaInfo schemaInfo = null;
private ApplicationContext context;
private File folderName = null;
public AppInfo(ApplicationContext context, String name) {
this.name = name;
this.context = context;
db = new AppDBHelper(context, name + "-app.db");
if (!db.open()) {
db = null;
}
String json = context.getStringPreference(name + "-schema", "");
// json =
// "{\"_rev\":2,\"_fkeys\":[{\"pk\":\"notepads.id\",\"fk\":\"sheets.notepad_id\"},{\"pk\":\"templates.id\",\"fk\":\"sheets.template_id\"},{\"pk\":\"sheets.id\",\"fk\":\"notes.sheet_id\"},{\"pk\":\"sheets.id\",\"fk\":\"bookmarks.sheet_id\"}],\"templates\":{\"index\":1,\"texts\":[\"name\",\"tag\"]},\"notepads\":{\"index\":0,\"numbers\":[\"archived\"],\"texts\":[\"name\",\"tag\"]},\"sheets\":{\"index\":2,\"numbers\":[\"template_id\",\"notepad_id\"],\"texts\":[\"title\"],\"indexes\":[[\"notepad_id\"]]},\"notes\":{\"index\":3,\"numbers\":[\"sheet_id\",\"archived\"],\"texts\":[\"text\"],\"indexes\":[[\"sheet_id\",\"archived\"]]},\"bookmarks\":{\"index\":4,\"numbers\":[\"sheet_id\"],\"texts\":[\"name\"],\"indexes\":[[\"sheet_id\"]]}}";
if (!TextUtils.isEmpty(json)) {
try {
schema = new JSONObject(json);
schemaInfo = parseSchema(schema);
} catch (Exception e) {
}
}
}
public synchronized long id() {
long now = System.currentTimeMillis();
if (now > id) {
id = now;
return id;
}
return ++id;
}
private SchemaInfo parseSchema(JSONObject schema) throws JSONException {
SchemaInfo info = new SchemaInfo();
info.parseSchema(schema);
return info;
}
private List<String> generateAlter(String table, TableInfo oldSchema, TableInfo newSchema) {
List<String> sqls = new ArrayList<String>();
for (int i = oldSchema.numbers.size(); i < newSchema.numbers.size(); i++) {
// New numbers
sqls.add(generateAlter(table, newSchema.numbers.get(i), "integer"));
}
for (int i = oldSchema.texts.size(); i < newSchema.texts.size(); i++) {
// New texts
sqls.add(generateAlter(table, newSchema.texts.get(i), "text"));
}
for (int i = oldSchema.indexes.size(); i < newSchema.indexes.size(); i++) {
// New indexes
sqls.add(createIndex(table, i, newSchema.indexes.get(i)));
}
return sqls;
}
private String generateAlter(String table, String field, String type) {
return "alter table t_" + table + " add f_" + field + " " + type;
}
private List<String> generateCreate(String table, TableInfo info) {
List<String> sqls = new ArrayList<String>();
StringBuffer create = new StringBuffer(
"create table if not exists t_"
+ table
+ " (id integer primary key, status integer default 0, updated integer default 0, own integer default 1, stream text, data text");
for (String field : info.numbers) { // Add numbers
create.append(", f_" + field + " integer");
}
for (String field : info.texts) { // Add texts
create.append(", f_" + field + " text");
}
create.append(")");
sqls.add(create.toString());
for (int i = 0; i < info.indexes.size(); i++) { // Create index
sqls.add(createIndex(table, i, info.indexes.get(i)));
}
return sqls;
}
private String createIndex(String table, int index, List<String> fields) {
StringBuffer create = new StringBuffer("create index i_" + table + "_" + index + " on t_" + table + " (status");
for (String field : fields) { // Add fields
create.append(", f_" + field);
}
create.append(")");
return create.toString();
}
public String upgradeSchema(JSONObject newSchema) {
try { // DB and JSON errors
SchemaInfo newSchemaInfo = new SchemaInfo();
newSchemaInfo.parseSchema(newSchema);
Log.i(TAG, "upgradeSchema: " + schemaInfo + ", " + newSchemaInfo);
if (null == schemaInfo || schemaInfo.revision < newSchemaInfo.revision) {
// New or upgrades are different
List<String> sqls = new ArrayList<String>();
for (String table : newSchemaInfo.tables.keySet()) {
// Check every table
if (null == schemaInfo || !schemaInfo.tables.containsKey(table)) {
// Create table
sqls.addAll(generateCreate(table, newSchemaInfo.tables.get(table)));
} else {
sqls.addAll(generateAlter(table, schemaInfo.tables.get(table), newSchemaInfo.tables.get(table)));
}
}
// Log.i(TAG, "Upgrade: " + sqls);
for (String sql : sqls) { // Execute SQL
Log.i(TAG, "Upgrade schema: " + sql);
db.getDatabase().execSQL(sql);
}
schemaInfo = newSchemaInfo;
}
return null;
} catch (Exception e) {
Log.e(TAG, "Error upgrading schema", e);
return "Error upgrading DB schema";
}
}
public void setSchema(JSONObject newSchema) {
schema = newSchema;
context.setStringPreference(name + "-schema", newSchema.toString());
}
public TableInfo getTableInfo(String stream) {
if (null == db) { // No DB
return null;
}
if (null == schemaInfo) { // Not synchronized
return null;
}
return schemaInfo.tables.get(stream);
}
public File getFilesFolder() {
if (null == folderName) {
folderName = new File(SuperActivity.getExternalCacheFolder(context), "files" + File.separatorChar + name);
if (!folderName.exists()) { // Not created yet
if (!folderName.mkdirs()) { // Failed
Log.w(TAG, "Error creating cache files folder");
}
}
}
return folderName;
}
}