// Shows the difference between two array entries. private void DisplayArrayDiff(object ao, object bo, DiffOperation dop, int indent) { if (dop is RemoveOperation) { RemovedText(_af.ArrayItem(ao, indent), ""); } else if (dop is ChangeOperation) { ChangedText(_af.ArrayItem(ao, indent), _bf.ArrayItem(bo, indent)); } else if (dop is ChangeObjectOperation) { SameText(_af.ObjectStart(indent), _bf.ObjectStart(indent)); DisplayDiff(ao as Hashtable, bo as Hashtable, (dop as ChangeObjectOperation).Diff, indent + 1); SameText(_af.ObjectEnd(indent), _bf.ObjectEnd(indent)); } else if (dop is ChangePositionArrayOperation) { SameText(_af.ArrayStart(indent), _bf.ArrayStart(indent)); DisplayDiff(ao as ArrayList, bo as ArrayList, (dop as ChangePositionArrayOperation).Diff, indent + 1); SameText(_af.ArrayEnd(indent), _bf.ArrayEnd(indent)); } else if (dop is ChangeIdArrayOperation) { SameText(_af.ArrayStart(indent), _bf.ArrayStart(indent)); DisplayDiff(ao as ArrayList, bo as ArrayList, (dop as ChangeIdArrayOperation).Diff, indent + 1); SameText(_af.ArrayEnd(indent), _bf.ArrayEnd(indent)); } else { SameText(_af.ArrayItem(ao, indent), _bf.ArrayItem(bo, indent)); } }
/// <summary> /// Finds the difference between two Json hashtables. /// </summary> public static HashDiff Diff(Hashtable first, Hashtable second) { HashDiff diff = new HashDiff(); foreach (DictionaryEntry de in first) { string key = (de.Key as string); object first_value = de.Value; object second_value = second.ContainsKey(key) ? second[key] : null; DiffOperation op = DiffValue(first_value, second_value); if (op != null) { diff.Operations[key] = op; } } foreach (DictionaryEntry de in second) { string key = de.Key as string; if (!first.ContainsKey(key)) { diff.Operations[key] = new ChangeOperation(de.Value); } } return(diff); }
/// <summary> /// Finds the difference between two Json arrays based on element IDs. /// </summary> public static HashDiff IdDiff(ArrayList a, ArrayList b) { HashDiff diff = new HashDiff(); for (int i = 0; i < a.Count; ++i) { object id = Id.GetId(a[i]); DiffOperation op = DiffValue(a[i], Id.FindObjectWithId(b, id)); if (op != null) { diff.Operations[id] = op; } } for (int i = 0; i < b.Count; ++i) { object id = Id.GetId(b[i]); object a_object = Id.FindObjectWithId(a, id); if (a_object == null) { diff.Operations[id] = new ChangeOperation(b[i]); } } return(diff); }
/// <summary> /// Merges two array differences to a unified difference. /// </summary> public static PositionArrayDiff Merge(PositionArrayDiff left, PositionArrayDiff right) { List <int> keys = left.Operations.Keys.ToList <int>(); foreach (var kvp in right.Operations) { if (!left.Operations.ContainsKey(kvp.Key)) { keys.Add(kvp.Key); } } PositionArrayDiff h = new PositionArrayDiff(); foreach (int key in keys) { if (left.Operations.ContainsKey(key) && right.Operations.ContainsKey(key)) { h.Operations[key] = DiffOperation.Merge(left.Operations[key], right.Operations[key]); } else if (left.Operations.ContainsKey(key)) { h.Operations[key] = left.Operations[key]; } else if (right.Operations.ContainsKey(key)) { h.Operations[key] = right.Operations[key]; } } return(h); }
/// <summary> /// Merges two HashDifferences to a unified difference. /// </summary> public static HashDiff Merge(HashDiff left, HashDiff right) { // Find the combined key list. List <object> keys = left.Operations.Keys.ToList <object>(); foreach (var kvp in right.Operations) { if (!left.Operations.ContainsKey(kvp.Key)) { keys.Add(kvp.Key); } } // Merge the operations for each key. HashDiff h = new HashDiff(); foreach (object key in keys) { if (left.Operations.ContainsKey(key) && right.Operations.ContainsKey(key)) { h.Operations[key] = DiffOperation.Merge(left.Operations[key], right.Operations[key]); } else if (left.Operations.ContainsKey(key)) { h.Operations[key] = left.Operations[key]; } else if (right.Operations.ContainsKey(key)) { h.Operations[key] = right.Operations[key]; } } return(h); }
// Shows the difference between a and b in the text box. private void DisplayDiff(RichTextBox rtb, IFormatter f, Hashtable a, Hashtable b, HashDiff diff, int indent, string path) { HashSet <string> keys = new HashSet <string>(); foreach (string key in a.Keys) { keys.Add(key); } foreach (string key in b.Keys) { keys.Add(key); } foreach (string key in keys.OrderBy(i => i)) { string subpath = path + "." + key; CheckLineNumber(rtb, subpath); if (diff.Operations.ContainsKey(key)) { DiffOperation dop = diff.Operations[key]; if (dop is RemoveOperation) { RemovedText(rtb, f.ObjectField(a, key, indent)); } else if (dop is ChangeOperation) { ChangedText(rtb, f.ObjectField(a, key, indent), f.ObjectField(b, key, indent)); } else if (dop is ChangeObjectOperation) { SameText(rtb, f.ObjectStart(key, indent)); DisplayDiff(rtb, f, a[key] as Hashtable, b[key] as Hashtable, (dop as ChangeObjectOperation).Diff, indent + 1, subpath); SameText(rtb, f.ObjectEnd(indent)); } else if (dop is ChangePositionArrayOperation) { SameText(rtb, f.ArrayStart(key, indent)); DisplayDiff(rtb, f, a[key] as ArrayList, b[key] as ArrayList, (dop as ChangePositionArrayOperation).Diff, indent + 1, subpath); SameText(rtb, f.ArrayEnd(indent)); } else if (dop is ChangeIdArrayOperation) { SameText(rtb, f.ArrayStart(key, indent)); DisplayDiff(rtb, f, a[key] as ArrayList, b[key] as ArrayList, (dop as ChangeIdArrayOperation).Diff, indent + 1, subpath); SameText(rtb, f.ArrayEnd(indent)); } } else { SameText(rtb, f.ObjectField(b, key, indent)); } } }
// Shows the difference between two hash tables. private void DisplayDiff(Hashtable a, Hashtable b, HashDiff diff, int indent) { HashSet <string> keys = new HashSet <string>(); foreach (string key in a.Keys) { keys.Add(key); } foreach (string key in b.Keys) { keys.Add(key); } foreach (string key in keys.OrderBy(i => i)) { if (diff.Operations.ContainsKey(key)) { DiffOperation dop = diff.Operations[key]; if (dop is RemoveOperation) { RemovedText(_af.ObjectField(a, key, indent), ""); } else if (dop is ChangeOperation) { ChangedText(_af.ObjectField(a, key, indent), _bf.ObjectField(b, key, indent)); } else if (dop is ChangeObjectOperation) { SameText(_af.ObjectStart(key, indent), _bf.ObjectStart(key, indent)); DisplayDiff(a[key] as Hashtable, b[key] as Hashtable, (dop as ChangeObjectOperation).Diff, indent + 1); SameText(_af.ObjectEnd(indent), _bf.ObjectEnd(indent)); } else if (dop is ChangePositionArrayOperation) { SameText(_af.ArrayStart(key, indent), _bf.ArrayStart(key, indent)); DisplayDiff(a[key] as ArrayList, b[key] as ArrayList, (dop as ChangePositionArrayOperation).Diff, indent + 1); SameText(_af.ArrayEnd(indent), _bf.ArrayEnd(indent)); } else if (dop is ChangeIdArrayOperation) { SameText(_af.ArrayStart(key, indent), _bf.ArrayStart(key, indent)); DisplayDiff(a[key] as ArrayList, b[key] as ArrayList, (dop as ChangeIdArrayOperation).Diff, indent + 1); SameText(_af.ArrayEnd(indent), _bf.ArrayEnd(indent)); } } else { SameText(_af.ObjectField(a, key, indent), _bf.ObjectField(a, key, indent)); } } }
/// <summary> /// Finds the difference between two Json arrays based on positions. /// </summary> public static PositionArrayDiff PositionDiff(ArrayList a, ArrayList b) { PositionArrayDiff diff = new PositionArrayDiff(); int n = Math.Max(a.Count, b.Count); for (int i = 0; i < n; ++i) { object first_value = i >= a.Count ? null : a[i]; object second_value = i >= b.Count ? null : b[i]; DiffOperation op = DiffValue(first_value, second_value); if (op != null) { diff.Operations[i] = op; } } return(diff); }
/// <summary> /// Merges two Diff operation into a single operation. /// </summary> static public DiffOperation Merge(DiffOperation left, DiffOperation right) { // Remove always trumps other operations. if (right is RemoveOperation) { return(right); } if (left is RemoveOperation) { return(left); } // Change operation trumps other operations and right changes take precedence over // left changes. if (right is ChangeOperation) { return(right); } if (left is ChangeOperation) { return(left); } // Recursively merge array and object operations. System.Diagnostics.Debug.Assert(left.GetType() == right.GetType()); if (left is ChangeObjectOperation) { return(ChangeObjectOperation.Merge(left as ChangeObjectOperation, right as ChangeObjectOperation)); } if (left is ChangePositionArrayOperation) { return(ChangePositionArrayOperation.Merge(left as ChangePositionArrayOperation, right as ChangePositionArrayOperation)); } if (left is ChangeIdArrayOperation) { return(ChangeIdArrayOperation.Merge(left as ChangeIdArrayOperation, right as ChangeIdArrayOperation)); } System.Diagnostics.Debug.Assert(false); return(null); }
// Shows the difference between ao and bo in the text box. private void DisplayArrayDiff(RichTextBox rtb, IFormatter f, object ao, object bo, DiffOperation dop, int indent, string path) { CheckLineNumber(rtb, path); if (dop is RemoveOperation) { RemovedText(rtb, f.ArrayItem(ao, indent)); } else if (dop is ChangeOperation) { ChangedText(rtb, f.ArrayItem(ao, indent), f.ArrayItem(bo, indent)); } else if (dop is ChangeObjectOperation) { SameText(rtb, f.ObjectStart(indent)); DisplayDiff(rtb, f, ao as Hashtable, bo as Hashtable, (dop as ChangeObjectOperation).Diff, indent + 1, path); SameText(rtb, f.ObjectEnd(indent)); } else if (dop is ChangePositionArrayOperation) { SameText(rtb, f.ArrayStart(indent)); DisplayDiff(rtb, f, ao as ArrayList, bo as ArrayList, (dop as ChangePositionArrayOperation).Diff, indent + 1, path); SameText(rtb, f.ArrayEnd(indent)); } else if (dop is ChangeIdArrayOperation) { SameText(rtb, f.ArrayStart(indent)); DisplayDiff(rtb, f, ao as ArrayList, bo as ArrayList, (dop as ChangeIdArrayOperation).Diff, indent + 1, path); SameText(rtb, f.ArrayEnd(indent)); } else { SameText(rtb, f.ArrayItem(ao, indent)); } }