org.disciple.db.Abatis.java Source code

Java tutorial

Introduction

Here is the source code for org.disciple.db.Abatis.java

Source

/*
* 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 org.disciple.db;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * 
 * @author sonix - http://www.sonix.asia
 * @since JDK1.5 Android Level 3
 *
 */
public class Abatis extends SQLiteOpenHelper {
    /**
     * Debug TAG
     */
    private static final String TAG = "aBatis";

    /**
     * DB
     */
    private static final String INIT_CREATE_SQL = "abatis_init";

    /**
     * abatis version
     */
    private static final String VERSION_FOR_UPGRADE = "abatis_version";

    /**
     * Default DB file name
     */
    private static final String DB_FILE_NAME = DataConstants.DB_NAME;

    /**
     * SQLiteDatabase object
     */
    private SQLiteDatabase dbObj;

    /**
     * Context object
     */
    private Context context;

    /**
     * Upgrade Flag
     */
    private boolean isUpgrade = false;

    /**
     * Default DB file name constructor
     *
     * @param context
     *
     */
    public Abatis(Context context) {
        super(context, DB_FILE_NAME, null, Integer.parseInt(context.getResources().getString(
                context.getResources().getIdentifier(VERSION_FOR_UPGRADE, "string", context.getPackageName()))));
        this.context = context;
    }

    /**
     *
     * @param context
     * @param dbName
     *
     */
    public Abatis(Context context, String dbName) {
        super(context, dbName.concat(".db"), null, Integer.parseInt(context.getResources().getString(
                context.getResources().getIdentifier(VERSION_FOR_UPGRADE, "string", context.getPackageName()))));
        this.context = context;
    }

    /**
     * DB connector
     * @param db SQLiteDatabase object
     *
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        int pointer = context.getResources().getIdentifier(INIT_CREATE_SQL, "string", context.getPackageName());
        if (pointer == 0) {
            Log.e(TAG, "undefined sql id - initialize");
        } else {
            String[] createTabelSqls = context.getResources().getString(pointer).split(";");
            for (String sql : createTabelSqls) {
                db.execSQL(sql + ";");
            }
        }
    }

    /**
     * for upgrade
     *
     * @param db SQLiteDatabase object
     * @param oldVersion old version value
     * @param newVersion new version value
     * 
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        isUpgrade = true;
    }

    /**
     * @param sqlId SQLID
     * @param bindParams sql parameter
     * 
     * @return Map<String, Object> result
     */
    public Map<String, Object> executeForMap(String sqlId, Map<String, Object> bindParams) {
        getDbObject();
        int pointer = context.getResources().getIdentifier(sqlId, "string", context.getPackageName());
        if (pointer == 0) {
            Log.e(TAG, "undefined sql id");
            return null;
        }
        String sql = context.getResources().getString(pointer);
        if (bindParams != null) {
            Iterator<String> mapIterator = bindParams.keySet().iterator();
            while (mapIterator.hasNext()) {
                String key = mapIterator.next();
                Object value = bindParams.get(key);
                sql = sql.replaceAll("#" + key.toLowerCase() + "#",
                        value == null ? null : "'" + value.toString() + "'");
            }
        }
        if (sql.indexOf('#') != -1) {
            Log.e(TAG, "undefined parameter");
            return null;
        }
        Cursor cursor = dbObj.rawQuery(sql, null);
        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
        if (cursor == null) {
            return null;
        }
        String[] columnNames = cursor.getColumnNames();
        while (cursor.moveToNext()) {
            Map<String, Object> map = new HashMap<String, Object>();
            int i = 0;
            for (String columnName : columnNames) {
                map.put(columnName, cursor.getString(i));
                i++;
            }
            mapList.add(map);
        }
        if (mapList.size() <= 0) {
            return null;
        }
        cursor.close();
        dbObj.close();
        return mapList.get(0);
    }

    /**
     *
     * @param sqlId SQLID
     * @param bindParams sql parameter
     * 
     * @return List<Map<String, Object>> result
     */
    public List<Map<String, Object>> executeForMapList(String sqlId, Map<String, Object> bindParams) {
        getDbObject();
        int pointer = context.getResources().getIdentifier(sqlId, "string", context.getPackageName());
        if (pointer == 0) {
            Log.e(TAG, "undefined sql id");
            return null;
        }
        String sql = context.getResources().getString(pointer);
        if (bindParams != null) {
            Iterator<String> mapIterator = bindParams.keySet().iterator();
            while (mapIterator.hasNext()) {
                String key = mapIterator.next();
                Object value = bindParams.get(key);
                sql = sql.replaceAll("#" + key.toLowerCase() + "#",
                        value == null ? null : "'" + value.toString() + "'");
            }
        }
        if (sql.indexOf('#') != -1) {
            Log.e(TAG, "undefined parameter");
            return null;
        }
        Cursor cursor = dbObj.rawQuery(sql, null);
        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
        if (cursor == null) {
            return null;
        }
        String[] columnNames = cursor.getColumnNames();
        while (cursor.moveToNext()) {
            Map<String, Object> map = new HashMap<String, Object>();
            int i = 0;
            for (String columnName : columnNames) {
                map.put(columnName, cursor.getString(i));
                i++;
            }
            mapList.add(map);
        }
        cursor.close();
        dbObj.close();
        return mapList;
    }

    /**
     *
     * @param sqlId SQLID
     * @param bindParams sql parameter
     * @param bean bean class of result 
     * 
     * @return List<Map<String, Object>> result
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public <T> T executeForBean(String sqlId, Map<String, Object> bindParams, Class bean) {
        getDbObject();
        int pointer = context.getResources().getIdentifier(sqlId, "string", context.getPackageName());
        if (pointer == 0) {
            Log.e(TAG, "undefined sql id");
            return null;
        }
        String sql = context.getResources().getString(pointer);
        if (bindParams != null) {
            Iterator<String> mapIterator = bindParams.keySet().iterator();
            while (mapIterator.hasNext()) {
                String key = mapIterator.next();
                Object value = bindParams.get(key);
                sql = sql.replaceAll("#" + key.toLowerCase() + "#",
                        value == null ? null : "'" + value.toString() + "'");
            }
        }
        if (sql.indexOf('#') != -1) {
            Log.e(TAG, "undefined parameter");
            return null;
        }
        Cursor cursor = dbObj.rawQuery(sql, null);
        List<T> objectList = new ArrayList<T>();
        if (cursor == null) {
            return null;
        }
        String[] columnNames = cursor.getColumnNames();
        List<String> dataNames = new ArrayList<String>();
        for (String columnName : columnNames) {
            dataNames.add(chgDataName(columnName));
        }
        T beanObj = null;
        // get bean class package
        Package beanPackage = bean.getPackage();
        while (cursor.moveToNext()) {
            Map<String, Object> map = new HashMap<String, Object>();
            int i = 0;
            for (String dataName : dataNames) {
                map.put(dataName, cursor.getString(i));
                i++;
            }
            JSONObject json = new JSONObject(map);
            try {
                beanObj = (T) parse(json.toString(), bean, beanPackage.getName());
            } catch (Exception e) {
                Log.d(TAG, e.toString());
                return null;
            }
            objectList.add(beanObj);
        }
        if (objectList.size() <= 0) {
            return null;
        }
        cursor.close();
        dbObj.close();
        return objectList.get(0);
    }

    /**
     *
     * @param sqlId SQLID
     * @param bindParams sql parameter
     * @param bean bean class of result 
     * 
     * @return List<Map<String, Object>> result
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public <T> List<T> executeForBeanList(String sqlId, Map<String, Object> bindParams, Class bean) {
        getDbObject();
        int pointer = context.getResources().getIdentifier(sqlId, "string", context.getPackageName());
        if (pointer == 0) {
            Log.e(TAG, "undefined sql id");
            return null;
        }
        String sql = context.getResources().getString(pointer);
        if (bindParams != null) {
            Iterator<String> mapIterator = bindParams.keySet().iterator();
            while (mapIterator.hasNext()) {
                String key = mapIterator.next();
                Object value = bindParams.get(key);
                sql = sql.replaceAll("#" + key.toLowerCase() + "#",
                        value == null ? null : "'" + value.toString() + "'");
            }
        }
        if (sql.indexOf('#') != -1) {
            Log.e(TAG, "undefined parameter");
            return null;
        }
        Cursor cursor = dbObj.rawQuery(sql, null);
        List<T> objectList = new ArrayList<T>();
        if (cursor == null) {
            return null;
        }
        String[] columnNames = cursor.getColumnNames();
        List<String> dataNames = new ArrayList<String>();
        for (String columnName : columnNames) {
            dataNames.add(chgDataName(columnName));
        }
        T beanObj = null;
        // get bean class package
        Package beanPackage = bean.getPackage();
        while (cursor.moveToNext()) {
            Map<String, Object> map = new HashMap<String, Object>();
            int i = 0;
            for (String dataName : dataNames) {
                map.put(dataName, cursor.getString(i));
                i++;
            }
            JSONObject json = new JSONObject(map);
            try {
                beanObj = (T) parse(json.toString(), bean, beanPackage.getName());
            } catch (Exception e) {
                Log.d(TAG, e.toString());
                return null;
            }
            objectList.add(beanObj);
        }
        cursor.close();
        dbObj.close();
        return objectList;
    }

    /**
     *
     * @param sqlId SQLiteDatabase object
     * @param bindParams old version value
     * 
     * @return int
     */
    public int execute(String sqlId, Map<String, Object> bindParams) {
        getDbObject();
        int row = 0;
        int pointer = context.getResources().getIdentifier(sqlId, "string", context.getPackageName());
        if (pointer == 0) {
            Log.e(TAG, "undefined sql id");
            return row;
        }
        String sql = context.getResources().getString(pointer);
        if (bindParams != null) {
            Iterator<String> mapIterator = bindParams.keySet().iterator();
            while (mapIterator.hasNext()) {
                String key = mapIterator.next();
                Object value = bindParams.get(key);
                sql = sql.replaceAll("#" + key.toLowerCase() + "#",
                        value == null ? null : "'" + value.toString() + "'");
            }
        }
        if (sql.indexOf('#') != -1) {
            Log.e(TAG, "undefined parameter");
            return row;
        }
        try {
            dbObj.execSQL(sql);
            dbObj.close();
            row += 1;
        } catch (SQLException e) {
            return row;
        }
        return row;
    }

    /**
     * SQLiteDatabase Object
     * 
     * @return SQLiteDatabase SQLiteDatabase Object
     */
    private SQLiteDatabase getDbObject() {
        if (dbObj == null || !dbObj.isOpen()) {
            dbObj = getWritableDatabase();
        }
        return dbObj;
    }

    /**
     * JsonString
     *  
     * @param jsonStr JSON String
     * @param beanClass Bean class 
     * @param basePackage Base package name which includes all Bean classes 
     * @return Object Bean
     * @throws Exception
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private Object parse(String jsonStr, Class beanClass, String basePackage) throws Exception {
        Object obj = null;
        JSONObject jsonObj = new JSONObject(jsonStr);
        // Check bean object
        if (beanClass == null) {
            Log.d(TAG, "Bean class is null");
            return null;
        }
        // Read Class member fields
        Field[] props = beanClass.getDeclaredFields();
        if (props == null || props.length == 0) {
            Log.d(TAG, "Class" + beanClass.getName() + " has no fields");
            return null;
        }
        // Create instance of this Bean class
        obj = beanClass.newInstance();
        // Set value of each member variable of this object
        for (int i = 0; i < props.length; i++) {
            String fieldName = props[i].getName();
            // Skip public and static fields
            if (props[i].getModifiers() == (Modifier.PUBLIC | Modifier.STATIC)) {
                continue;
            }
            // Date Type of Field 
            Class type = props[i].getType();
            String typeName = type.getName();
            // Check for Custom type
            if (typeName.equals("int")) {
                Class[] parms = { type };
                Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
                m.setAccessible(true);
                // Set value
                try {
                    m.invoke(obj, jsonObj.getInt(fieldName));
                } catch (Exception ex) {
                    Log.d(TAG, ex.getMessage());
                }
            } else if (typeName.equals("long")) {
                Class[] parms = { type };
                Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
                m.setAccessible(true);
                // Set value
                try {
                    m.invoke(obj, jsonObj.getLong(fieldName));
                } catch (Exception ex) {
                    Log.d(TAG, ex.getMessage());
                }
            } else if (typeName.equals("java.lang.String")) {
                Class[] parms = { type };
                Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
                m.setAccessible(true);
                // Set value
                try {
                    m.invoke(obj, jsonObj.getString(fieldName));
                } catch (Exception ex) {
                    Log.d(TAG, ex.getMessage());
                }
            } else if (typeName.equals("double")) {
                Class[] parms = { type };
                Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
                m.setAccessible(true);
                // Set value
                try {
                    m.invoke(obj, jsonObj.getDouble(fieldName));
                } catch (Exception ex) {
                    Log.d(TAG, ex.getMessage());
                }
            } else if (type.getName().equals(List.class.getName())
                    || type.getName().equals(ArrayList.class.getName())) {
                // Find out the Generic
                String generic = props[i].getGenericType().toString();
                if (generic.indexOf("<") != -1) {
                    String genericType = generic.substring(generic.lastIndexOf("<") + 1, generic.lastIndexOf(">"));
                    if (genericType != null) {
                        JSONArray array = null;
                        try {
                            array = jsonObj.getJSONArray(fieldName);
                        } catch (Exception ex) {
                            Log.d(TAG, ex.getMessage());
                            array = null;
                        }
                        if (array == null) {
                            continue;
                        }
                        ArrayList arrayList = new ArrayList();
                        for (int j = 0; j < array.length(); j++) {
                            arrayList.add(parse(array.getJSONObject(j).toString(), Class.forName(genericType),
                                    basePackage));
                        }
                        // Set value
                        Class[] parms = { type };
                        Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
                        m.setAccessible(true);
                        m.invoke(obj, arrayList);
                    }
                } else {
                    // No generic defined
                    generic = null;
                }
            } else if (typeName.startsWith(basePackage)) {
                Class[] parms = { type };
                Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
                m.setAccessible(true);
                // Set value
                try {
                    JSONObject customObj = jsonObj.getJSONObject(fieldName);
                    if (customObj != null) {
                        m.invoke(obj, parse(customObj.toString(), type, basePackage));
                    }
                } catch (JSONException ex) {
                    Log.d(TAG, ex.getMessage());
                }
            } else {
                // Skip
                Log.d(TAG, "Field " + fieldName + "#" + typeName + " is skip");
            }
        }
        return obj;
    }

    /**
     * BeanClass fields
     * @param fieldName
     * @param type
     * @return String MethodName
     */
    private String getBeanMethodName(String fieldName, int type) {
        if (fieldName == null || fieldName == "") {
            return "";
        }
        String methodName = "";
        if (type == 0) {
            methodName = "get";
        } else {
            methodName = "set";
        }
        methodName += fieldName.substring(0, 1).toUpperCase();
        if (fieldName.length() == 1) {
            return methodName;
        }
        methodName += fieldName.substring(1);
        return methodName;
    }

    /**
     * Database
     * @param targetStr database
     * @return String bean data
     */
    private String chgDataName(String targetStr) {
        Pattern p = Pattern.compile("_([a-z])");
        Matcher m = p.matcher(targetStr.toLowerCase());

        StringBuffer sb = new StringBuffer(targetStr.length());
        while (m.find()) {
            m.appendReplacement(sb, m.group(1).toUpperCase());
        }
        m.appendTail(sb);
        return sb.toString();
    }

    /**
     * 
     * @return boolean Upgrade
     */
    ;

    public boolean isUpgrade() {
        // log and set upgrade flag
        Log.d(TAG, String.valueOf(getDbObject().getVersion()));
        return isUpgrade;
    }
}