org.privatenotes.sync.web.SnowySyncMethod.java Source code

Java tutorial

Introduction

Here is the source code for org.privatenotes.sync.web.SnowySyncMethod.java

Source

/*
 * Tomdroid
 * Tomboy on Android
 * http://www.launchpad.net/tomdroid
 * 
 * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org>
 * 
 * This file is part of Tomdroid.
 * 
 * Tomdroid is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Tomdroid is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Tomdroid.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.privatenotes.sync.web;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Set;

import org.json.JSONException;
import org.privatenotes.Note;
import org.privatenotes.sync.ServiceAuth;
import org.privatenotes.sync.SyncMethod;
import org.privatenotes.ui.Tomdroid;

import android.app.Activity;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class SnowySyncMethod extends SyncMethod implements ServiceAuth {

    private static final String TAG = "SnowySyncMethod";

    public SnowySyncMethod(Activity activity, Handler handler) {
        super(activity, handler);
    }

    @Override
    public String getDescription() {
        return "Tomboy Web";
    }

    @Override
    public String getName() {
        return "tomboy-web";
    }

    public boolean isConfigured() {
        OAuthConnection auth = SyncServer.getAuthConnection();
        return auth.isAuthenticated();
    }

    @Override
    public boolean needsServer() {
        return true;
    }

    @Override
    public boolean needsAuth() {
        return true;
    }

    public void getAuthUri(final String server, final Handler handler) {

        execInThread(new Runnable() {

            public void run() {

                // Reset the authentication credentials
                OAuthConnection auth = new OAuthConnection();
                Uri authUri = null;

                try {
                    authUri = auth.getAuthorizationUrl(server);

                } catch (UnknownHostException e) {
                    Log.e(TAG, "Internet connection not available");
                    sendMessage(NO_INTERNET);
                }

                Message message = new Message();
                message.obj = authUri;
                handler.sendMessage(message);
            }

        });
    }

    public void remoteAuthComplete(final Uri uri, final Handler handler) {

        execInThread(new Runnable() {

            public void run() {

                try {
                    // TODO: might be intelligent to show something like a progress dialog
                    // else the user might try to sync before the authorization process
                    // is complete
                    OAuthConnection auth = SyncServer.getAuthConnection();
                    boolean result = auth.getAccess(uri.getQueryParameter("oauth_verifier"));

                    if (result) {
                        if (Tomdroid.LOGGING_ENABLED)
                            Log.i(TAG, "The authorization process is complete.");
                    } else {
                        Log.e(TAG, "Something went wrong during the authorization process.");
                    }
                } catch (UnknownHostException e) {
                    Log.e(TAG, "Internet connection not available");
                    sendMessage(NO_INTERNET);
                }

                // We don't care what we send, just remove the dialog
                handler.sendEmptyMessage(0);
            }
        });
    }

    @Override
    public boolean isSyncable() {
        return super.isSyncable() && isConfigured();
    }

    @Override
    protected void sync() {

        // start loading snowy notes
        setSyncProgress(0);
        if (Tomdroid.LOGGING_ENABLED)
            Log.v(TAG, "Loading Snowy notes");

        execInThread(new Runnable() {

            public void run() {

                OAuthConnection auth = SyncServer.getAuthConnection();

                try {
                    SyncServer server = new SyncServer();
                    setSyncProgress(30);

                    syncWith(server);

                } catch (JSONException e1) {
                    Log.e(TAG, "Problem parsing the server response", e1);
                    sendMessage(PARSING_FAILED);
                    setSyncProgress(100);
                    return;
                } catch (java.net.UnknownHostException e) {
                    Log.e(TAG, "Internet connection not available");
                    sendMessage(NO_INTERNET);
                    setSyncProgress(100);
                    return;
                }
            }
        });
    }

    void syncWith(SyncServer server) throws UnknownHostException, JSONException {

        if (server.isInSync(getLocalStorage())) {
            setSyncProgress(100);
            return;
        }

        ensureServerIdIsAsExpected();

        ArrayList<Note> updatesFromServer = server.getNoteUpdates();
        setSyncProgress(50);

        fixTitleConflicts(updatesFromServer);

        insertAndUpdateLocalNotes(updatesFromServer);
        setSyncProgress(70);

        deleteNotesNotFoundOnServer(server);

        if (!server.createNewRevisionWith(getLocalStorage().getNewAndUpdatedNotes())) {
            setSyncProgress(100);
            return;
        }
        setSyncProgress(90);

        deleteNotesNotFoundOnClient(server);

        getLocalStorage().onSynced(server.getSyncRevision());
        setSyncProgress(100);
    }

    private void deleteNotesNotFoundOnServer(SyncServer server) throws UnknownHostException, JSONException {
        Set<String> remotelyRemovedNoteIds = getLocalStorage().getNoteGuids();
        remotelyRemovedNoteIds.removeAll(server.getNoteIds());
        getLocalStorage().deleteNotes(remotelyRemovedNoteIds);
    }

    private void deleteNotesNotFoundOnClient(SyncServer server) throws UnknownHostException, JSONException {
        Set<String> locallyRemovedNoteIds = server.getNoteIds();
        locallyRemovedNoteIds.removeAll(getLocalStorage().getNoteGuids());
        server.delete(locallyRemovedNoteIds);
    }

    /**
     * Check if the server's guid is as expected to prevent deleting local notes, etc when the
     * server has been wiped or reinitialized by another client.
     */
    private void ensureServerIdIsAsExpected() {

        /*
         * // If the server has been wiped or reinitialized by another client // for some reason,
         * our local manifest is inaccurate and could misguide // sync into erroneously deleting
         * local notes, etc. We reset the client // to prevent this situation. string serverId =
         * server.Id; if (client.AssociatedServerId != serverId) { client.Reset ();
         * client.AssociatedServerId = serverId; }
         */
    }

    private void insertAndUpdateLocalNotes(ArrayList<Note> serverUpdates) {
        for (Note noteUpdate : serverUpdates) {
            getLocalStorage().mergeNote(noteUpdate);
        }
    }

    private void fixTitleConflicts(ArrayList<Note> noteUpdates) {

        // TODO implement in a similar way as Tomboy (see code below)

        /*
         * // First, check for new local notes that might have title conflicts // with the updates
         * coming from the server. Prompt the user if necessary. // TODO: Lots of searching here and
         * in the next foreach... // Want this stuff to happen all at once first, but // maybe
         * there's a way to store this info and pass it on? foreach (NoteUpdate noteUpdate in
         * noteUpdates.Values) { if (FindNoteByUUID (noteUpdate.UUID) == null) { Note existingNote =
         * NoteMgr.Find (noteUpdate.Title); if (existingNote != null && !noteUpdate.BasicallyEqualTo
         * (existingNote)) { // Logger.Debug ("Sync: Early conflict detection for '{0}'",
         * noteUpdate.Title); if (syncUI != null) { syncUI.NoteConflictDetected (NoteMgr,
         * existingNote, noteUpdate, noteUpdateTitles); // Suspend this thread while the GUI is
         * presented to // the user. syncThread.Suspend (); } } } }
         */
    }

}