[tomboy/autosync: 1/15] better note difference comparison WIP



commit 319360f48ea5ba1a3cbe6a8edd57d4a705a09860
Author: Sandy Armstrong <sanfordarmstrong gmail com>
Date:   Fri Dec 4 17:50:34 2009 -0800

    better note difference comparison WIP

 Tomboy/Note.cs                        |   40 ++++++++++++++++-------
 Tomboy/Synchronization/SyncManager.cs |   56 +++++++++++++++++++++++++++++++-
 2 files changed, 82 insertions(+), 14 deletions(-)
---
diff --git a/Tomboy/Note.cs b/Tomboy/Note.cs
index e936c2f..7a6ec7d 100644
--- a/Tomboy/Note.cs
+++ b/Tomboy/Note.cs
@@ -1154,15 +1154,40 @@ namespace Tomboy
 
 		public virtual NoteData ReadFile (string read_file, string uri)
 		{
-			NoteData note = new NoteData (uri);
-			string version = "";
-
 			StreamReader reader = new StreamReader (read_file,
 			                                        System.Text.Encoding.UTF8);
 			XmlTextReader xml = new XmlTextReader (reader);
 			xml.Namespaces = false;
+			
+			string version;
+			NoteData data = Read (xml, uri, out version);
+
+			if (version != NoteArchiver.CURRENT_VERSION) {
+				// Note has old format, so rewrite it.  No need
+				// to reread, since we are not adding anything.
+				Logger.Log ("Updating note XML to newest format...");
+				NoteArchiver.Write (read_file, data);
+			}
+
+			reader.Close ();
+			xml.Close ();
+
+			return data;
+		}
+		
+		public virtual NoteData Read (XmlTextReader xml, string uri)
+		{
+			string version; // discarded
+			NoteData data = Read (xml, uri, out version);
+			return data;
+		}
+
+		private NoteData Read (XmlTextReader xml, string uri, out string version)
+		{
+			NoteData note = new NoteData (uri);
 			DateTime date;
 			int num;
+			version = String.Empty;
 
 			while (xml.Read ()) {
 				switch (xml.NodeType) {
@@ -1234,15 +1259,6 @@ namespace Tomboy
 					break;
 				}
 			}
-			reader.Close ();
-			xml.Close ();
-
-			if (version != NoteArchiver.CURRENT_VERSION) {
-				// Note has old format, so rewrite it.  No need
-				// to reread, since we are not adding anything.
-				Logger.Log ("Updating note XML to newest format...");
-				NoteArchiver.Write (read_file, note);
-			}
 
 			return note;
 		}
diff --git a/Tomboy/Synchronization/SyncManager.cs b/Tomboy/Synchronization/SyncManager.cs
index 901a995..40b08f9 100644
--- a/Tomboy/Synchronization/SyncManager.cs
+++ b/Tomboy/Synchronization/SyncManager.cs
@@ -321,7 +321,8 @@ namespace Tomboy.Sync
 				{
 					if (FindNoteByUUID (noteUpdate.UUID) == null) {
 						Note existingNote = NoteMgr.Find (noteUpdate.Title);
-						if (existingNote != null) {
+						if (existingNote != null && !noteUpdate.BasicallyEqualTo (existingNote)) {
+//							Logger.Debug ("Sync: Early conflict detection for '{0}'", noteUpdate.Title);
 							if (NoteConflictDetected != null) {
 								NoteConflictDetected (NoteMgr, existingNote, noteUpdate, noteUpdateTitles);
 
@@ -354,10 +355,12 @@ namespace Tomboy.Sync
 							DeleteNoteInMainThread (existingNote);
 						}
 						CreateNoteInMainThread (noteUpdate);
-					} else if (existingNote.MetadataChangeDate.CompareTo (client.LastSyncDate) <= 0) {
+					} else if (existingNote.MetadataChangeDate.CompareTo (client.LastSyncDate) <= 0 ||
+					           noteUpdate.BasicallyEqualTo (existingNote)) {
 						// Existing note hasn't been modified since last sync; simply update it from server
 						UpdateNoteInMainThread (existingNote, noteUpdate);
 					} else {
+//						Logger.Debug ("Sync: Late conflict detection for '{0}'", noteUpdate.Title);
 						Logger.Debug (string.Format (
 						                      "SyncManager: Content conflict in note update for note '{0}'",
 						                      noteUpdate.Title));
@@ -511,6 +514,7 @@ namespace Tomboy.Sync
 			}
 		}
 
+
 		/// <summary>
 		/// The GUI should call this after having the user resolve a conflict
 		/// so the synchronization thread can continue.
@@ -775,6 +779,54 @@ namespace Tomboy.Sync
 				}
 			}
 		}
+
+		public bool BasicallyEqualTo (Note existingNote)
+		{
+//			Logger.Debug ("Comparing NoteData for '{0}'", existingNote.Title);
+			// NOTE: This would be so much easier if NoteUpdate
+			//       was not just a container for a big XML string
+			NoteData updateData = null;
+			using (var xml = new XmlTextReader (new StringReader (XmlContent))) {
+				xml.Namespaces = false;
+				updateData = NoteArchiver.Instance.Read (xml, UUID);
+			}
+			
+			// NOTE: Mostly a hack to ignore missing version attributes
+			string existingInnerContent = GetInnerContent (existingNote.Data.Text);
+			string updateInnerContent = GetInnerContent (updateData.Text);
+			
+//			Logger.Debug ("existingNote.Data.Title: {0}", existingNote.Data.Title);
+//			Logger.Debug ("updateData.Title: {0}", updateData.Title);
+//			
+//			Logger.Debug ("existingInnerContent: {0}", existingInnerContent);
+//			Logger.Debug ("updateInnerContent: {0}", updateInnerContent);
+			
+			return existingInnerContent == updateInnerContent &&
+				existingNote.Data.Title == updateData.Title &&
+				CompareTags (existingNote.Data.Tags, updateData.Tags);
+				// TODO: Compare open-on-startup, pinned
+		}
+		
+		private string GetInnerContent (string fullContentElement)
+		{
+			const string noteContentRegex =
+				@"^<note-content(\s+version=""(?<contentVersion>[^""]*)"")?\s*((/>)|(>(?<innerContent>.*)</note-content>))$";
+			Match m = Regex.Match (fullContentElement, noteContentRegex, RegexOptions.Singleline);
+			Group contentGroup = m.Groups ["innerContent"];
+			if (!contentGroup.Success)
+				return null;
+			return contentGroup.Value;
+		}
+
+		private bool CompareTags (Dictionary<string, Tag> set1, Dictionary<string, Tag> set2)
+		{
+			if (set1.Count != set2.Count)
+				return false;
+			foreach (string key in set1.Keys)
+				if (!set2.ContainsKey (key))
+					return false;
+			return true;
+		}
 	}
 
 	public class SyncLockInfo



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]