de.azapps.mirakel.model.list.ListMirakel.java Source code

Java tutorial

Introduction

Here is the source code for de.azapps.mirakel.model.list.ListMirakel.java

Source

/*******************************************************************************
 * Mirakel is an Android App for managing your ToDo-Lists
 * 
 * Copyright (c) 2013 Anatolij Zelenin, Georg Semmler.
 * 
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

package de.azapps.mirakel.model.list;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

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

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import de.azapps.mirakel.Mirakel;
import de.azapps.mirakel.helper.Log;
import de.azapps.mirakel.helper.MirakelPreferences;
import de.azapps.mirakel.helper.UndoHistory;
import de.azapps.mirakel.model.DatabaseHelper;
import de.azapps.mirakel.model.account.AccountMirakel;
import de.azapps.mirakel.model.task.Task;
import de.azapps.mirakel.sync.SyncAdapter;
import de.azapps.mirakel.sync.SyncAdapter.SYNC_STATE;
import de.azapps.mirakelandroid.R;

/**
 * @author az
 * 
 */
public class ListMirakel extends ListBase {
    public static final short SORT_BY_OPT = 0, SORT_BY_DUE = 1, SORT_BY_PRIO = 2, SORT_BY_ID = 3,
            SORT_BY_REVERT_DEFAULT = 4;
    public static final String TABLE = "lists";

    public boolean isSpecialList() {
        return false;
    }

    // private static final String TAG = "ListMirakel";

    /**
     * Create an empty list
     */
    /*
     * private ListMirakel() { }
     */

    protected ListMirakel(int id, String name, short sort_by, String created_at, String updated_at,
            SYNC_STATE sync_state, int lft, int rgt, int color, AccountMirakel account) {
        super(id, name, sort_by, created_at, updated_at, sync_state, lft, rgt, color, account);
    }

    ListMirakel(int id, String name) {
        super(id, name);
    }

    private ListMirakel() {
        super();
    }

    protected ListMirakel(int id, String name, short sort_by, String created_at, String updated_at,
            SYNC_STATE sync_state, int lft, int rgt, int color, int account) {
        super(id, name, sort_by, created_at, updated_at, sync_state, lft, rgt, color, account);
    }

    /**
     * Update the List in the Database
     * 
     * @param list
     *            The List
     */
    public void save() {
        save(true);
    }

    public void save(boolean log) {
        SharedPreferences.Editor editor = MirakelPreferences.getEditor();
        // TODO implement for specialLists
        if (getId() > 0) {
            database.beginTransaction();
            setSyncState(getSyncState() == SYNC_STATE.ADD || getSyncState() == SYNC_STATE.IS_SYNCED ? getSyncState()
                    : SYNC_STATE.NEED_SYNC);
            setUpdatedAt(new SimpleDateFormat(context.getString(R.string.dateTimeFormat), Locale.getDefault())
                    .format(new Date()));
            ContentValues values = getContentValues();
            if (log)
                UndoHistory.updateLog(ListMirakel.getList(getId()), context);
            database.update(ListMirakel.TABLE, values, DatabaseHelper.ID + " = " + getId(), null);
            database.setTransactionSuccessful();
            database.endTransaction();

        }
        editor.commit();
    }

    /**
     * Delete a List from the Database
     * 
     * @param list
     */
    public void destroy() {
        destroy(false);
    }

    public void destroy(boolean force) {
        if (!force)
            UndoHistory.updateLog(this, context);
        long id = getId();
        if (id <= 0)
            return;
        database.beginTransaction();
        try {
            if (getSyncState() == SYNC_STATE.ADD || force) {
                database.delete(Task.TABLE, Task.LIST_ID + " = " + id, null);
                database.delete(ListMirakel.TABLE, DatabaseHelper.ID + " = " + id, null);
            } else {
                ContentValues values = new ContentValues();
                values.put(SyncAdapter.SYNC_STATE, SYNC_STATE.DELETE.toInt());
                database.update(Task.TABLE, values, Task.LIST_ID + " = " + id, null);
                database.update(ListMirakel.TABLE, values, DatabaseHelper.ID + "=" + id, null);
            }
            database.rawQuery("UPDATE " + ListMirakel.TABLE + " SET " + LFT + "=" + LFT + "-2 WHERE " + LFT + ">"
                    + getLft() + "; UPDATE " + ListMirakel.TABLE + " SET " + RGT + "=" + RGT + "-2 WHERE " + LFT
                    + ">" + getRgt() + ";", null);
            database.setTransactionSuccessful();
        } catch (Exception e) {
            Log.wtf(TAG, "cannot remove List");
        } finally {
            database.endTransaction();
        }
    }

    /**
     * Count the tasks of that list
     * 
     * @return
     */
    public int countTasks() {
        Cursor c;
        String where;
        if (getId() < 0) {
            where = ((SpecialList) this).getWhereQuery(true);
        } else {

            where = Task.LIST_ID + " = " + getId();
        }
        c = Mirakel.getReadableDatabase()
                .rawQuery("Select count(" + DatabaseHelper.ID + ") from " + Task.TABLE + " where " + where
                        + (where.length() != 0 ? " and " : " ") + " " + Task.DONE + "=0 and not "
                        + SyncAdapter.SYNC_STATE + "=" + SYNC_STATE.DELETE, null);
        c.moveToFirst();
        if (c.getCount() > 0) {
            int n = c.getInt(0);
            c.close();
            return n;
        }
        c.close();
        return 0;
    }

    /**
     * Get all Tasks
     * 
     * @return
     */
    public List<Task> tasks() {
        return Task.getTasks(this, getSortBy(), false);
    }

    public String toJson() {
        String json = "{";
        json += "\"name\":\"" + getName() + "\",";
        json += "\"id\":" + getId() + ",";
        json += "\"created_at\":\"" + getCreatedAt() + "\",";
        json += "\"updated_at\":\"" + getName() + "\",";
        json += "\"lft\":" + getLft() + ",";
        json += "\"rgt\":" + getRgt() + ",";
        json += "\"sort_by\":" + getSortBy() + ",";
        json += "\"sync_state\":" + getSyncState() + "";
        json += "}";
        return json;
    }

    /**
     * Get all Tasks
     * 
     * @param showDone
     * @return
     */
    public List<Task> tasks(boolean showDone) {
        return Task.getTasks(this, getSortBy(), showDone);
    }

    // Static Methods

    private static SQLiteDatabase database;
    private static DatabaseHelper dbHelper;
    private static final String[] allColumns = { DatabaseHelper.ID, DatabaseHelper.NAME, SORT_BY,
            DatabaseHelper.CREATED_AT, DatabaseHelper.UPDATED_AT, SyncAdapter.SYNC_STATE, LFT, RGT, COLOR,
            ACCOUNT_ID };
    private static final String TAG = "ListMirakel";
    private static Context context;

    public static ListMirakel parseJson(JsonObject el) {
        ListMirakel t = null;
        JsonElement id = el.get("id");
        if (id != null)
            // use old List from db if existing
            t = ListMirakel.getList(id.getAsInt());
        if (t == null) {
            t = new ListMirakel();
        }
        JsonElement j = el.get("name");
        if (j != null)
            t.setName(j.getAsString());

        j = el.get("lft");
        if (j != null)
            t.setLft(j.getAsInt());

        j = el.get("rgt");
        if (j != null)
            t.setRgt(j.getAsInt());

        j = el.get("lft");
        if (j != null)
            t.setLft(j.getAsInt());

        j = el.get("updated_at");
        if (j != null) {
            t.setUpdatedAt(j.getAsString().replace(":", ""));
        }

        j = el.get("sort_by");
        if (j != null)
            t.setSortBy(j.getAsInt());

        return t;
    }

    /**
     * Initialize the Database and the preferences
     * 
     * @param context
     *            The Application-Context
     */
    public static void init(@SuppressWarnings("hiding") Context context) {
        ListMirakel.context = context;
        dbHelper = new DatabaseHelper(context);
        database = dbHelper.getWritableDatabase();
    }

    /**
     * Close the DatabaseConnection
     */
    public static void close() {
        dbHelper.close();
    }

    /**
     * Create and insert a new List
     * 
     * @param name
     * @return
     */
    public static ListMirakel newList(String name) {
        return newList(name, SORT_BY_OPT);
    }

    /**
     * Create and insert a new List
     * 
     * @param name
     *            Name of the List
     * @param sort_by
     *            the default sorting
     * @return new List
     */
    public static ListMirakel newList(String name, int sort_by) {
        return newList(name, sort_by, MirakelPreferences.getDefaultAccount());
    }

    public static ListMirakel newList(String name, int sort_by, AccountMirakel account) {
        ContentValues values = new ContentValues();
        values.put(DatabaseHelper.NAME, name);
        values.put(ACCOUNT_ID, account.getId());
        values.put(SORT_BY, sort_by);
        values.put(SyncAdapter.SYNC_STATE, SYNC_STATE.ADD.toInt());
        values.put(DatabaseHelper.CREATED_AT,
                new SimpleDateFormat(context.getString(R.string.dateTimeFormat), Locale.US).format(new Date()));
        values.put(DatabaseHelper.UPDATED_AT,
                new SimpleDateFormat(context.getString(R.string.dateTimeFormat), Locale.US).format(new Date()));
        values.put(RGT, 0);
        values.put(LFT, 0);
        database.beginTransaction();
        long insertId;
        insertId = database.insert(ListMirakel.TABLE, null, values);
        // Dirty workaround
        database.execSQL("update " + ListMirakel.TABLE + " SET lft=(SELECT MAX(" + RGT + ") from " + TABLE + ")+1, "
                + RGT + "=(SELECT MAX(" + RGT + ") from lists)+2 where " + DatabaseHelper.ID + "=" + insertId);
        database.setTransactionSuccessful();
        database.endTransaction();

        Cursor cursor = database.query(ListMirakel.TABLE, allColumns, DatabaseHelper.ID + " = " + insertId, null,
                null, null, null);
        cursor.moveToFirst();
        ListMirakel newList = cursorToList(cursor);
        cursor.close();
        UndoHistory.logCreate(newList, context);
        return newList;
    }

    /**
     * Create a List from a Cursor
     * 
     * @param cursor
     * @return
     */
    private static ListMirakel cursorToList(Cursor cursor) {
        int i = 0;
        int id = cursor.getInt(i++);
        ListMirakel list = new ListMirakel(id, cursor.getString(i++), cursor.getShort(i++), cursor.getString(i++),
                cursor.getString(i++), SYNC_STATE.parseInt(cursor.getInt(i++)), cursor.getInt(i++),
                cursor.getInt(i++), cursor.getInt(i++), cursor.getInt(i++));
        return list;
    }

    public static ListMirakel findByName(String name) {
        String[] args = { name };
        Cursor cursor = database.query(ListMirakel.TABLE, allColumns, DatabaseHelper.NAME + "=?", args, null, null,
                null);
        cursor.moveToFirst();
        if (cursor.getCount() != 0) {
            ListMirakel t = cursorToList(cursor);
            cursor.close();
            return t;
        }
        return null;
    }

    public static ListMirakel safeGetList(int listId) {
        ListMirakel l = getList(listId);
        if (l == null) {
            l = safeFirst(context);
        }
        return l;
    }

    public static ListMirakel getList(int listId) {
        if (listId < 0)
            return SpecialList.getSpecialList(-listId);

        Cursor cursor = database.query(ListMirakel.TABLE, allColumns, DatabaseHelper.ID + "='" + listId + "'", null,
                null, null, null);
        if (cursor.moveToFirst()) {
            ListMirakel t = cursorToList(cursor);
            cursor.close();
            return t;
        }
        cursor.close();
        return null;
    }

    public static int count() {
        Cursor c = database.rawQuery("Select count(" + DatabaseHelper.ID + ") from " + TABLE, null);
        c.moveToFirst();
        int count = c.getInt(0);
        c.close();
        return count;
    }

    /**
     * Get the first List
     * 
     * @return List
     */
    public static ListMirakel first() {
        Cursor cursor = database.query(ListMirakel.TABLE, allColumns,
                "not " + SyncAdapter.SYNC_STATE + "=" + SYNC_STATE.DELETE, null, null, null, LFT + " ASC");
        ListMirakel list = null;
        cursor.moveToFirst();
        if (!cursor.isAfterLast()) {
            list = cursorToList(cursor);
            cursor.moveToNext();
        }
        cursor.close();
        return list;
    }

    public static ListMirakel safeFirst(Context ctx) {
        ListMirakel s = first();
        if (s == null) {
            s = ListMirakel.newList(ctx.getString(R.string.inbox));
        }
        return s;
    }

    /**
     * Get the last List
     * 
     * @return List
     */
    public static ListMirakel last() {
        Cursor cursor = database.query(ListMirakel.TABLE, allColumns,
                "not " + SyncAdapter.SYNC_STATE + "=" + SYNC_STATE.DELETE, null, null, null,
                DatabaseHelper.ID + " DESC");
        ListMirakel list = null;
        cursor.moveToFirst();
        if (!cursor.isAfterLast()) {
            list = cursorToList(cursor);
            cursor.moveToNext();
        }
        cursor.close();
        return list;
    }

    /**
     * Get all Lists in the Database
     * 
     * @return List of Lists
     */
    public static List<ListMirakel> all() {
        return all(true);
    }

    public static List<ListMirakel> all(boolean withSpecial) {
        List<ListMirakel> lists = new ArrayList<ListMirakel>();

        if (withSpecial) {
            List<SpecialList> slists = SpecialList.allSpecial();
            for (SpecialList slist : slists) {
                lists.add(slist);
            }
        }

        Cursor cursor = database.rawQuery("  SELECT n.*, " + "COUNT(*)-1 AS level " + "FROM " + ListMirakel.TABLE
                + " AS n, " + ListMirakel.TABLE + " p " + "WHERE n." + LFT + " BETWEEN p." + LFT + " AND p." + RGT
                + " " + " and not n." + SyncAdapter.SYNC_STATE + "=" + SYNC_STATE.DELETE + " GROUP BY n." + LFT
                + " " + "ORDER BY n." + LFT + ";", null);
        // query(ListMirakel.TABLE, allColumns,
        // "not sync_state=" + SYNC_STATE.DELETE, null, "lft",
        // null, null);
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            ListMirakel list = cursorToList(cursor);
            lists.add(list);
            cursor.moveToNext();
        }
        cursor.close();
        return lists;
    }

    /**
     * Get Lists by a sync state
     * 
     * @param state
     * @see Mirakel.SYNC_STATE*
     * @return
     */
    public static List<ListMirakel> bySyncState(SYNC_STATE state) {

        Cursor c = database.query(ListMirakel.TABLE, allColumns, SyncAdapter.SYNC_STATE + "=" + state, null, null,
                null, null);
        c.moveToFirst();
        List<ListMirakel> lists = cursorToListList(c);
        c.close();
        return lists;
    }

    public static List<ListMirakel> byAccount(AccountMirakel a) {
        Cursor c = database.query(ListMirakel.TABLE, allColumns, ACCOUNT_ID + "=" + a.getId(), null, null, null,
                null);
        c.moveToFirst();
        List<ListMirakel> lists = cursorToListList(c);
        c.close();
        return lists;
    }

    private static List<ListMirakel> cursorToListList(Cursor c) {
        List<ListMirakel> lists = new ArrayList<ListMirakel>();
        while (!c.isAfterLast()) {
            lists.add(cursorToList(c));
            c.moveToNext();
        }
        return lists;
    }

    public static ListMirakel getSafeDefaultList() {
        ListMirakel list = MirakelPreferences.getImportDefaultList(true);
        return list;
    }

    public static List<ListMirakel> getListsForAccount(AccountMirakel account) {
        if (account == null || !account.isEnabeld()) {
            return new ArrayList<ListMirakel>();
        }
        Cursor c = database.query(TABLE, allColumns, "NOT " + SyncAdapter.SYNC_STATE + "=" + SYNC_STATE.DELETE
                + " and " + ACCOUNT_ID + "=" + account.getId(), null, null, null, null);
        c.moveToFirst();
        List<ListMirakel> list = cursorToListList(c);
        c.close();
        return list;
    }

    public static ListMirakel getInboxList(AccountMirakel account) {
        Cursor c = database.query(TABLE, allColumns, DatabaseHelper.NAME + "='" + context.getString(R.string.inbox)
                + "' and " + ACCOUNT_ID + "=" + account.getId(), null, null, null, null);
        c.moveToFirst();
        if (c.getCount() > 0) {
            ListMirakel l = cursorToList(c);
            c.close();
            return l;
        }
        return newList(context.getString(R.string.inbox), SORT_BY_OPT, account);
    }

}