package com.code44.finance.api.requests;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.code44.finance.api.GcmRegistration;
import com.code44.finance.api.Request;
import com.code44.finance.api.User;
import com.code44.finance.backend.endpoint.accounts.Accounts;
import com.code44.finance.backend.endpoint.categories.Categories;
import com.code44.finance.backend.endpoint.currencies.Currencies;
import com.code44.finance.backend.endpoint.tags.Tags;
import com.code44.finance.backend.endpoint.transactions.Transactions;
import com.code44.finance.common.utils.Preconditions;
import com.code44.finance.data.DataStore;
import com.code44.finance.data.Query;
import com.code44.finance.data.db.Column;
import com.code44.finance.data.db.DBHelper;
import com.code44.finance.data.db.Tables;
import com.code44.finance.data.model.Account;
import com.code44.finance.data.model.Category;
import com.code44.finance.data.model.Currency;
import com.code44.finance.data.model.SyncState;
import com.code44.finance.data.model.Tag;
import com.code44.finance.data.model.Transaction;
import com.code44.finance.data.providers.AccountsProvider;
import com.code44.finance.data.providers.CategoriesProvider;
import com.code44.finance.data.providers.CurrenciesProvider;
import com.code44.finance.data.providers.TagsProvider;
import com.code44.finance.data.providers.TransactionsProvider;
import com.code44.finance.utils.EventBus;
import com.code44.finance.utils.IOUtils;
import java.util.ArrayList;
import java.util.List;
public class SyncRequest extends Request {
private final Context context;
private final DBHelper dbHelper;
private final User user;
private final GcmRegistration gcmRegistration;
private final Currencies currenciesService;
private final Categories categoriesService;
private final Tags tagsService;
private final Accounts accountsService;
private final Transactions transactionsService;
public SyncRequest(EventBus eventBus, Context context, DBHelper dbHelper, User user, GcmRegistration gcmRegistration, Currencies currenciesService, Categories categoriesService, Tags tagsService, Accounts accountsService, Transactions transactionsService) {
super(eventBus);
Preconditions.notNull(eventBus, "EventBus cannot be null.");
Preconditions.notNull(context, "Context cannot be null.");
Preconditions.notNull(dbHelper, "DBHelper cannot be null.");
Preconditions.notNull(user, "User cannot be null.");
Preconditions.notNull(gcmRegistration, "Gcm registration cannot be null.");
Preconditions.notNull(currenciesService, "Currencies service cannot be null.");
Preconditions.notNull(categoriesService, "Categories service cannot be null.");
Preconditions.notNull(tagsService, "Tags service cannot be null.");
Preconditions.notNull(accountsService, "Accounts service cannot be null.");
Preconditions.notNull(transactionsService, "Transactions service cannot be null.");
this.context = context;
this.dbHelper = dbHelper;
this.user = user;
this.gcmRegistration = gcmRegistration;
this.currenciesService = currenciesService;
this.categoriesService = categoriesService;
this.tagsService = tagsService;
this.accountsService = accountsService;
this.transactionsService = transactionsService;
}
@Override protected void performRequest() throws Exception {
final SQLiteDatabase database = dbHelper.getWritableDatabase();
pushCurrencies(database);
getCurrencies();
pushCategories(database);
getCategories();
pushTags(database);
getTags();
pushAccounts(database);
getAccounts();
pushTransactions(database);
getTransactions();
}
private void pushCurrencies(SQLiteDatabase database) {
markInProgress(database, Tables.Currencies.SYNC_STATE);
final Cursor cursor = Query.create()
.projectionLocalId(Tables.Currencies.LOCAL_ID)
.projection(Tables.Currencies.PROJECTION)
.selection(Tables.Currencies.SYNC_STATE + "=?", SyncState.InProgress.asString())
.from(context, CurrenciesProvider.uriCurrencies())
.execute();
final List<Currency> currencies = new ArrayList<>();
do {
currencies.add(Currency.from(cursor));
} while (cursor.moveToNext());
IOUtils.closeQuietly(cursor);
new PostCurrenciesRequest(gcmRegistration, currenciesService, currencies).run();
}
private void getCurrencies() {
new GetCurrenciesRequest(context, user, currenciesService).run();
}
private void pushCategories(SQLiteDatabase database) {
markInProgress(database, Tables.Categories.SYNC_STATE);
final Cursor cursor = Query.create()
.projectionLocalId(Tables.Categories.LOCAL_ID)
.projection(Tables.Categories.PROJECTION)
.selection(Tables.Categories.SYNC_STATE + "=?", SyncState.InProgress.asString())
.from(context, CategoriesProvider.uriCategories())
.execute();
final List<Category> categories = new ArrayList<>();
do {
categories.add(Category.from(cursor));
} while (cursor.moveToNext());
IOUtils.closeQuietly(cursor);
new PostCategoriesRequest(gcmRegistration, categoriesService, categories).run();
}
private void getCategories() {
new GetCategoriesRequest(context, user, categoriesService).run();
}
private void pushTags(SQLiteDatabase database) {
markInProgress(database, Tables.Tags.SYNC_STATE);
final Cursor cursor = Query.create()
.projectionLocalId(Tables.Tags.LOCAL_ID)
.projection(Tables.Tags.PROJECTION)
.selection(Tables.Tags.SYNC_STATE + "=?", SyncState.InProgress.asString())
.from(context, TagsProvider.uriTags())
.execute();
final List<Tag> tags = new ArrayList<>();
do {
tags.add(Tag.from(cursor));
} while (cursor.moveToNext());
IOUtils.closeQuietly(cursor);
new PostTagsRequest(gcmRegistration, tagsService, tags).run();
}
private void getTags() {
new GetTagsRequest(context, user, tagsService).run();
}
private void pushAccounts(SQLiteDatabase database) {
markInProgress(database, Tables.Accounts.SYNC_STATE);
final Cursor cursor = Query.create()
.projectionLocalId(Tables.Accounts.LOCAL_ID)
.projection(Tables.Accounts.PROJECTION)
.projection(Tables.Currencies.PROJECTION)
.selection(Tables.Accounts.SYNC_STATE + "=?", SyncState.InProgress.asString())
.from(context, AccountsProvider.uriAccounts())
.execute();
final List<Account> accounts = new ArrayList<>();
do {
accounts.add(Account.from(cursor));
} while (cursor.moveToNext());
IOUtils.closeQuietly(cursor);
new PostAccountsRequest(gcmRegistration, accountsService, accounts).run();
}
private void getAccounts() {
new GetAccountsRequest(context, user, accountsService).run();
}
private void pushTransactions(SQLiteDatabase database) {
markInProgress(database, Tables.Transactions.SYNC_STATE);
final Cursor cursor = Query.create()
.projectionLocalId(Tables.Transactions.LOCAL_ID)
.projection(Tables.Transactions.PROJECTION)
.projection(Tables.Accounts.PROJECTION_ACCOUNT_FROM)
.projection(Tables.Accounts.PROJECTION_ACCOUNT_TO)
.projection(Tables.Currencies.PROJECTION_ACCOUNT_FROM)
.projection(Tables.Currencies.PROJECTION_ACCOUNT_TO)
.projection(Tables.Categories.PROJECTION)
.selection(Tables.Transactions.SYNC_STATE + "=?", SyncState.InProgress.asString())
.from(context, TransactionsProvider.uriTransactions())
.execute();
final List<Transaction> transactions = new ArrayList<>();
do {
transactions.add(Transaction.from(cursor));
} while (cursor.moveToNext());
IOUtils.closeQuietly(cursor);
new PostTransactionsRequest(gcmRegistration, transactionsService, transactions).run();
}
private void getTransactions() {
new GetTransactionsRequest(context, user, transactionsService).run();
}
private void markInProgress(SQLiteDatabase database, Column syncStateColumn) {
final ContentValues values = new ContentValues();
values.put(syncStateColumn.getName(), SyncState.InProgress.asInt());
DataStore.update()
.values(values)
.withSelection(syncStateColumn.getName() + "<>?", SyncState.Synced.asString())
.into(database, syncStateColumn.getTableName());
}
}