ln.objects/ng/Document.cs

190 lines
5.3 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using ln.objects.catalog;
namespace ln.types.odb.ng
{
public class Document : ODBEntity
{
public override ODBValue Identity => new ODBGuid(ID);
private Dictionary<ODBEntity, ODBEntity> properties = new Dictionary<ODBEntity, ODBEntity>();
public Document()
:base(0x1001)
{
ID = Guid.NewGuid();
}
public Document(Guid id)
:base(0x1001)
{
ID = id;
}
public Guid ID { get; }
public DateTime StorageTimeStamp { get; set; }
public Document(byte[] bytes)
: this(bytes, 0, bytes.Length)
{}
public Document(byte[] bytes,int offset,int length)
:this(new Guid(bytes.Slice(offset, 16)))
{
int endOffset = offset + length;
offset += 16; // GUID (!!!) -> this(...)
int nProps = BitConverter.ToInt32(bytes, offset);
offset += 4;
for (int n=0;n<nProps;n++)
{
ODBEntity propName = ODBEntity.Deserialize(bytes,ref offset);
ODBEntity propValue = ODBEntity.Deserialize(bytes, ref offset);
properties.Add(propName, propValue);
}
if (offset > endOffset)
throw new FormatException("Document deserialization read behind end of buffer");
}
public ODBEntity this[ODBEntity propName]
{
get
{
if (properties.ContainsKey(propName))
return properties[propName];
return ODBNull.Instance;
}
set
{
if (ODBNull.Instance.Equals(value))
{
if (properties.ContainsKey(propName))
properties.Remove(propName);
}
else
{
properties[propName] = value;
}
}
}
public ODBEntity this[string propName]
{
get => this[new ODBStringValue(propName)];
set => this[new ODBStringValue(propName)] = value;
}
public IEnumerable<ODBEntity> Keys => properties.Keys;
public bool Contains(string propName) => Contains(new ODBStringValue(propName));
public bool Contains(ODBEntity propName)
{
return !ODBNull.Instance.Equals(this[propName]);
}
public override ODBEntity Clone()
{
Document clone = new Document(ID);
clone.StorageTimeStamp = StorageTimeStamp;
foreach (ODBEntity fieldName in properties.Keys)
{
clone[fieldName] = this[fieldName].Clone();
}
return clone;
}
public void CloneTo(Document target)
{
target.properties.Clear();
target.StorageTimeStamp = StorageTimeStamp;
foreach (ODBEntity fieldName in properties.Keys)
{
target[fieldName] = this[fieldName].Clone();
}
}
public override byte[] GetStorageBytes()
{
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(ID.ToByteArray());
writer.Write(properties.Count);
foreach (ODBEntity propName in properties.Keys)
{
ODBEntity propValue = properties[propName];
propName.Write(writer);
propValue.Write(writer);
}
return stream.ToArray();
}
public override string ToString()
{
return String.Format("[Document ID={0} {1}]", ID.ToString(),String.Join(" ",properties.Select(kv=> String.Format("{0}={1}",kv.Key,kv.Value))));
}
public override string ToTreeString(int indent)
{
indent += 2;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendFormat("{0} Identity={1} Count={2}", GetType().Name, Identity, properties.Count);
foreach (ODBValue key in properties.Keys)
{
stringBuilder.AppendLine();
stringBuilder.AppendFormat("{0}{1,-32}: {2}", new String(' ', indent), key, properties[key].ToTreeString(indent));
}
return stringBuilder.ToString();
}
public override int GetHashCode()
{
return ID.GetHashCode();
}
public override bool Equals(object obj)
{
if (Equals(GetType(), obj.GetType()) && (obj is Document))
{
Document you = obj as Document;
return ID.Equals(you.ID);
}
return false;
}
protected override int compare(ODBEntity e)
{
Document other = e as Document;
ODBEntity[] keys = Keys.Union(other.Keys).ToArray();
foreach (ODBEntity key in keys)
{
ODBEntity mine = this[key];
ODBEntity yours = other[key];
int c = mine.CompareTo(yours);
if (c != 0)
return c;
}
return 0;
}
public override T As<T>() => (T)Mapper.Default.UnmapValue(typeof(T), this);
static Document()
{
RegisterDeserializer(0x1001, (b,o,l) => new Document(b,o,l));
}
}
}