ln.objects/catalog/ODBEntity.cs

209 lines
7.4 KiB
C#

using ln.type;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
/**
* typeCode list
*
* 0x0000 ODBNull
* 0x0001 ODBStringValue
* 0x0002 ODBList
* 0x0003 ODBGuid
* 0x0004 ODBBool
* 0x0005 ODBObject
*
* 0x0010 ODBInteger
* 0x0011 ODBUInteger
* 0x0012 ODBLong
* 0x0013 ODBULong
*
* 0x0018 ODBDouble
*
* 0x0020 ODBTypedMapping
*
* 0x0800 ODBByteBuffer
*
* 0x1000 ODBDocument
* 0x1001 Document (ln.types.odb.ng)
*
*
*
**/
namespace ln.objects.catalog
{
public delegate ODBEntity ODBValueFactory(object value);
public delegate ODBEntity ODBDeserialize(byte[] storageBytes, int offset, int length);
/// <summary>
/// ODBEntity. The base of all ODB types.
/// </summary>
/// <remarks>The data model used by ODB can be described as follows:
///
/// Each piece of information to be used with ODB may be called an entity.
/// ODB provides support for several types of entities (e.g. numbers, strings, documents, lists,...)
/// An entity has an identity and a state.
/// Two entities of same type having the same identity are considered to be "equal".
/// Two entities of same type having the same identity may represent different states of the same entity. (different "Versions", e.g. an old and up to date
///
/// <c>ODBEntity</c> instances
/// - define identity through <c>Identity</c>
/// - may be seen as a "container" holding a certain state
///
/// <c>ODBValue</c> instances
/// extend <c>ODBEntity</c>
/// - implement <c>Identity</c> to return itself
/// - implement <c>CompareTo</c> as simple "substraction"
///
/// other <c>ODBEntity</c> subtypes
/// - implement a read-only <c>Identity</c> to return a <c>ODBvalue</c> instance
/// - implement <c>CompareTo</c> type specific without defined semantic meaning
///
///
/// </remarks>
///
public abstract class ODBEntity : IComparable<ODBEntity>
{
int storageTypeCode;
/// <summary>
/// Gets the identity of this Entity.
/// </summary>
/// <value>The identity.</value>
public virtual ODBValue Identity { get; }
/// <summary>
/// Independently clone this instance.
/// </summary>
/// <remarks>
/// For immutable values this returns the instance itself.
/// Complex ODBEntities will return a copy of themself that is completly independend of the source.
/// </remarks>
/// <returns>The clone.</returns>
public abstract ODBEntity Clone();
/// <summary>
/// Implements the internal comparison within the same subclass of ODBEntity.
/// </summary>
/// <returns>The compare.</returns>
/// <param name="other">Other.</param>
protected abstract int compare(ODBEntity other);
protected ODBEntity(int storageTypeCode)
{
this.storageTypeCode = storageTypeCode;
}
public int CompareTo(ODBEntity other)
{
if (storageTypeCode != other.storageTypeCode)
return storageTypeCode - other.storageTypeCode;
return compare(other);
}
public abstract byte[] Serialize();
public virtual void Serialize(BinaryWriter storage)
{
byte[] storageBytes = Serialize();
storage.Write(storageTypeCode);
storage.Write(storageBytes.Length);
storage.Write(storageBytes, 0, storageBytes.Length);
}
public override int GetHashCode() => Identity.GetHashCode();
public override bool Equals(object obj)
{
if (Equals(GetType(), obj.GetType()) && obj is ODBEntity)
return Equals(Identity, (obj as ODBEntity).Identity);
return false;
}
public static bool operator <(ODBEntity a, ODBEntity b) => a.CompareTo(b) < 0;
public static bool operator >(ODBEntity a, ODBEntity b) => a.CompareTo(b) > 0;
public static bool operator <=(ODBEntity a, ODBEntity b) => a.CompareTo(b) <= 0;
public static bool operator >=(ODBEntity a, ODBEntity b) => a.CompareTo(b) >= 0;
public static bool operator ==(ODBEntity a, ODBEntity b) => a is null ? b is null : a.CompareTo(b) == 0;
public static bool operator !=(ODBEntity a, ODBEntity b) => a is null ? !(b is null) : a.CompareTo(b) != 0;
//public static implicit operator ODBEntity(ValueType v)
//{
// return Mapper.Default.MapValue(v);
//}
//public static implicit operator ODBEntity(String v)
//{
// return Mapper.Default.MapValue(v);
//}
//public static ODBEntity FromNative(object v)
//{
// return Mapper.Default.MapValue(v);
//}
static Dictionary<int, ODBDeserialize> valueDeserializers = new Dictionary<int, ODBDeserialize>();
public static void RegisterDeserializer(int storageTypeCode, ODBDeserialize deserialize)
{
valueDeserializers.Add(storageTypeCode, deserialize);
}
public static ODBEntity Deserialize(byte[] buffer, ref int offset)
{
int storageTypeCode = BitConverter.ToInt32(buffer, offset);
int storageLength = BitConverter.ToInt32(buffer, offset + 4);
if (!valueDeserializers.ContainsKey(storageTypeCode))
throw new KeyNotFoundException(string.Format("StorageTypeCode 0x{0:x8} at offset 0x{1:x8}", storageTypeCode, offset));
ODBEntity value = valueDeserializers[storageTypeCode](buffer, offset + 8, storageLength);
offset += 8 + storageLength;
return value;
}
public static ODBEntity Deserialize(Stream stream)
{
int storageTypeCode = stream.ReadInteger();
int storageLength = stream.ReadInteger();
byte[] b = new byte[storageLength];
stream.Read(b, 0, storageLength);
if (valueDeserializers.ContainsKey(storageTypeCode))
return valueDeserializers[storageTypeCode](b, 0, storageLength);
else
throw new FormatException("wrong storage type code");
}
public override string ToString()
{
return string.Format("[{0} Identity={1}]", GetType().Name, Identity);
}
public string TreeString => ToTreeString(0);
public abstract string ToTreeString(int indent);
static ODBEntity()
{
RuntimeHelpers.RunClassConstructor(typeof(ODBNull).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBObject).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBList).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBStringValue).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBInteger).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBUInteger).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBLong).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBULong).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBDouble).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBGuid).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBBool).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(ODBByteBuffer).TypeHandle);
}
}
}