package org.gnucash.android.db.adapter; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteStatement; import android.support.annotation.NonNull; import android.util.Pair; import org.gnucash.android.app.GnuCashApplication; import org.gnucash.android.model.Price; import org.gnucash.android.util.TimestampHelper; import static org.gnucash.android.db.DatabaseSchema.PriceEntry; /** * Database adapter for prices */ public class PricesDbAdapter extends DatabaseAdapter<Price> { /** * Opens the database adapter with an existing database * @param db SQLiteDatabase object */ public PricesDbAdapter(SQLiteDatabase db) { super(db, PriceEntry.TABLE_NAME, new String[]{ PriceEntry.COLUMN_COMMODITY_UID, PriceEntry.COLUMN_CURRENCY_UID, PriceEntry.COLUMN_DATE, PriceEntry.COLUMN_SOURCE, PriceEntry.COLUMN_TYPE, PriceEntry.COLUMN_VALUE_NUM, PriceEntry.COLUMN_VALUE_DENOM }); } public static PricesDbAdapter getInstance(){ return GnuCashApplication.getPricesDbAdapter(); } @Override protected @NonNull SQLiteStatement setBindings(@NonNull SQLiteStatement stmt, @NonNull final Price price) { stmt.clearBindings(); stmt.bindString(1, price.getCommodityUID()); stmt.bindString(2, price.getCurrencyUID()); stmt.bindString(3, price.getDate().toString()); if (price.getSource() != null) { stmt.bindString(4, price.getSource()); } if (price.getType() != null) { stmt.bindString(5, price.getType()); } stmt.bindLong(6, price.getValueNum()); stmt.bindLong(7, price.getValueDenom()); stmt.bindString(8, price.getUID()); return stmt; } @Override public Price buildModelInstance(@NonNull final Cursor cursor) { String commodityUID = cursor.getString(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_COMMODITY_UID)); String currencyUID = cursor.getString(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_CURRENCY_UID)); String dateString = cursor.getString(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_DATE)); String source = cursor.getString(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_SOURCE)); String type = cursor.getString(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_TYPE)); long valueNum = cursor.getLong(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_VALUE_NUM)); long valueDenom = cursor.getLong(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_VALUE_DENOM)); Price price = new Price(commodityUID, currencyUID); price.setDate(TimestampHelper.getTimestampFromUtcString(dateString)); price.setSource(source); price.setType(type); price.setValueNum(valueNum); price.setValueDenom(valueDenom); populateBaseModelAttributes(cursor, price); return price; } /** * Get the price for commodity / currency pair. * The price can be used to convert from one commodity to another. The 'commodity' is the origin and the 'currency' is the target for the conversion. * * <p>Pair is used instead of Price object because we must sometimes invert the commodity/currency in DB, * rendering the Price UID invalid.</p> * * @param commodityUID GUID of the commodity which is starting point for conversion * @param currencyUID GUID of target commodity for the conversion * * @return The numerator/denominator pair for commodity / currency pair */ public Pair<Long, Long> getPrice(@NonNull String commodityUID, @NonNull String currencyUID) { Pair<Long, Long> pairZero = new Pair<>(0L, 0L); if (commodityUID.equals(currencyUID)) { return new Pair<Long, Long>(1L, 1L); } Cursor cursor = mDb.query(PriceEntry.TABLE_NAME, null, // the commodity and currency can be swapped "( " + PriceEntry.COLUMN_COMMODITY_UID + " = ? AND " + PriceEntry.COLUMN_CURRENCY_UID + " = ? ) OR ( " + PriceEntry.COLUMN_COMMODITY_UID + " = ? AND " + PriceEntry.COLUMN_CURRENCY_UID + " = ? )", new String[]{commodityUID, currencyUID, currencyUID, commodityUID}, null, null, // only get the latest price PriceEntry.COLUMN_DATE + " DESC", "1"); try { if (cursor.moveToNext()) { String commodityUIDdb = cursor.getString(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_COMMODITY_UID)); long valueNum = cursor.getLong(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_VALUE_NUM)); long valueDenom = cursor.getLong(cursor.getColumnIndexOrThrow(PriceEntry.COLUMN_VALUE_DENOM)); if (valueNum < 0 || valueDenom < 0) { // this should not happen return pairZero; } if (!commodityUIDdb.equals(commodityUID)) { // swap Num and denom long t = valueNum; valueNum = valueDenom; valueDenom = t; } return new Pair<Long, Long>(valueNum, valueDenom); } else { return pairZero; } } finally { cursor.close(); } } }