com.momock.util.JsonDatabase.java Source code

Java tutorial

Introduction

Here is the source code for com.momock.util.JsonDatabase.java

Source

/*******************************************************************************
 * Copyright 2013 momock.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.momock.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public abstract class JsonDatabase {
    static final int IDX_ID = 0;
    static final int IDX_NAME = 1;
    static final int IDX_JSON = 2;

    public static class Document {
        Collection col;
        String id;
        JSONObject jo;

        Document(Collection col, String id, JSONObject jo) {
            this.col = col;
            this.id = id;
            this.jo = jo;
        }

        public String getId() {
            return id;
        }

        public JSONObject getData() {
            if (jo == null) {
                jo = col.get(id);
            }
            return jo;
        }
    }

    public static interface IFilter {
        boolean check(String id, JSONObject doc);
    }

    public static class Collection {
        MySQLiteOpenHelper helper;
        String name;
        SQLiteDatabase dbMem = null;
        JsonDatabase jdb;
        boolean cachable = false;
        HashMap<String, Document> cachedDocs = null;

        Collection(JsonDatabase db, MySQLiteOpenHelper helper, String name) {
            this.jdb = db;
            this.helper = helper;
            this.name = name;
        }

        public JSONObject get(String id) {
            if (id == null)
                return null;
            if (cachable) {
                Document doc = cachedDocs.get(id);
                return doc == null ? null : doc.getData();
            }
            JSONObject jo = null;
            String sql = "select * from data where id=? and name=?;";
            SQLiteDatabase db = jdb.getNativeDatabase();
            if (db == null)
                return null;
            Cursor cursor = null;
            try {
                cursor = db.rawQuery(sql, new String[] { id, name });
                if (cursor != null && cursor.getCount() == 1) {
                    cursor.moveToNext();
                    String json = cursor.getString(IDX_JSON);
                    jo = parse(json);
                }
            } catch (Exception e) {
                Logger.error(e);
            } finally {
                if (cursor != null) {
                    cursor.close();
                    cursor = null;
                }
            }
            return jo;
        }

        public String set(String id, JSONObject jo) {
            SQLiteDatabase db = jdb.getNativeDatabase();
            if (db == null)
                return null;
            Cursor cursor = null;
            try {
                if (id == null)
                    id = UUID.randomUUID().toString();
                if (jo == null) {
                    db.delete("data", "id=? and name=?", new String[] { id, name });
                    if (cachable) {
                        cachedDocs.remove(id);
                    }
                } else {
                    String sql = "select * from data where id=? and name=?;";
                    cursor = db.rawQuery(sql, new String[] { id, name });
                    String json = jo.toString();
                    boolean exists = cursor != null && cursor.getCount() == 1;
                    Logger.debug("exists " + exists + ":" + cursor.getCount());
                    if (exists) {
                        ContentValues values = new ContentValues();
                        values.put("json", json);
                        db.update("data", values, "id=? and name=?", new String[] { id, name });
                    } else {
                        ContentValues values = new ContentValues();
                        values.put("id", id);
                        values.put("name", name);
                        values.put("json", json);
                        db.insert("data", "", values);
                    }
                    if (cachable) {
                        cachedDocs.put(id, new Document(this, id, jo));
                    }
                }
            } catch (Exception e) {
                Logger.error(e);
            } finally {
                if (cursor != null) {
                    cursor.close();
                    cursor = null;
                }
            }
            return id;
        }

        public int size() {
            return cachable ? cachedDocs.size() : list().size();
        }

        public List<Document> list() {
            return list(null, false, 0);
        }

        public List<Document> list(IFilter filter, boolean delayLoad, int max) {
            List<Document> rows = new ArrayList<Document>();
            if (cachable) {
                for (Document doc : cachedDocs.values()) {
                    String id = doc.getId();
                    if (filter == null) {
                        rows.add(doc);
                    } else {
                        if (filter.check(id, doc.getData())) {
                            rows.add(doc);
                        }
                    }
                    if (max > 0 && rows.size() >= max)
                        break;
                }
                return rows;
            }
            String sql = "select * from data where name=?";
            SQLiteDatabase db = jdb.getNativeDatabase();
            if (db == null)
                return rows;
            Cursor cursor = null;
            try {
                cursor = db.rawQuery(sql, new String[] { name });
                if (cursor != null) {
                    while (cursor.moveToNext()) {
                        String id = cursor.getString(IDX_ID);
                        if (filter == null) {
                            rows.add(new Document(this, id, delayLoad ? null : parse(cursor.getString(IDX_JSON))));
                        } else {
                            String json = cursor.getString(IDX_JSON);
                            JSONObject jo = parse(json);
                            if (filter.check(id, jo)) {
                                rows.add(new Document(this, id, delayLoad ? null : jo));
                            }
                        }
                        if (max > 0 && rows.size() >= max)
                            break;
                    }
                }
            } catch (Exception e) {
                Logger.error(e);
            } finally {
                if (cursor != null) {
                    cursor.close();
                    cursor = null;
                }
            }
            return rows;
        }

        public boolean isCachable() {
            return cachable;
        }

        public void setCachable(boolean cachable) {
            if (this.cachable != cachable) {
                if (cachable) {
                    cachedDocs = new HashMap<String, Document>();
                    List<Document> docs = list();
                    for (Document doc : docs) {
                        cachedDocs.put(doc.getId(), doc);
                    }
                }
                this.cachable = cachable;
            }
        }
    }

    private static class MySQLiteOpenHelper extends SQLiteOpenHelper {

        public MySQLiteOpenHelper(Context context, String name) {
            super(context, name, null, 1);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            String sql = "create table data(id text,name text,json text, primary key(name, id));";
            Logger.debug("Create Json Database");
            db.execSQL(sql);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }

    }

    abstract SQLiteDatabase getNativeDatabase();

    public abstract Collection getCollection(String name);

    public abstract void forceClose();

    public static JsonDatabase get(Context context) {
        return get(context, null);
    }

    public static JsonDatabase get(final Context context, final String dbname) {
        return new JsonDatabase() {
            Map<String, Collection> cols = new HashMap<String, Collection>();
            SQLiteDatabase db = null;
            MySQLiteOpenHelper helper = new MySQLiteOpenHelper(context, dbname);

            @Override
            public Collection getCollection(String name) {
                if (!cols.containsKey(name)) {
                    cols.put(name, new Collection(this, helper, name));
                }
                return cols.get(name);
            }

            @Override
            public void forceClose() {
                if (db != null) {
                    db.close();
                    db = null;
                }
            }

            @Override
            SQLiteDatabase getNativeDatabase() {
                if (db == null || !db.isOpen()) {
                    try {
                        db = helper.getWritableDatabase();
                    } catch (Exception e) {
                        Logger.error(e);
                        Logger.debug("Database Path :" + context.getDatabasePath(dbname).getPath());
                        try {
                            helper = new MySQLiteOpenHelper(context, null);
                            db = helper.getWritableDatabase();
                        } catch (Exception ex) {
                            Logger.error(ex);
                            db = null;
                        }
                    }
                }
                return db;
            }

        };
    }

    static JSONObject parse(String json) {
        JSONTokener tokener = new JSONTokener(json);
        Object root;
        try {
            root = tokener.nextValue();
        } catch (JSONException e) {
            Logger.error(e);
            return null;
        }
        return (JSONObject) root;
    }
}