package com.raizlabs.android.dbflow.structure;
import android.support.annotation.NonNull;
import com.raizlabs.android.dbflow.config.FlowManager;
import com.raizlabs.android.dbflow.sql.BaseAsyncObject;
import com.raizlabs.android.dbflow.structure.database.DatabaseWrapper;
import com.raizlabs.android.dbflow.structure.database.transaction.DefaultTransactionQueue;
import com.raizlabs.android.dbflow.structure.database.transaction.ProcessModelTransaction;
import com.raizlabs.android.dbflow.structure.database.transaction.Transaction;
import java.lang.ref.WeakReference;
/**
* Description: Called from a {@link BaseModel}, this places the current {@link Model} interaction on the background.
*/
public class AsyncModel<TModel> extends BaseAsyncObject<AsyncModel<TModel>> implements Model {
/**
* Listens for when this {@link Model} modification completes.
*/
public interface OnModelChangedListener<T> {
/**
* Called when the change finishes on the {@link DefaultTransactionQueue}. This method is called on the UI thread.
*/
void onModelChanged(T model);
}
private final TModel model;
private transient WeakReference<OnModelChangedListener<TModel>> onModelChangedListener;
private ModelAdapter<TModel> modelAdapter;
public AsyncModel(@NonNull TModel referenceModel) {
super(referenceModel.getClass());
model = referenceModel;
}
/**
* Call before {@link #save()}, {@link #delete()}, {@link #update()}, or {@link #insert()}.
*
* @param onModelChangedListener The listener to use for a corresponding call to a method.
*/
public AsyncModel<TModel> withListener(OnModelChangedListener<TModel> onModelChangedListener) {
this.onModelChangedListener = new WeakReference<>(onModelChangedListener);
return this;
}
private ModelAdapter<TModel> getModelAdapter() {
if (modelAdapter == null) {
//noinspection unchecked
modelAdapter = (ModelAdapter<TModel>) FlowManager.getModelAdapter(model.getClass());
}
return modelAdapter;
}
@Override
public boolean save(@NonNull DatabaseWrapper wrapper) {
return save();
}
@Override
public boolean save() {
executeTransaction(new ProcessModelTransaction.Builder<>(
new ProcessModelTransaction.ProcessModel<TModel>() {
@Override
public void processModel(TModel model, DatabaseWrapper wrapper) {
getModelAdapter().save(model, wrapper);
}
}).add(model).build());
return false;
}
@Override
public boolean delete(@NonNull DatabaseWrapper wrapper) {
return delete();
}
@Override
public boolean delete() {
executeTransaction(new ProcessModelTransaction.Builder<>(
new ProcessModelTransaction.ProcessModel<TModel>() {
@Override
public void processModel(TModel model, DatabaseWrapper wrapper) {
getModelAdapter().delete(model, wrapper);
}
}).add(model).build());
return false;
}
@Override
public boolean update(@NonNull DatabaseWrapper wrapper) {
return update();
}
@Override
public boolean update() {
executeTransaction(new ProcessModelTransaction.Builder<>(
new ProcessModelTransaction.ProcessModel<TModel>() {
@Override
public void processModel(TModel model, DatabaseWrapper wrapper) {
getModelAdapter().update(model, wrapper);
}
}).add(model).build());
return false;
}
@Override
public long insert(DatabaseWrapper wrapper) {
return insert();
}
@Override
public long insert() {
executeTransaction(new ProcessModelTransaction.Builder<>(
new ProcessModelTransaction.ProcessModel<TModel>() {
@Override
public void processModel(TModel model, DatabaseWrapper wrapper) {
getModelAdapter().insert(model, wrapper);
}
}).add(model).build());
return INVALID_ROW_ID;
}
@Override
public void load(DatabaseWrapper wrapper) {
load();
}
@Override
public void load() {
executeTransaction(new ProcessModelTransaction.Builder<>(
new ProcessModelTransaction.ProcessModel<TModel>() {
@Override
public void processModel(TModel model, DatabaseWrapper wrapper) {
getModelAdapter().load(model, wrapper);
}
}).add(model).build());
}
@Override
public boolean exists(DatabaseWrapper wrapper) {
return exists();
}
@Override
public boolean exists() {
return getModelAdapter().exists(model);
}
/**
* @return Itself since it's already async.
*/
@NonNull
@Override
public AsyncModel<? extends Model> async() {
//noinspection unchecked
return (AsyncModel<? extends Model>) this;
}
@Override
protected void onSuccess(@NonNull Transaction transaction) {
if (onModelChangedListener != null && onModelChangedListener.get() != null) {
onModelChangedListener.get().onModelChanged(model);
}
}
}