// syncing with remote changes protected void prepareSyncableNotes(List<Note> notesList) { remoteGuids = new List<string>(); pushableNotes = new List<Note>(); pullableNotes = new List<Note>(); comparableNotes = new List<Note[]>(); deleteableNotes = new List<Note>(); conflictingNotes = new List<Note[]>(); // check if remote notes are already in local foreach(Note remoteNote in notesList) { Note localNote = NoteManager.getNoteByGuid(activity,remoteNote.getGuid()); remoteGuids.Add(remoteNote.getGuid()); if(localNote == null) { // check to make sure there is no note with this title, otherwise show conflict dialogue ICursor cursor = NoteManager.getTitles(activity); if (!(cursor == null || cursor.Count == 0)) { cursor.MoveToFirst(); do { string atitle = cursor.GetString(cursor.GetColumnIndexOrThrow(Note.TITLE)); if(atitle.Equals(remoteNote.getTitle())) { string aguid = cursor.GetString(cursor.GetColumnIndexOrThrow(Note.GUID)); localNote = NoteManager.getNoteByGuid(activity, aguid); break; } } while (cursor.MoveToNext()); } cursor.Close(); if(localNote == null) pullableNotes.Add(remoteNote); else { // compare two different notes with same title remoteGuids.Add(localNote.getGuid()); // add to avoid catching it below Note[] compNotes = {localNote, remoteNote}; comparableNotes.Add(compNotes); } } else { Note[] compNotes = {localNote, remoteNote}; comparableNotes.Add(compNotes); } } if(cancelled) { doCancel(); return; } // get non-remote notes; if newer than last sync, push, otherwise delete ICursor localGuids = NoteManager.getGuids(this.activity); if (!(localGuids == null || localGuids.Count == 0)) { string localGuid; localGuids.MoveToFirst(); do { localGuid = localGuids.GetString(localGuids.GetColumnIndexOrThrow(Note.GUID)); if(!remoteGuids.Contains(localGuid)) { Note note = NoteManager.getNoteByGuid(this.activity, localGuid); string syncDatestring = Preferences.GetString(Preferences.Key.LATEST_SYNC_DATE); Time syncDate = new Time(); syncDate.Parse3339(syncDatestring); int compareSync = Time.Compare(syncDate, note.getLastChangeDate()); if(compareSync > 0) // older than last sync, means it's been deleted from server deleteableNotes.Add(note); else if(!note.getTags().Contains("system:template")) // don't push templates TODO: find out what's wrong with this, if anything pushableNotes.Add(note); } } while (localGuids.MoveToNext()); } TLog.d(TAG, "Notes to pull: {0}, Notes to push: {1}, Notes to delete: {2}, Notes to compare: {3}",pullableNotes.Count,pushableNotes.Count,deleteableNotes.Count,comparableNotes.Count); if(cancelled) { doCancel(); return; } // deal with notes in both - compare and push, pull or diff syncDatestring = Preferences.GetString(Preferences.Key.LATEST_SYNC_DATE); syncDate = new Time(); syncDate.Parse3339(syncDatestring); foreach (var notes in comparableNotes) { Note localNote = notes[0]; Note remoteNote = notes[1]; // if different guids, means conflicting titles if(!remoteNote.getGuid().Equals(localNote.getGuid())) { TLog.i(TAG, "adding conflict of two different notes with same title"); conflictingNotes.Add(notes); continue; } if(cancelled) { doCancel(); return; } int compareSyncLocal = Time.Compare(syncDate, localNote.getLastChangeDate()); int compareSyncRemote = Time.Compare(syncDate, remoteNote.getLastChangeDate()); int compareBoth = Time.Compare(localNote.getLastChangeDate(), remoteNote.getLastChangeDate()); // if not two-way and not same date, overwrite the local version if(!push && compareBoth != 0) { TLog.i(TAG, "Different note dates, overwriting local note"); pullableNotes.Add(remoteNote); continue; } // begin compare if(cancelled) { doCancel(); return; } // check date difference TLog.v(TAG, "compare both: {0}, compare local: {1}, compare remote: {2}", compareBoth, compareSyncLocal, compareSyncRemote); if(compareBoth != 0) TLog.v(TAG, "Different note dates"); if((compareSyncLocal < 0 && compareSyncRemote < 0) || (compareSyncLocal > 0 && compareSyncRemote > 0)) TLog.v(TAG, "both either older or newer"); if(compareBoth != 0 && ((compareSyncLocal < 0 && compareSyncRemote < 0) || (compareSyncLocal > 0 && compareSyncRemote > 0))) { // sync conflict! both are older or newer than last sync TLog.i(TAG, "Note Conflict: TITLE:{0} GUID:{1}", localNote.getTitle(), localNote.getGuid()); conflictingNotes.Add(notes); } else if(compareBoth > 0) // local newer, bundle in pushable pushableNotes.Add(localNote); else if(compareBoth < 0) { // local older, pull immediately, no need to bundle TLog.i(TAG, "Local note is older, updating in content provider TITLE:{0} GUID:{1}", localNote.getTitle(), localNote.getGuid()); pullableNotes.Add(remoteNote); } else { // both same date if(localNote.getTags().Contains("system:deleted") && push) { // deleted, bundle for remote deletion TLog.i(TAG, "Notes are same date, deleted, deleting remote: TITLE:{0} GUID:{1}", localNote.getTitle(), localNote.getGuid()); pushableNotes.Add(localNote); } else { // do nothing TLog.i(TAG, "Notes are same date, doing nothing: TITLE:{0} GUID:{1}", localNote.getTitle(), localNote.getGuid()); // NoteManager.putNote(activity, remoteNote); } } } if(conflictingNotes.IsEmpty()) doSyncNotes(); else fixConflictingNotes(); }
public Time getLastChangeDate() { Time time = new Time(); time.Parse3339(lastChangeDate); return time; }