package com.radicaldynamic.groupinform.tasks; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Set; import org.ektorp.ReplicationStatus; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import com.radicaldynamic.groupinform.application.Collect; import com.radicaldynamic.groupinform.listeners.SynchronizeFoldersListener; import com.radicaldynamic.groupinform.logic.AccountFolder; import com.radicaldynamic.groupinform.services.DatabaseService; //public class SynchronizeFoldersTask extends AsyncTask<Params, Progress, Result> { public class SynchronizeFoldersTask extends AsyncTask<Void, Void, Void> { private static final String t = "SynchronizeFoldersTask: "; private SynchronizeFoldersListener mStateListener; private HashMap<String, HashMap<String, ReplicationStatus>> mSummary = new HashMap<String, HashMap<String, ReplicationStatus>>(); private ArrayList<String> mFoldersToSynchronize = new ArrayList<String>(); private int mTransferMode = SynchronizeFoldersListener.MODE_UNDEFINED; private boolean mPostExecuteSwitch = false; private int mErrorCode = SynchronizeFoldersListener.OUTCOME_OKAY; final Handler progressHandler = new Handler() { public void handleMessage(Message msg) { if (mStateListener != null) { mStateListener.synchronizationHandler(msg); } } }; @Override protected Void doInBackground(Void... nothing) { if (Collect.getInstance().getIoService().isSignedIn() || Collect.getInstance().getIoService().goOnline()) { mSummary = synchronize(); } else { mErrorCode = SynchronizeFoldersListener.OUTCOME_DISCONNECTED; } return null; } @Override protected void onPreExecute() { // Trigger display of progress dialog if so implemented synchronized (this) { if (mStateListener != null) { mStateListener.synchronizationHandler(null); } } } @Override protected void onPostExecute(Void nothing) { synchronized (this) { if (mStateListener != null) { Bundle b = new Bundle(); // Go through summary of replications and look for problems Set<String> folders = mSummary.keySet(); Iterator<String> folderIds = folders.iterator(); while (folderIds.hasNext()) { String id = folderIds.next(); HashMap<String, ReplicationStatus> result = mSummary.get(id); if (result.containsKey(SynchronizeFoldersListener.PUSH_RESULT)) { ReplicationStatus r = result.get(SynchronizeFoldersListener.PUSH_RESULT); if (r == null || (!r.isOk() && !r.isNoChanges())) { mErrorCode = SynchronizeFoldersListener.OUTCOME_INTERRUPTED; } } if (result.containsKey(SynchronizeFoldersListener.PULL_RESULT)) { ReplicationStatus r = result.get(SynchronizeFoldersListener.PULL_RESULT); if (r == null || (!r.isOk() && !r.isNoChanges())) { mErrorCode = SynchronizeFoldersListener.OUTCOME_INTERRUPTED; } } } if (mErrorCode > 0) { b.putBoolean(SynchronizeFoldersListener.SUCCESSFUL, false); b.putInt(SynchronizeFoldersListener.FAILURE, mErrorCode); } else { b.putBoolean(SynchronizeFoldersListener.SUCCESSFUL, true); } // Pass along optional execution path b.putBoolean(SynchronizeFoldersListener.POS, mPostExecuteSwitch); mStateListener.synchronizationTaskFinished(b); } } } // Activity handler; this will be used during pre-execute to set up activity UI public void setListener(SynchronizeFoldersListener sl) { synchronized (this) { mStateListener = sl; } } // A specific set of folders to synchronize vs. everything public void setFolders(ArrayList<String> folders) { mFoldersToSynchronize = folders; } // Return with result; use for alternate workflow in activity post-task handling public void setPostExecuteSwitch(boolean s) { mPostExecuteSwitch = s; } // Set transfer direction (up, down or both) public void setTransferMode(int mode) { mTransferMode = mode; } // Run synchronization process using task configuration private HashMap<String, HashMap<String, ReplicationStatus>> synchronize() { HashMap<String, HashMap<String, ReplicationStatus>> status = new HashMap<String, HashMap<String, ReplicationStatus>>(); Set<String> folderSet = Collect.getInstance().getInformOnlineState().getAccountFolders().keySet(); Iterator<String> folderIds = folderSet.iterator(); int progress = 0; int total = 0; // Figure out how many folders are marked for replication while (folderIds.hasNext()) { AccountFolder folder = Collect.getInstance().getInformOnlineState().getAccountFolders().get(folderIds.next()); // If we were supplied with a specific list of folders to synchronize AND this folder isn't in the list if (!mFoldersToSynchronize.isEmpty() && !mFoldersToSynchronize.contains(folder.getId())) { if (Collect.Log.VERBOSE) Log.v(Collect.LOGTAG, t + folder.getId() + " is not among the list of folders to synchronize; removing it from the queue"); folderIds.remove(); } else if (folder.isReplicated()) { // Otherwise, keep it in the list and increment the total number of folders to process total++; } } // Abort (no folders to replicate) if (total == 0) { return status; } // Reset iterator folderIds = folderSet.iterator(); while (folderIds.hasNext()) { AccountFolder folder = Collect.getInstance().getInformOnlineState().getAccountFolders().get(folderIds.next()); HashMap<String, ReplicationStatus> replicationResults = new HashMap<String, ReplicationStatus>(); // Remember if a database existed prior to the PULL that follows this boolean dbMayHaveChanges = Collect.getInstance().getDbService().isDbLocal(folder.getId()); if (folder.isReplicated()) { // Update progress dialog Message msg = progressHandler.obtainMessage(); msg.arg1 = ++progress; msg.arg2 = total; progressHandler.sendMessage(msg); try { if (mTransferMode == SynchronizeFoldersListener.MODE_PULL || mTransferMode == SynchronizeFoldersListener.MODE_SWAP) { replicationResults.put(SynchronizeFoldersListener.PULL_RESULT, Collect.getInstance().getDbService().replicate(folder.getId(), DatabaseService.REPLICATE_PULL)); } } catch (Exception e) { if (Collect.Log.WARN) Log.w(Collect.LOGTAG, t + "problem pulling " + folder.getId() + ": " + e.toString()); e.printStackTrace(); replicationResults.put(SynchronizeFoldersListener.PULL_RESULT, null); } // A push should only occur if the database exists locally and is likely to have changes if (dbMayHaveChanges) { try { if (mTransferMode == SynchronizeFoldersListener.MODE_PUSH || mTransferMode == SynchronizeFoldersListener.MODE_SWAP) { replicationResults.put(SynchronizeFoldersListener.PUSH_RESULT, Collect.getInstance().getDbService().replicate(folder.getId(), DatabaseService.REPLICATE_PUSH)); } } catch (Exception e) { if (Collect.Log.WARN) Log.w(Collect.LOGTAG, t + "problem pushing " + folder.getId() + ": " + e.toString()); e.printStackTrace(); replicationResults.put(SynchronizeFoldersListener.PUSH_RESULT, null); } } status.put(folder.getId(), replicationResults); } } return status; } }