116 lines
3.3 KiB
C#
116 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using ln.types.odb.values;
|
|
using System.Xml.Serialization;
|
|
using System.Linq;
|
|
namespace ln.types.odb.ng
|
|
{
|
|
public class DocumentChanges
|
|
{
|
|
public Document Source { get; }
|
|
public Document Destination { get; }
|
|
|
|
List<DocumentChange> changes = new List<DocumentChange>();
|
|
public DocumentChange[] Changes => changes.ToArray();
|
|
|
|
|
|
public DocumentChanges(Document src,Document dst)
|
|
{
|
|
Source = src;
|
|
Destination = dst;
|
|
|
|
diffDocument(src, dst);
|
|
}
|
|
|
|
private void diffDocument(Document src, Document dst) => diffDocument(new Stack<ODBValue>(), src, dst);
|
|
private void diffDocument(Stack<ODBValue> path,Document src,Document dst)
|
|
{
|
|
HashSet<ODBValue> keys = new HashSet<ODBValue>(src.Keys);
|
|
foreach (ODBValue key in dst.Keys)
|
|
keys.Add(key);
|
|
|
|
foreach (ODBValue key in keys)
|
|
{
|
|
path.Push(key);
|
|
diff(path, src[key], dst[key]);
|
|
path.Pop();
|
|
}
|
|
}
|
|
private void diffList(Stack<ODBValue> path,ODBList src,ODBList dst)
|
|
{
|
|
int commonLength = src.Count < dst.Count ? src.Count : dst.Count;
|
|
|
|
for (int i = 0; i < commonLength; i++)
|
|
{
|
|
path.Push(i);
|
|
diff(path, src[i], dst[i]);
|
|
path.Pop();
|
|
}
|
|
|
|
for (int i = commonLength; i < src.Count; i++)
|
|
{
|
|
path.Push(i);
|
|
diff(path, src[i], null);
|
|
path.Pop();
|
|
}
|
|
for (int i = commonLength; i < dst.Count; i++)
|
|
{
|
|
path.Push(i);
|
|
diff(path, ODBNull.Instance, dst[i]);
|
|
path.Pop();
|
|
}
|
|
}
|
|
|
|
private void diff(Stack<ODBValue> path,ODBValue srcValue,ODBValue dstValue)
|
|
{
|
|
if ((srcValue is ODBList) && (dstValue is ODBList))
|
|
{
|
|
diffList(path, srcValue as ODBList, dstValue as ODBList);
|
|
}
|
|
else if ((srcValue is Document) && (dstValue is Document))
|
|
{
|
|
diffDocument(path, srcValue as Document, dstValue as Document);
|
|
}
|
|
else if (!srcValue.Equals(dstValue))
|
|
{
|
|
changes.Add(new DocumentChange(path.Reverse(), dstValue));
|
|
}
|
|
}
|
|
|
|
|
|
public class DocumentChange
|
|
{
|
|
public ODBValue[] Path { get; }
|
|
|
|
public ODBValue Key => Path[Path.Length - 1];
|
|
public ODBValue Value { get; }
|
|
|
|
public DocumentChange(ODBValue value)
|
|
{
|
|
Value = value;
|
|
}
|
|
public DocumentChange(IEnumerable<ODBValue> path,ODBValue value)
|
|
:this(value)
|
|
{
|
|
if (path is ODBValue[])
|
|
Path = path as ODBValue[];
|
|
else
|
|
Path = path.ToArray();
|
|
}
|
|
|
|
public void Apply(Document document)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
public override string ToString()
|
|
{
|
|
return String.Format("[DocumentChange Path={0} Value={1}]", String.Join("/", Path.Select((x) => x?.AsString)), Value);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|