147
* Insert notes in the content provider.
149
* @param notes The notes to insert.
152
protected void insertNotes(List<Note> notes, boolean push) {
154
NoteManager.putNotes(this.activity, notes, push);
157
* Insert last note in the content provider. tell the
157
* Insert last note in the content provider.
159
159
* @param note The note to insert.
162
protected void insertNote(Note note, boolean push) {
163
NoteManager.putNote(this.activity, note, push);
162
protected void insertNote(Note note) {
163
NoteManager.putNote(this.activity, note);
164
sendMessage(INCREMENT_PROGRESS );
166
* Delete notes in the content provider. The guids passed identify the notes existing
167
* on the remote end (ie. that shouldn't be deleted).
169
* @param remoteGuids The notes NOT to delete.
172
protected void deleteNotes(ArrayList<String> remoteGuids) {
174
Cursor localGuids = NoteManager.getGuids(this.activity);
176
// cursor must not be null and must return more than 0 entry
177
if (!(localGuids == null || localGuids.getCount() == 0)) {
181
localGuids.moveToFirst();
184
localGuid = localGuids.getString(localGuids.getColumnIndexOrThrow(Note.GUID));
186
if(!remoteGuids.contains(localGuid)) {
187
int id = localGuids.getInt(localGuids.getColumnIndexOrThrow(Note.ID));
188
NoteManager.deleteNote(this.activity, id);
191
} while (localGuids.moveToNext());
195
// TODO send an error to the user
196
TLog.d(TAG, "Cursor returned null or 0 notes");
201
* Add notes from the content provider. The guids passed identify the notes existing
202
* on the remote end (ie. that shouldn't be added).
204
* @param remoteGuids The notes NOT to add.
207
protected List<Note> pullNotes(ArrayList<String> remoteGuids) {
209
Cursor localGuids = NoteManager.getGuids(this.activity);
210
String lastGUID = null;
211
// cursor must not be null and must return more than 0 entry
212
List<Note> notes = new ArrayList<Note>();
213
if (!(localGuids == null || localGuids.getCount() == 0)) {
217
localGuids.moveToFirst();
219
localGuid = localGuids.getString(localGuids.getColumnIndexOrThrow(Note.GUID));
221
if(!remoteGuids.contains(localGuid)) {
222
int id = localGuids.getInt(localGuids.getColumnIndexOrThrow(Note.ID));
223
notes.add(NoteManager.getNote(this.activity, Uri.parse(Tomdroid.CONTENT_URI + "/" + id)));
224
lastGUID = localGuid;
227
} while (localGuids.moveToNext());
231
// TODO send an error to the user
232
TLog.d(TAG, "Cursor returned null or 0 notes");
168
protected void syncNotes(ArrayList<Note> notesList, boolean push) {
170
ArrayList<String> remoteGuids = new ArrayList<String>();
171
ArrayList<Note> pushableNotes = new ArrayList<Note>();
172
ArrayList<Note> pullableNotes = new ArrayList<Note>();
173
HashMap<String,Note[]> comparableNotes = new HashMap<String,Note[]>();
174
ArrayList<String> deleteableNotes = new ArrayList<String>();
176
for ( Note remoteNote : notesList) {
177
Note localNote = NoteManager.getNoteByGuid(activity,remoteNote.getGuid());
178
remoteGuids.add(remoteNote.getGuid());
179
if(localNote == null) {
180
pullableNotes.add(remoteNote);
183
Note[] compNotes = {localNote, remoteNote};
184
comparableNotes.put(localNote.getGuid(), compNotes);
187
// get non-remote notes
189
Cursor localGuids = NoteManager.getGuids(this.activity);
190
// cursor must not be null and must return more than 0 entry
191
if (!(localGuids == null || localGuids.getCount() == 0)) {
195
localGuids.moveToFirst();
197
localGuid = localGuids.getString(localGuids.getColumnIndexOrThrow(Note.GUID));
199
if(!remoteGuids.contains(localGuid)) {
200
int id = localGuids.getInt(localGuids.getColumnIndexOrThrow(Note.ID));
201
Note note = NoteManager.getNoteByGuid(this.activity, localGuid);
202
if(note.getTags().contains("system:deleted"))
203
deleteableNotes.add(note.getGuid());
205
pushableNotes.add(note);
208
} while (localGuids.moveToNext());
211
TLog.d(TAG, "Notes to pull: {0}, Notes to push: {1}, Notes to delete: {2}, Notes to compare: {3}",pullableNotes.size(),pushableNotes.size(),deleteableNotes.size(),comparableNotes.size());
215
HashMap<String, Object> hm = new HashMap<String, Object>();
216
hm.put("total", pullableNotes.size()+pushableNotes.size()+comparableNotes.size()+deleteableNotes.size());
217
sendMessage(BEGIN_PROGRESS,hm);
219
// deal with notes that are not in local content provider - always pull
221
for(Note note : pullableNotes)
226
// deal with notes not in remote service - push or delete
228
// if two-way sync, push local only notes, otherwise delete them
231
SyncManager.getInstance().getCurrentService().pushNotes(pushableNotes);
234
deleteNonRemoteNotes(pullableNotes);
236
// deleted notes not in remote
238
SyncManager.getInstance().getCurrentService().deleteNotes(deleteableNotes);
243
// deal with notes in both - compare and push, pull or diff
245
compareNotes(comparableNotes,push);
250
protected void deleteNonRemoteNotes(ArrayList<Note> notes) {
252
for(Note note : notes) {
253
NoteManager.deleteNote(this.activity, note.getDbId());
254
sendMessage(INCREMENT_PROGRESS);
259
private void compareNotes(HashMap<String, Note[]> comparableNotes, boolean push) {
261
String syncDateString = Preferences.getString(Preferences.Key.LATEST_SYNC_DATE);
262
Time syncDate = new Time();
263
syncDate.parse3339(syncDateString);
265
int compareCount = 0;
267
for(Note[] notes : comparableNotes.values()) {
269
Note localNote = notes[0];
270
Note remoteNote = notes[1];
272
int compareSyncLocal = Time.compare(syncDate, localNote.getLastChangeDate());
273
int compareSyncRemote = Time.compare(syncDate, remoteNote.getLastChangeDate());
274
int compareBoth = Time.compare(localNote.getLastChangeDate(), remoteNote.getLastChangeDate());
276
// if not two-way, overwrite the local version
279
NoteManager.putNote(activity, remoteNote);
283
// check date difference
285
TLog.v(TAG, "compare both: {0}, compare local: {1}, compare remote: {2}", compareBoth, compareSyncLocal, compareSyncRemote);
287
TLog.v(TAG, "Different note dates");
288
if((compareSyncLocal < 0 && compareSyncRemote < 0) || (compareSyncLocal > 0 && compareSyncRemote > 0))
289
TLog.v(TAG, "both either older or newer");
291
if(compareBoth != 0 && ((compareSyncLocal < 0 && compareSyncRemote < 0) || (compareSyncLocal > 0 && compareSyncRemote > 0))) { // sync conflict! both are older or newer than last sync
293
TLog.v(TAG, "note conflict... showing resolution dialog TITLE:{0} GUID:{1}", localNote.getTitle(), localNote.getGuid());
295
// send everything to Tomdroid so it can show Sync Dialog
296
Bundle bundle = new Bundle();
297
bundle.putString("title",remoteNote.getTitle());
298
bundle.putString("file",remoteNote.getFileName());
299
bundle.putString("guid",remoteNote.getGuid());
300
bundle.putString("date",remoteNote.getLastChangeDate().format3339(false));
301
bundle.putString("content", remoteNote.getXmlContent());
302
bundle.putString("tags", remoteNote.getTags());
303
bundle.putInt("datediff", compareBoth);
305
Intent intent = new Intent(activity.getApplicationContext(), SyncDialog.class);
306
intent.putExtras(bundle);
308
activity.startActivityForResult(intent, compareCount++);
310
else if(compareBoth > 0) { // local newer
312
TLog.v(TAG, "local newer, pushing local to remote");
314
/* pushing local changes, reject older incoming note.
315
* If the local counterpart has the tag "system:deleted", delete from both local and remote.
316
* Otherwise, push local to remote.
319
if(localNote.getTags().contains("system:deleted")) {
320
TLog.v(TAG, "local note is deleted, deleting from server TITLE:{0} GUID:{1}", localNote.getTitle(),localNote.getGuid());
321
SyncManager.getInstance().deleteNote(localNote.getGuid()); // delete from remote
322
NoteManager.deleteNote(activity,localNote.getDbId()); // really delete locally
325
TLog.v(TAG, "local note is newer, sending new version TITLE:{0} GUID:{1}", localNote.getTitle(),localNote.getGuid());
326
SyncManager.getInstance().pushNote(localNote);
329
else if(compareBoth < 0) { // local older
330
TLog.v(TAG, "Local note is older, updating in content provider TITLE:{0} GUID:{1}", localNote.getTitle(), localNote.getGuid());
331
sendMessage(INCREMENT_PROGRESS);
332
// pull remote changes
333
NoteManager.putNote(activity, remoteNote);
335
else { // both same date
336
if(localNote.getTags().contains("system:deleted")) {
337
TLog.v(TAG, "local note is deleted, deleting from server TITLE:{0} GUID:{1}", localNote.getTitle(),localNote.getGuid());
338
SyncManager.getInstance().deleteNote(localNote.getGuid()); // delete from remote
339
NoteManager.deleteNote(activity,localNote.getDbId()); // really delete locally
342
TLog.v(TAG, "Notes are same date, updating in content provider TITLE:{0} GUID:{1}", localNote.getTitle(), localNote.getGuid());
344
sendMessage(INCREMENT_PROGRESS);
345
// pull remote changes anyway
346
NoteManager.putNote(activity, remoteNote);
238
354
* Send a message to the main UI.