public override void AddInterface(Type type, NodeInterface nodeInterface) { if (!(nodeInterface is XmlOutputNodeInterface)) { throw new ArgumentException("Node interfaces for the XmlOutputStructuredDiff must implement XmlOutputNodeInterface."); } base.AddInterface(type, nodeInterface); }
protected override void WriteNodeChange(NodeInterface leftInterface, object left, NodeInterface rightInterface, object right) { ((XmlOutputNodeInterface)leftInterface).WriteBeginNode(left, right, (XmlWriter)output); output.WriteAttributeString("Status", "Changed"); ((XmlOutputNodeInterface)leftInterface).WriteBeginNode(left, left, (XmlWriter)output); ((XmlOutputNodeInterface)leftInterface).WriteNodeChildren(left, (XmlWriter)output); output.WriteEndElement(); ((XmlOutputNodeInterface)rightInterface).WriteBeginNode(right, right, (XmlWriter)output); ((XmlOutputNodeInterface)rightInterface).WriteNodeChildren(right, (XmlWriter)output); output.WriteEndElement(); output.WriteEndElement(); }
internal NodeInterface GetInterface(object obj) { bool store = false; Type type = obj.GetType(); while (type != null) { NodeInterface ret = (NodeInterface)nodeInterfaces[type]; if (ret != null) { if (store) { nodeInterfaces[obj.GetType()] = ret; } return(ret); } type = type.BaseType; store = true; } throw new ArgumentException("Node type has no interface defined: " + obj.GetType()); }
int IComparer.Compare(object left, object right) { float ret; Pair pair = new Pair(left, right, differ); if (left.GetType() != right.GetType()) { ret = 1; } else if (useCache && differ.comparisonCache.ContainsKey(pair)) { ret = (float)differ.comparisonCache[pair]; } else { NodeInterface comparer = differ.GetInterface(left); ret = comparer.Compare(left, right, differ); } if (useCache) { differ.comparisonCache[pair] = ret; } if (ret < minimumDifference && ret > threshold) { minimumDifference = ret; } if (ret <= threshold) { return(0); } else { return(1); } }
protected override void WriteNodeSame(NodeInterface nodeInterface, object left, object right) { bool deep = deepOutput; if (left is XmlNode && !deepOutput && !allContext) { if (!contextNodes.ContainsKey(((XmlNode)left).Name)) { return; } else { deep = true; } } ((XmlOutputNodeInterface)nodeInterface).WriteBeginNode(left, left, (XmlWriter)output); output.WriteAttributeString("Status", "Same"); if (deep) { ((XmlOutputNodeInterface)nodeInterface).WriteNodeChildren(left, (XmlWriter)output); } output.WriteEndElement(); }
public override void AddInterface(Type type, NodeInterface nodeInterface) { if (!(nodeInterface is XmlOutputNodeInterface)) throw new ArgumentException("Node interfaces for the XmlOutputStructuredDiff must implement XmlOutputNodeInterface."); base.AddInterface(type, nodeInterface); }
protected override void WriteNodeSame(NodeInterface nodeInterface, object left, object right) { bool deep = deepOutput; if (left is XmlNode && !deepOutput && !allContext) { if (!contextNodes.ContainsKey(((XmlNode)left).Name)) { return; } else { deep = true; } } ((XmlOutputNodeInterface)nodeInterface).WriteBeginNode(left, left, (XmlWriter)output); output.WriteAttributeString("Status", "Same"); if (deep) ((XmlOutputNodeInterface)nodeInterface).WriteNodeChildren(left, (XmlWriter)output); output.WriteEndElement(); }
protected abstract void WriteNodeSame(NodeInterface nodeInterface, object left, object right);
protected abstract void WriteNodeChange(NodeInterface leftInterface, object left, NodeInterface rightInterface, object right);
private float CompareLists(IList left, IList right, float threshold, bool output) { // Given two lists, find the elements in the list that correspond. // Two elements correspond if their 'difference metric' is less than // or equal to threshold. For the hunks of correspondent items, // recursively descend into items not truly equal. For hunks of // irreconsiliable material, raise the threshold to the next useful // level and rescan the items. if (left.Count == 0 && right.Count == 0) { return(0); } NodeComparerWrapper comparer = new NodeComparerWrapper(threshold, this); Diff diff = new Diff(left, right, comparer, comparer); int nitems = 0, ndiffs = 0; foreach (Diff.Hunk hunk in diff) { if (hunk.Same || (hunk.Left.Count == 1 && hunk.Right.Count == 1)) { // This comprises a block of correspondent items who // differ by no more than the threshold value. nitems += hunk.Left.Count; bool inSameRegion = false; for (int i = 0; i < hunk.Left.Count; i++) { object oleft = hunk.Left[i]; object oright = hunk.Right[i]; NodeInterface ileft = GetInterface(oleft); NodeInterface iright = GetInterface(oright); IList cleft = null, cright = null; cleft = ileft.GetChildren(oleft); cright = iright.GetChildren(oright); float comp = 0; if (ileft == iright) { comp = ileft.Compare(oleft, oright, this); } // If the nodes are equal, emit one node. if (ileft == iright && comp == 0) { if (output) { if (!inSameRegion) { WritePushSame(); inSameRegion = true; } WriteNodeSame(ileft, oleft, oright); } // Recurse into the lists of each node. } else if (ileft == iright && cleft != null && cright != null && cleft.Count > 0 && cright.Count > 0 && comp <= 1.0) { if (output && inSameRegion) { WritePopSame(); inSameRegion = false; } if (output) { WritePushNode(ileft, oleft, oright); } float d = CompareLists(cleft, cright, 0, output); d *= hunk.Left.Count; if (d < 1) { d = 1; } ndiffs += (int)d; if (output) { WritePopNode(); } // The nodes are not equal, so emit removed and added nodes. } else { if (output && inSameRegion) { WritePopSame(); inSameRegion = false; } if (output) { WriteNodeChange(ileft, oleft, iright, oright); } ndiffs += hunk.Left.Count; } } if (output && inSameRegion) { WritePopSame(); } } else { int ct = hunk.Left.Count + hunk.Right.Count; nitems += ct; ndiffs += ct; if (output) { bool noRecurse = comparer.minimumDifference >= 1; if (hunk.Right.Count == 0 || (hunk.Left.Count > 0 && noRecurse)) { WriteNodesRemoved(hunk.Left); } if (hunk.Left.Count == 0 || (hunk.Right.Count > 0 && noRecurse)) { WriteNodesAdded(hunk.Right); } if (hunk.Right.Count != 0 && hunk.Left.Count != 0 && !noRecurse) { CompareLists(hunk.Left, hunk.Right, comparer.minimumDifference, output); } } } } return((float)ndiffs / (float)nitems); }
public virtual void AddInterface(Type type, NodeInterface nodeInterface) { nodeInterfaces[type] = nodeInterface; }
protected override void WritePushNode(NodeInterface nodeInterface, object left, object right) { ((XmlOutputNodeInterface)nodeInterface).WriteBeginNode(left, right, output); }
protected override void WriteNodeChange(NodeInterface leftInterface, object left, NodeInterface rightInterface, object right) { AddHunk(((Node)left).count, ((Node)right).count, false); }
protected override void WriteNodeSame(NodeInterface nodeInterface, object left, object right) { AddHunk(((Node)left).count, ((Node)right).count, true); }
protected override void WritePushNode(NodeInterface nodeInterface, object left, object right) { }