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();
}
}
}