de.geeksfactory.opacclient.storage.AccountDataSource.java Source code

Java tutorial

Introduction

Here is the source code for de.geeksfactory.opacclient.storage.AccountDataSource.java

Source

/**
 * Copyright (C) 2013 by Raphael Michel under the MIT license:
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package de.geeksfactory.opacclient.storage;

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

import org.joda.time.DateTime;
import org.joda.time.LocalDate;

import java.util.ArrayList;
import java.util.List;

import de.geeksfactory.opacclient.objects.Account;
import de.geeksfactory.opacclient.objects.AccountData;
import de.geeksfactory.opacclient.objects.AccountItem;
import de.geeksfactory.opacclient.objects.LentItem;
import de.geeksfactory.opacclient.objects.ReservedItem;
import de.geeksfactory.opacclient.objects.SearchResult;
import de.geeksfactory.opacclient.reminder.Alarm;

public class AccountDataSource {
    // Database fields
    private SQLiteDatabase database;
    private String[] allColumns = AccountDatabase.COLUMNS;

    public AccountDataSource(Context context) {
        AccountDatabase dbHelper = AccountDatabase.getInstance(context);
        database = dbHelper.getWritableDatabase();
        // we do not need to close the database, as only one instance is created
        // see e.g. http://stackoverflow
        // .com/questions/4547461/closing-the-database-in-a-contentprovider/12715032#12715032
    }

    public long addAccount(Account acc) {
        ContentValues values = new ContentValues();
        values.put("bib", acc.getLibrary());
        values.put("label", acc.getLabel());
        values.put("name", acc.getName());
        values.put("password", acc.getPassword());
        return database.insert("accounts", null, values);
    }

    public void update(Account acc) {
        ContentValues values = new ContentValues();
        values.put("bib", acc.getLibrary());
        values.put("label", acc.getLabel());
        values.put("name", acc.getName());
        values.put("password", acc.getPassword());
        values.put("passwordValid", acc.isPasswordKnownValid() ? 1 : 0);
        database.update("accounts", values, "id = ?", new String[] { acc.getId() + "" });
    }

    public long addAccount(String bib, String label, String name, String password) {
        ContentValues values = new ContentValues();
        values.put("bib", bib);
        values.put("label", label);
        values.put("name", name);
        values.put("password", password);
        return database.insert("accounts", null, values);
    }

    public List<Account> getAllAccounts() {
        List<Account> accs = new ArrayList<>();
        Cursor cursor = database.query("accounts", allColumns, null, null, null, null, null);

        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            Account acc = cursorToAccount(cursor);
            accs.add(acc);
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();
        return accs;
    }

    public List<Account> getAllAccounts(String bib) {
        List<Account> accs = new ArrayList<>();
        String[] selA = { bib };
        Cursor cursor = database.query("accounts", allColumns, "bib = ?", selA, null, null, null);

        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            Account acc = cursorToAccount(cursor);
            accs.add(acc);
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();
        return accs;
    }

    public List<Account> getAccountsWithPassword() {
        List<Account> accs = new ArrayList<>();

        Cursor cursor = database.query("accounts", allColumns,
                "name is not null AND name != '' AND password is not null", null, null, null, null);

        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            Account acc = cursorToAccount(cursor);
            accs.add(acc);
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();
        return accs;
    }

    public Account getAccount(long id) {
        String[] selA = { "" + id };
        Cursor cursor = database.query("accounts", allColumns, "id = ?", selA, null, null, null);
        Account acc = null;

        cursor.moveToFirst();
        if (!cursor.isAfterLast()) {
            acc = cursorToAccount(cursor);
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();
        return acc;
    }

    private Account cursorToAccount(Cursor cursor) {
        Account acc = new Account();
        acc.setId(cursor.getLong(0));
        acc.setLibrary(cursor.getString(1));
        acc.setLabel(cursor.getString(2));
        acc.setName(cursor.getString(3));
        acc.setPassword(cursor.getString(4));
        acc.setCached(cursor.getLong(5));
        acc.setPasswordKnownValid(cursor.getLong(9) > 0);
        return acc;
    }

    public void remove(Account acc) {
        deleteAccountData(acc);
        String[] selA = { "" + acc.getId() };
        database.delete("accounts", "id=?", selA);
    }

    public int getExpiring(Account account, int tolerance) {
        String[] selA = { String.valueOf(account.getId()) };
        Cursor cursor = database.query(AccountDatabase.TABLENAME_LENT, new String[] { "COUNT(*)" },
                "account = ? AND date(deadline) < date('now','-" + tolerance + " days')", selA, null, null, null);
        cursor.moveToFirst();
        int result = cursor.getInt(0);
        cursor.close();
        return result;
    }

    public AccountData getCachedAccountData(Account account) {
        AccountData adata = new AccountData(account.getId());

        List<LentItem> lent = new ArrayList<>();
        String[] selectionArgs = { "" + account.getId() };
        Cursor cursor = database.query(AccountDatabase.TABLENAME_LENT, AccountDatabase.COLUMNS_LENT, "account = ?",
                selectionArgs, null, null, null);
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            LentItem entry = cursorToLentItem(cursor);
            lent.add(entry);
            cursor.moveToNext();
        }
        cursor.close();
        adata.setLent(lent);

        List<ReservedItem> res = new ArrayList<>();
        cursor = database.query(AccountDatabase.TABLENAME_RESERVATION, AccountDatabase.COLUMNS_RESERVATIONS,
                "account = ?", selectionArgs, null, null, null);
        cursor.moveToFirst();

        while (!cursor.isAfterLast()) {
            ReservedItem entry = cursorToReservedItem(cursor);
            res.add(entry);
            cursor.moveToNext();
        }
        cursor.close();
        adata.setReservations(res);

        String[] selA = { "" + account.getId() };
        cursor = database.query("accounts", new String[] { "pendingFees", "validUntil", "warning" }, "id = ?", selA,
                null, null, null);
        cursor.moveToFirst();
        if (!cursor.isAfterLast()) {
            adata.setPendingFees(cursor.getString(0));
            adata.setValidUntil(cursor.getString(1));
            adata.setWarning(cursor.getString(2));
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();

        return adata;
    }

    private LentItem cursorToLentItem(Cursor cursor) {
        LentItem item = new LentItem();
        setAccountItemAttributes(cursor, item);
        item.setBarcode(cursor.getString(7));
        item.setDeadline(cursor.getString(8));
        item.setHomeBranch(cursor.getString(9));
        item.setLendingBranch(cursor.getString(10));
        item.setProlongData(cursor.getString(11));
        item.setRenewable(cursor.getInt(12) == 1);
        item.setDownloadData(cursor.getString(13));
        item.setEbook(cursor.getInt(14) == 1);
        return item;
    }

    private ReservedItem cursorToReservedItem(Cursor cursor) {
        ReservedItem item = new ReservedItem();
        setAccountItemAttributes(cursor, item);
        item.setReadyDate(cursor.getString(7));
        item.setExpirationDate(cursor.getString(8));
        item.setBranch(cursor.getString(9));
        item.setCancelData(cursor.getString(10));
        item.setBookingData(cursor.getString(11));
        return item;
    }

    private void setAccountItemAttributes(Cursor cursor, AccountItem item) {
        item.setDbId(cursor.getLong(0));
        item.setAccount(cursor.getLong(1));
        item.setTitle(cursor.getString(2));
        item.setAuthor(cursor.getString(3));
        item.setFormat(cursor.getString(4));
        item.setId(cursor.getString(5));
        item.setStatus(cursor.getString(6));
        String mediatype = cursor.getString(cursor.getColumnIndex("mediatype"));
        item.setMediaType(mediatype != null ? SearchResult.MediaType.valueOf(mediatype) : null);
        item.setCover(cursor.getString(cursor.getColumnIndex("cover")));
    }

    private ContentValues lentItemToContentValues(LentItem item, long accountId) {
        ContentValues cv = new ContentValues();
        setAccountItemAttributes(item, cv, accountId);
        putOrNull(cv, "barcode", item.getBarcode());
        putOrNull(cv, "deadline", item.getDeadline());
        putOrNull(cv, "homebranch", item.getHomeBranch());
        putOrNull(cv, "lending_branch", item.getLendingBranch());
        putOrNull(cv, "prolong_data", item.getProlongData());
        cv.put("renewable", item.isRenewable() ? 1 : 0);
        putOrNull(cv, "download_data", item.getDownloadData());
        cv.put("ebook", item.isEbook() ? 1 : 0);
        return cv;
    }

    private ContentValues reservedItemToContentValues(ReservedItem item, long accountId) {
        ContentValues cv = new ContentValues();
        setAccountItemAttributes(item, cv, accountId);
        putOrNull(cv, "ready", item.getReadyDate());
        putOrNull(cv, "expiration", item.getExpirationDate());
        putOrNull(cv, "branch", item.getBranch());
        putOrNull(cv, "cancel_data", item.getCancelData());
        putOrNull(cv, "booking_data", item.getBookingData());
        return cv;
    }

    private void setAccountItemAttributes(AccountItem item, ContentValues cv, long accountId) {
        if (item.getDbId() != null)
            cv.put("id", item.getDbId());
        cv.put("account", accountId);
        putOrNull(cv, "title", item.getTitle());
        putOrNull(cv, "author", item.getAuthor());
        putOrNull(cv, "format", item.getFormat());
        putOrNull(cv, "itemid", item.getId());
        putOrNull(cv, "status", item.getStatus());
        putOrNull(cv, "cover", item.getCover());
        putOrNull(cv, "mediatype", item.getMediaType() != null ? item.getMediaType().toString() : null);
    }

    private void putOrNull(ContentValues cv, String key, LocalDate value) {
        if (value != null) {
            cv.put(key, value.toString());
        } else {
            cv.putNull(key);
        }
    }

    private void putOrNull(ContentValues cv, String key, String value) {
        if (value != null) {
            cv.put(key, value);
        } else {
            cv.putNull(key);
        }
    }

    public void invalidateCachedData() {
        database.delete(AccountDatabase.TABLENAME_LENT, null, null);
        database.delete(AccountDatabase.TABLENAME_RESERVATION, null, null);
        database.delete(AccountDatabase.TABLENAME_ALARMS, null, null);
        ContentValues update = new ContentValues();
        update.put("cached", 0);
        update.put("pendingFees", (String) null);
        update.put("validUntil", (String) null);
        update.put("warning", (String) null);
        database.update(AccountDatabase.TABLENAME_ACCOUNTS, update, null, null);
    }

    public void deleteAccountData(Account account) {
        database.delete(AccountDatabase.TABLENAME_LENT, "account = ?", new String[] { "" + account.getId() });
        database.delete(AccountDatabase.TABLENAME_RESERVATION, "account = ?",
                new String[] { "" + account.getId() });

    }

    public void invalidateCachedAccountData(Account account) {
        ContentValues update = new ContentValues();
        update.put("cached", 0);
        database.update(AccountDatabase.TABLENAME_ACCOUNTS, update, "id = ?",
                new String[] { "" + account.getId() });
    }

    public long getCachedAccountDataTime(Account account) {
        return getAccount(account.getId()).getCached();
    }

    public void storeCachedAccountData(Account account, AccountData adata) {
        if (adata == null) {
            return;
        }

        long time = System.currentTimeMillis();
        ContentValues update = new ContentValues();
        update.put("cached", time);
        update.put("pendingFees", adata.getPendingFees());
        update.put("validUntil", adata.getValidUntil());
        update.put("warning", adata.getWarning());
        database.update(AccountDatabase.TABLENAME_ACCOUNTS, update, "id = ?",
                new String[] { "" + account.getId() });

        database.delete(AccountDatabase.TABLENAME_LENT, "account = ?", new String[] { "" + account.getId() });
        for (LentItem entry : adata.getLent()) {
            ContentValues insertmapping = lentItemToContentValues(entry, account.getId());
            database.insert(AccountDatabase.TABLENAME_LENT, null, insertmapping);
        }

        database.delete(AccountDatabase.TABLENAME_RESERVATION, "account = ?",
                new String[] { "" + account.getId() });
        for (ReservedItem entry : adata.getReservations()) {
            ContentValues insertmapping = reservedItemToContentValues(entry, account.getId());
            database.insert(AccountDatabase.TABLENAME_RESERVATION, null, insertmapping);
        }
    }

    public List<LentItem> getAllLentItems() {
        List<LentItem> items = new ArrayList<>();
        Cursor cursor = database.query(AccountDatabase.TABLENAME_LENT, AccountDatabase.COLUMNS_LENT, null, null,
                null, null, null);
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            LentItem item = cursorToLentItem(cursor);
            items.add(item);
            cursor.moveToNext();
        }
        cursor.close();
        return items;
    }

    public LentItem getLentItem(long id) {
        String[] selA = { "" + id };
        Cursor cursor = database.query(AccountDatabase.TABLENAME_LENT, AccountDatabase.COLUMNS_LENT, "id = ?", selA,
                null, null, null);
        LentItem item = null;
        cursor.moveToFirst();
        if (!cursor.isAfterLast()) {
            item = cursorToLentItem(cursor);
        }
        // Make sure to close the cursor
        cursor.close();
        return item;
    }

    public List<LentItem> getLentItems(long[] ids) {
        List<LentItem> items = new ArrayList<>();
        Cursor cursor = database.query(AccountDatabase.TABLENAME_LENT, AccountDatabase.COLUMNS_LENT,
                "id IN(" + joinLongs(ids, ",") + ")", null, null, null, null);
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            LentItem item = cursorToLentItem(cursor);
            items.add(item);
            cursor.moveToNext();
        }
        cursor.close();
        return items;
    }

    public List<Account> getAccountsWithPassword(String ident) {
        List<Account> accs = new ArrayList<>();

        Cursor cursor = database.query("accounts", allColumns,
                "name is not null AND name != '' AND password is not null AND bib = ?", new String[] { ident },
                null, null, null);

        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            Account acc = cursorToAccount(cursor);
            accs.add(acc);
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();
        return accs;
    }

    public long addAlarm(LocalDate deadline, long[] media, DateTime alarmTime) {
        for (long mid : media) {
            if (getLentItem(mid) == null) {
                throw new DataIntegrityException("Cannot add alarm with deadline " + deadline.toString()
                        + " that has dependency on the non-existing media item " + mid);
            }
        }

        ContentValues values = new ContentValues();
        values.put("deadline", deadline.toString());
        values.put("media", joinLongs(media, ","));
        values.put("alarm", alarmTime.toString());
        values.put("notified", 0);
        values.put("finished", 0);
        return database.insert(AccountDatabase.TABLENAME_ALARMS, null, values);
    }

    public void updateAlarm(Alarm alarm) {
        for (long mid : alarm.media) {
            if (getLentItem(mid) == null) {
                throw new DataIntegrityException("Cannot update alarm with deadline " + alarm.deadline.toString()
                        + " that has dependency on the non-existing media item " + mid);
            }
        }

        ContentValues values = new ContentValues();
        values.put("deadline", alarm.deadline.toString());
        values.put("media", joinLongs(alarm.media, ","));
        values.put("alarm", alarm.notificationTime.toString());
        values.put("notified", alarm.notified ? 1 : 0);
        values.put("finished", alarm.finished ? 1 : 0);
        database.update(AccountDatabase.TABLENAME_ALARMS, values, "id = ?", new String[] { alarm.id + "" });
    }

    public void resetNotifiedOnAllAlarams() {
        ContentValues values = new ContentValues();
        values.put("notified", 0);
        database.update(AccountDatabase.TABLENAME_ALARMS, values, "finished = 0 AND notified = 1", null);
    }

    public Alarm getAlarmByDeadline(LocalDate deadline) {
        String[] selA = { deadline.toString() };
        Cursor cursor = database.query(AccountDatabase.TABLENAME_ALARMS, AccountDatabase.COLUMNS_ALARMS,
                "deadline = ?", selA, null, null, null);
        Alarm item = null;
        cursor.moveToFirst();
        if (!cursor.isAfterLast()) {
            item = cursorToAlarm(cursor);
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();
        return item;
    }

    public Alarm getAlarm(long id) {
        String[] selA = { "" + id };
        Cursor cursor = database.query(AccountDatabase.TABLENAME_ALARMS, AccountDatabase.COLUMNS_ALARMS, "id = ?",
                selA, null, null, null);
        Alarm item = null;
        cursor.moveToFirst();
        if (!cursor.isAfterLast()) {
            item = cursorToAlarm(cursor);
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();
        return item;
    }

    public List<Alarm> getAllAlarms() {
        List<Alarm> alarms = new ArrayList<>();
        Cursor cursor = database.query(AccountDatabase.TABLENAME_ALARMS, AccountDatabase.COLUMNS_ALARMS, null, null,
                null, null, null);

        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            Alarm alarm = cursorToAlarm(cursor);
            alarms.add(alarm);
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();
        return alarms;
    }

    public void clearAlarms() {
        database.delete(AccountDatabase.TABLENAME_ALARMS, null, null);
    }

    private Alarm cursorToAlarm(Cursor cursor) {
        Alarm alarm = new Alarm();
        alarm.id = cursor.getLong(0);
        alarm.deadline = new LocalDate(cursor.getString(1));
        alarm.media = splitLongs(cursor.getString(2), ",");
        alarm.notificationTime = new DateTime(cursor.getString(3));
        alarm.notified = cursor.getInt(4) == 1;
        alarm.finished = cursor.getInt(5) == 1;
        return alarm;
    }

    public void removeAlarm(Alarm alarm) {
        String[] selA = { "" + alarm.id };
        database.delete(AccountDatabase.TABLENAME_ALARMS, "id=?", selA);
    }

    private String joinLongs(long[] longs, String separator) {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (long l : longs) {
            if (first) {
                first = false;
            } else {
                sb.append(separator);
            }
            sb.append(l);
        }
        return sb.toString();
    }

    private long[] splitLongs(String string, String separator) {
        String[] strings = string.split(separator);
        long[] longs = new long[strings.length];
        for (int i = 0; i < strings.length; i++) {
            longs[i] = Long.valueOf(strings[i]);
        }
        return longs;
    }
}