package co.smartreceipts.android.persistence.database.controllers.impl; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.google.common.base.Preconditions; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import co.smartreceipts.android.analytics.Analytics; import co.smartreceipts.android.analytics.events.ErrorEvent; import co.smartreceipts.android.model.Column; import co.smartreceipts.android.model.ColumnDefinitions; import co.smartreceipts.android.model.Receipt; import co.smartreceipts.android.persistence.database.controllers.TableEventsListener; import co.smartreceipts.android.persistence.database.controllers.alterations.StubTableActionAlterations; import co.smartreceipts.android.persistence.database.controllers.alterations.TableActionAlterations; import co.smartreceipts.android.persistence.database.operations.DatabaseOperationMetadata; import co.smartreceipts.android.persistence.database.tables.AbstractColumnTable; import co.smartreceipts.android.utils.ListUtils; import co.smartreceipts.android.utils.log.Logger; import io.reactivex.Scheduler; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; public class ColumnTableController extends AbstractTableController<Column<Receipt>> { private final AbstractColumnTable mAbstractColumnTable; private final ColumnDefinitions<Receipt> mReceiptColumnDefinitions; private final Scheduler mPreprocessingObserveOnScheduler; public ColumnTableController(@NonNull AbstractColumnTable table, @NonNull Analytics analytics, @NonNull ColumnDefinitions<Receipt> receiptColumnDefinitions) { this(table, new StubTableActionAlterations<Column<Receipt>>(), analytics, receiptColumnDefinitions); } public ColumnTableController(@NonNull AbstractColumnTable table, @NonNull TableActionAlterations<Column<Receipt>> tableActionAlterations, @NonNull Analytics analytics, @NonNull ColumnDefinitions<Receipt> receiptColumnDefinitions) { this(table, tableActionAlterations, receiptColumnDefinitions, analytics, Schedulers.io(), AndroidSchedulers.mainThread(), Schedulers.io()); } ColumnTableController(@NonNull AbstractColumnTable table, @NonNull TableActionAlterations<Column<Receipt>> tableActionAlterations, @NonNull ColumnDefinitions<Receipt> receiptColumnDefinitions, @NonNull Analytics analytics, @NonNull Scheduler subscribeOnScheduler, @NonNull Scheduler observeOnScheduler, @NonNull Scheduler preprocessingObserveOnScheduler) { super(table, tableActionAlterations, analytics, subscribeOnScheduler, observeOnScheduler); mAbstractColumnTable = Preconditions.checkNotNull(table); mReceiptColumnDefinitions = Preconditions.checkNotNull(receiptColumnDefinitions); mPreprocessingObserveOnScheduler = Preconditions.checkNotNull(preprocessingObserveOnScheduler); } /** * Inserts the default column as defined by {@link ColumnDefinitions#getDefaultInsertColumn()} */ public synchronized void insertDefaultColumn() { insert(mReceiptColumnDefinitions.getDefaultInsertColumn(), new DatabaseOperationMetadata()); } /** * Attempts to delete the last column in the list */ public synchronized void deleteLast(final @NonNull DatabaseOperationMetadata databaseOperationMetadata) { // TODO: Reduce code overflow and just chain directly with #delete observables via composition Logger.info(this, "#deleteLast:"); final AtomicReference<Disposable> disposableRef = new AtomicReference<>(); final Disposable subscription = mAbstractColumnTable.get() .map(this::removeLastColumnIfPresent) .observeOn(mSubscribeOnScheduler) .subscribeOn(mPreprocessingObserveOnScheduler) .subscribe(column -> { if (column != null) { for (final TableEventsListener<Column<Receipt>> tableEventsListener : mTableEventsListeners) { tableEventsListener.onDeleteSuccess(column, databaseOperationMetadata); } } else { for (final TableEventsListener<Column<Receipt>> tableEventsListener : mTableEventsListeners) { // TODO: Link this stuff better to fix improper null here :/ tableEventsListener.onDeleteFailure(column, null, databaseOperationMetadata); } } Logger.debug(this, "#deleteLast - onComplete"); unsubscribeReference(disposableRef); }, throwable -> { mAnalytics.record(new ErrorEvent(ColumnTableController.this, throwable)); Logger.debug(this, "#onDeleteLastFailure - onError"); unsubscribeReference(disposableRef); }); disposableRef.set(subscription); compositeDisposable.add(subscription); } @Nullable private Column<Receipt> removeLastColumnIfPresent(@NonNull List<Column<Receipt>> columns) { final Column<Receipt> lastColumn = ListUtils.removeLast(columns); if (lastColumn != null) { delete(lastColumn, new DatabaseOperationMetadata()); return lastColumn; } else { return null; } } }