using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace ln.objects.catalog { public class ODBObject : ODBEntity { private Dictionary properties = new Dictionary(); public ODBObject() :base(0x0005) { } public ODBObject(byte[] bytes) : this(bytes, 0, bytes.Length) {} public ODBObject(byte[] bytes,int offset,int length) :this() { int endOffset = offset + length; int nProps = BitConverter.ToInt32(bytes, offset); offset += 4; for (int n=0;n endOffset) throw new FormatException("object 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 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() { ODBObject clone = new ODBObject(); foreach (ODBEntity fieldName in properties.Keys) { clone[fieldName] = this[fieldName].Clone(); } return clone; } public void CloneTo(ODBObject target) { target.properties.Clear(); foreach (ODBEntity fieldName in properties.Keys) { target[fieldName] = this[fieldName].Clone(); } } public override byte[] Serialize() { MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); writer.Write(properties.Count); foreach (ODBEntity propName in properties.Keys) { ODBEntity propValue = properties[propName]; propName.Serialize(writer); propValue.Serialize(writer); } return stream.ToArray(); } public override string ToString() { return String.Format("[Object {0}]", 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(); } protected override int compare(ODBEntity e) { ODBObject other = e as ODBObject; 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; } static ODBObject() { RegisterDeserializer(0x0005, (b,o,l) => new ODBObject(b,o,l)); } } }