package org.projectbuendia.client.sync.controllers;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.SyncResult;
import android.database.Cursor;
import android.net.Uri;
import com.android.volley.toolbox.RequestFuture;
import org.projectbuendia.client.App;
import org.projectbuendia.client.json.JsonForm;
import org.projectbuendia.client.models.Form;
import org.projectbuendia.client.providers.Contracts;
import org.projectbuendia.client.ui.OdkActivityLauncher;
import org.projectbuendia.client.utils.Logger;
import org.projectbuendia.client.utils.Utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
/**
* Handles syncing forms. All forms are always fetched, which is okay because there are only a few
* forms; usually less than 10.
*/
public class FormsSyncPhaseRunnable implements SyncPhaseRunnable {
private static final Logger LOG = Logger.create();
@Override
public void sync(ContentResolver contentResolver, SyncResult syncResult,
ContentProviderClient providerClient)
throws Throwable {
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
ops.addAll(getFormUpdateOps(syncResult));
providerClient.applyBatch(ops);
LOG.i("Finished updating forms (" + ops.size() + " db ops)");
contentResolver.notifyChange(Contracts.Forms.CONTENT_URI, null, false);
OdkActivityLauncher.fetchAndCacheAllXforms();
}
private static List<ContentProviderOperation> getFormUpdateOps(SyncResult syncResult)
throws ExecutionException, InterruptedException {
LOG.i("Listing all forms on server");
RequestFuture<List<JsonForm>> future = RequestFuture.newFuture();
App.getServer().listForms(future, future);
Map<String, ContentValues> cvs = new HashMap<>();
for (JsonForm form : future.get()) {
cvs.put(form.id, Form.fromJson(form).toContentValues());
}
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
final ContentResolver resolver = App.getInstance().getContentResolver();
Cursor c = resolver.query(Contracts.Forms.CONTENT_URI, new String[] {Contracts.Forms.UUID},
null, null, null);
LOG.i("Examining forms: " + c.getCount() + " local, " + cvs.size() + " from server");
try {
while (c.moveToNext()) {
String uuid = Utils.getString(c, Contracts.Forms.UUID);
Uri uri = Contracts.Forms.CONTENT_URI.buildUpon().appendPath(uuid).build();
LOG.i(" - will delete form " + uuid);
ops.add(ContentProviderOperation.newDelete(uri).build());
}
} finally {
c.close();
}
for (ContentValues values : cvs.values()) { // server has a new record
LOG.i(" - will insert form " + values.getAsString(Contracts.Forms.UUID));
ops.add(ContentProviderOperation.newInsert(Contracts.Forms.CONTENT_URI).withValues(values).build());
syncResult.stats.numInserts++;
}
return ops;
}
}