Fixed semantics of ODBEntities

pull/2/head
Harald Wolff 2019-09-20 11:42:02 +02:00
parent 71abdd8f00
commit 3d2f7a5ad0
39 changed files with 653 additions and 1196 deletions

78
Cast.cs 100644
View File

@ -0,0 +1,78 @@
// /**
// * File: Cast.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.Reflection;
using System.Linq;
using System.Threading;
namespace ln.types
{
public static class Cast
{
public static T To<T>(object value) => (T)To(value, typeof(T));
public static object To(object value, Type targetType)
{
if (Object.ReferenceEquals(null, value))
return null;
if (targetType.IsInstanceOfType(value))
return value;
object casted;
if (
!Implicit(value, targetType, out casted) &&
!Implicit(value, value.GetType(), targetType, out casted) &&
!Explicit(value, targetType, out casted) &&
!Explicit(value, value.GetType(), targetType, out casted)
)
throw new InvalidCastException();
return casted;
}
public static bool Implicit(object value, Type type, out object casted) => Implicit(value, type, type, out casted);
public static bool Implicit(object value, Type type, Type targetType, out object casted)
{
foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.Public | BindingFlags.Static))
{
if (methodInfo.Name.Equals("op_Implicit") && methodInfo.ReturnType.Equals(targetType))
{
ParameterInfo parameterInfo = methodInfo.GetParameters().FirstOrDefault();
if ((parameterInfo != null) && (parameterInfo.ParameterType.Equals(value.GetType())))
{
casted = methodInfo.Invoke(null, new object[] { value });
return true;
}
}
}
casted = null;
return false;
}
public static bool Explicit(object value, Type type, out object casted) => Implicit(value, type, type, out casted);
public static bool Explicit(object value, Type type, Type targetType, out object casted)
{
foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.Public | BindingFlags.Static))
{
if (methodInfo.Name.Equals("op_Explicit") && methodInfo.ReturnType.Equals(targetType))
{
ParameterInfo parameterInfo = methodInfo.GetParameters().FirstOrDefault();
if ((parameterInfo != null) && (parameterInfo.ParameterType.Equals(value.GetType())))
{
casted = methodInfo.Invoke(null, new object[] { value });
return true;
}
}
}
casted = null;
return false;
}
}
}

View File

@ -46,7 +46,7 @@
<Compile Include="odb\values\ODBGuid.cs" />
<Compile Include="odb\values\ODBNull.cs" />
<Compile Include="odb\values\ODBStringValue.cs" />
<Compile Include="odb\values\ODBValue.cs" />
<Compile Include="odb\values\ODBEntity.cs" />
<Compile Include="odb\values\ODBInteger.cs" />
<Compile Include="odb\values\ODBLong.cs" />
<Compile Include="odb\values\ODBDouble.cs" />
@ -94,7 +94,6 @@
<Compile Include="threads\ThreadHelpers.cs" />
<Compile Include="threads\DynamicPool.cs" />
<Compile Include="threads\PoolThread.cs" />
<Compile Include="odb\ng\DocumentChanges.cs" />
<Compile Include="net\IPv6.cs" />
<Compile Include="arithmetics\Words.cs" />
<Compile Include="odb\ng\storage\bases\StorageBase.cs" />
@ -112,6 +111,11 @@
<Compile Include="odb\ng\storage\fs\FSStorageContainer.cs" />
<Compile Include="threads\LockingException.cs" />
<Compile Include="odb\ng\storage\bases\ChainedStorage.cs" />
<Compile Include="odb\values\ODBValue.cs" />
<Compile Include="Cast.cs" />
<Compile Include="test\CacheTests.cs" />
<Compile Include="test\ODBTests.cs" />
<Compile Include="test\TypesTests.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="odb\" />

View File

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.types", "ln.types.csproj", "{8D9AB9A5-E513-4BA7-A450-534F6456BF28}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.types.test", "ln.types.test\ln.types.test.csproj", "{E39D8B11-7CF6-4C78-B723-F7E100121704}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.logging", "..\ln.logging\ln.logging.csproj", "{D471A566-9FB6-41B2-A777-3C32874ECD0E}"
EndProject
Global
@ -17,10 +15,6 @@ Global
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.Build.0 = Release|Any CPU
{E39D8B11-7CF6-4C78-B723-F7E100121704}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E39D8B11-7CF6-4C78-B723-F7E100121704}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E39D8B11-7CF6-4C78-B723-F7E100121704}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E39D8B11-7CF6-4C78-B723-F7E100121704}.Release|Any CPU.Build.0 = Release|Any CPU
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@ -1,269 +0,0 @@
// /**
// * File: Program.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using ln.types.odb.ng.storage;
using ln.types.odb.ng;
using ln.logging;
using System.Linq;
using ln.types.threads;
using System.Collections.Generic;
using ln.types.odb.ng.mappings;
using System.Net;
using ln.types.odb.ng.storage.session;
namespace ln.types.test
{
class MainClass
{
public static void Main(string[] args)
{
IPv6 maskTest = IPv6.Parse("255.255.255.255");
Console.WriteLine("Mask Test: {0} => {1}", maskTest.ToCIDR(), maskTest.Network.ToCIDR());
for (int n=0;n<31;n++)
{
maskTest = new IPv6(maskTest, maskTest.Netmask-1);
Console.WriteLine("Mask Test: {0} => {1}", maskTest.ToCIDR(), maskTest.Network.ToCIDR());
}
ParseIPv6("1.2.3.4");
ParseIPv6("10.112.0.0/10");
ParseIPv6("::1234:5678:9ABC:DEF0");
ParseIPv6("1234:5678:9ABC:DEF0::");
ParseIPv6("::");
ParseIPv6(IPv6.V4Space.ToCIDR());
ParseIPv6("::ffff:127.0.0.1");
ParseIPv6("2001:db8::1428:57ab");
IPv6 ip = IPv6.V4Space;
Console.WriteLine("IPv4Space: {0}",ip.ToCIDR());
for (int n = 0; n < 10; n++)
{
ip++;
Console.WriteLine("+1: {0}", ip.ToCIDR());
}
for (int n = 0; n < 32; n++)
{
ip += 256;
Console.WriteLine("+256: {0}", ip.ToCIDR());
}
for (int n = 0; n < 32; n++)
{
ip += 1<<14;
Console.WriteLine("+(1<<14): {0}", ip.ToCIDR());
}
Console.WriteLine("->IPAddress: {0}", (IPAddress)ip);
IPAddress ip4 = IPAddress.Parse("10.112.1.254");
Console.WriteLine("IP4 = {0} => {1}",ip4,(IPv6)ip4);
IPv6 ten = IPv6.Parse("::ffff:10.0.0.0/104");
Console.WriteLine("Splitting Network: {0}",ten.ToCIDR());
foreach (IPv6 subnet in ten.Split(8))
Console.WriteLine(" {0}", subnet.ToCIDR());
IPv6 v6 = IPv6.Parse("2001:470:7408::/48");
Console.WriteLine("Splitting Network: {0}", v6.ToCIDR());
foreach (IPv6 subnet in v6.Split(4))
Console.WriteLine(" {0}", subnet.ToCIDR());
}
public static void ParseIPv6(string source)
{
IPv6 ip = IPv6.Parse(source);
Console.WriteLine("IPv6: {0,40} => {1} [ {3,24} ] = {2}", source, ip.ToString(false),ip,ip.Network.ToCIDR());
Console.WriteLine("CIDR: {0}", ip.ToCIDR());
Console.WriteLine("(IPAddress) = {0}", (IPAddress)ip);
}
public static void TestStorage(IStorageContainer container)
{
using (IStorage storage = container.GetStorage("test"))
{
if (!storage.IsOpen)
storage.Open();
foreach (Guid documentID in storage.GetDocumentIDs())
{
Logging.Log(LogLevel.INFO, "DocumentID: {0}", documentID);
Document doc = storage.Load(documentID);
Logging.Log(LogLevel.INFO, doc.ToString());
doc["FeldC"] = doc["FeldC"].AsLong + 1;
storage.Save(doc);
}
Document document = new Document();
document["FeldA"] = "Ich bin das Feld A";
document["FeldB"] = "Ich bin das Feld B";
document["FeldC"] = new Random().Next();
storage.Save(document);
storage.Save(document);
}
}
public static void TestMapper(IStorageContainer container)
{
Mapper mapper = new Mapper(container);
Logging.Log(LogLevel.INFO, "Cleaning up Person store");
foreach (Guid documentID in mapper.GetDocumentIDs<Person>())
mapper.Delete<Person>(documentID);
Logging.Log(LogLevel.INFO, "Storage counts {0} entities", mapper.GetDocumentIDs<Person>().Count());
Person[] persons = new Person[15000];
for (int n = 0; n < persons.Length; n++)
persons[n] = new Person();
Logging.Log(LogLevel.INFO, "Created {0} persons", persons.Length);
Timing.Meassure("store persons", () =>
{
foreach (Person person in persons)
mapper.Save(person);
});
Guid[] documentIDs = mapper.GetDocumentIDs<Person>().ToArray();
Random random = new Random();
//for (int n = 0; n < 20; n++)
//{
// Guid choosenID = documentIDs[random.Next(documentIDs.Length)];
// Person person = mapper.Load<Person>(choosenID);
// Logging.Log(LogLevel.INFO, "Querying: {0}", person.FirstName);
// IEnumerable<Guid> ids = Timing.Meassure(() => mapper.GetDocumentIDs<Person>(Query.Equals<Person>("MiddleNames[]", person.FirstName)));
// Guid[] matchedIDs = ids.ToArray();
// Logging.Log(LogLevel.INFO, "Found {0} persons.", matchedIDs.Length);
//}
IODBMapping pMapping = mapper.GetMapping<Person>();
Person p1 = new Person();
Document pd1 = pMapping.MapValue(mapper, p1) as Document;
p1.MiddleNames[1] = "N/A";
Document pd2 = pMapping.MapValue(mapper, p1) as Document;
DocumentChanges documentChanges = new DocumentChanges(pd1, pd2);
Logging.Log(LogLevel.INFO, "DocumentChanges: \n{0}",String.Join("\n",documentChanges.Changes.Select((x)=>x.ToString())));
mapper.EnsureIndex<Person>("MiddleNames[]");
mapper.EnsureIndex<Person>("FirstName");
Logging.Log(LogLevel.INFO, "using indeces");
for (int n = 0; n < 20; n++)
{
Guid choosenID = documentIDs[random.Next(documentIDs.Length)];
Person person = mapper.Load<Person>(choosenID);
IEnumerable<Guid> ids = Timing.Meassure(() => mapper.GetDocumentIDs<Person>(Query.Equals<Person>("MiddleNames[]", person.FirstName)));
Guid[] matchedIDs = ids.ToArray();
Logging.Log(LogLevel.INFO, "Queried '{0}' with {1,4} matches", person.FirstName, matchedIDs.Length);
}
for (int n = 0; n < 20; n++)
{
Guid choosenID = documentIDs[random.Next(documentIDs.Length)];
Person person = mapper.Load<Person>(choosenID);
IEnumerable<Guid> ids = Timing.Meassure(() => mapper.GetDocumentIDs<Person>(
Query.AND(
Query.Equals<Person>("MiddleNames[]", person.FirstName),
Query.Equals<Person>("FirstName", person.FirstName)
)
)
);
Guid[] matchedIDs = ids.ToArray();
Logging.Log(LogLevel.INFO, "Queried complex '{0}' with {1,4} matches", person.FirstName, matchedIDs.Length);
}
}
}
class Person
{
static Random random = new Random();
static string[] firstNames = new string[]
{
"Harald","Simone","Viola","Antigona","Peter","Paul","Maria","Karel","Bruno","Ilse","Sonja","Ute","Justus","Niclas","Pascal"
};
static string[] lastNames = new string[]
{
"Wolff","Thobaben","Schmidt","Seefeld","van der Heide","Schuhmacher","Brommer","Günther","Freilauf","Unger","Thomalla","Christensen","Person","Forghammer"
};
public string FirstName;
public string LastName;
public String[] MiddleNames;
public int Age;
public Person()
{
FirstName = firstNames[random.Next(firstNames.Length)];
LastName = lastNames[random.Next(lastNames.Length)];
MiddleNames = new string[]
{
firstNames[random.Next(firstNames.Length)],
firstNames[random.Next(firstNames.Length)],
firstNames[random.Next(firstNames.Length)]
};
Age = random.Next(120);
}
public override string ToString()
{
return string.Format("[Person FirstName={0} LastName={1} Age={2}]",FirstName,LastName,Age);
}
}
class MapableClass
{
public int ANumber { get; set; }
public String MyString;
public MapableClass()
{
ANumber = new Random().Next();
MyString = ANumber.ToString();
}
public override string ToString()
{
return String.Format("[MapableClass ANumber={0} MyString={1}]",ANumber,MyString);
}
}
}

View File

@ -1,35 +0,0 @@
// /**
// * File: AssemblyInfo.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("ln.types.test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

View File

@ -1,53 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E39D8B11-7CF6-4C78-B723-F7E100121704}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ln.types.test</RootNamespace>
<AssemblyName>ln.types.test</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="nunit.framework">
<Package>nunit</Package>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TypesTests.cs" />
<Compile Include="ODBTests.cs" />
<Compile Include="CacheTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.types.csproj">
<Project>{8D9AB9A5-E513-4BA7-A450-534F6456BF28}</Project>
<Name>ln.types</Name>
</ProjectReference>
<ProjectReference Include="..\..\ln.logging\ln.logging.csproj">
<Project>{D471A566-9FB6-41B2-A777-3C32874ECD0E}</Project>
<Name>ln.logging</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -5,14 +5,16 @@ using ln.types.odb.values;
using System.Linq;
namespace ln.types.odb.ng
{
public class Document : ODBValue
public class Document : ODBEntity
{
private Dictionary<ODBValue, ODBValue> properties = new Dictionary<ODBValue, ODBValue>();
public override ODBValue Identity => new ODBGuid(ID);
private Dictionary<ODBEntity, ODBEntity> properties = new Dictionary<ODBEntity, ODBEntity>();
public Document()
:base(0x1001)
{
ID = Guid.NewGuid();
ID = Guid.NewGuid();
}
public Document(Guid id)
@ -21,25 +23,26 @@ namespace ln.types.odb.ng
ID = id;
}
public Guid ID { get; internal set; }
public Guid ID { get; }
public DateTime StorageTimeStamp { get; set; }
public Document(Guid documentID,byte[] bytes)
: this(documentID, bytes, 0, bytes.Length)
{ }
public Document(Guid documentID,byte[] bytes,int offset,int length)
:this(documentID)
public Document(byte[] bytes)
: this(bytes, 0, bytes.Length)
{}
public Document(byte[] bytes,int offset,int length)
:this(new Guid(bytes.Slice(offset, 16)))
{
ID = documentID;
int endOffset = offset + length;
offset += 16; // GUID (!!!) -> this(...)
int nProps = BitConverter.ToInt32(bytes, offset);
offset += 4;
for (int n=0;n<nProps;n++)
{
ODBValue propName = ODBValue.Deserialize(bytes,ref offset);
ODBValue propValue = ODBValue.Deserialize(bytes, ref offset);
ODBEntity propName = ODBEntity.Deserialize(bytes,ref offset);
ODBEntity propValue = ODBEntity.Deserialize(bytes, ref offset);
properties.Add(propName, propValue);
}
@ -47,7 +50,7 @@ namespace ln.types.odb.ng
throw new FormatException("Document deserialization read behind end of buffer");
}
public ODBValue this[ODBValue propName]
public ODBEntity this[ODBEntity propName]
{
get
{
@ -68,22 +71,26 @@ namespace ln.types.odb.ng
}
}
}
public ODBEntity this[string propName]
{
get => this[new ODBStringValue(propName)];
set => this[new ODBStringValue(propName)] = value;
}
public IEnumerable<ODBValue> Keys => properties.Keys;
public IEnumerable<ODBEntity> Keys => properties.Keys;
public override int CompareLevel => 128;
public bool Contains(ODBValue propName)
public bool Contains(string propName) => Contains(new ODBStringValue(propName));
public bool Contains(ODBEntity propName)
{
return !ODBNull.Instance.Equals(this[propName]);
}
public override ODBValue Clone()
public override ODBEntity Clone()
{
Document clone = new Document(ID);
clone.StorageTimeStamp = StorageTimeStamp;
foreach (ODBValue fieldName in properties.Keys)
foreach (ODBEntity fieldName in properties.Keys)
{
clone[fieldName] = this[fieldName].Clone();
}
@ -94,24 +101,25 @@ namespace ln.types.odb.ng
{
target.properties.Clear();
target.StorageTimeStamp = StorageTimeStamp;
foreach (ODBValue fieldName in properties.Keys)
foreach (ODBEntity fieldName in properties.Keys)
{
target[fieldName] = this[fieldName].Clone();
}
}
public override byte[] ToStorage()
public override byte[] GetStorageBytes()
{
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(ID.ToByteArray());
writer.Write(properties.Count);
foreach (ODBValue propName in properties.Keys)
foreach (ODBEntity propName in properties.Keys)
{
ODBValue propValue = properties[propName];
propName.Store(writer);
propValue.Store(writer);
ODBEntity propValue = properties[propName];
propName.Write(writer);
propValue.Write(writer);
}
return stream.ToArray();
@ -136,37 +144,17 @@ namespace ln.types.odb.ng
return false;
}
public bool ContentEquals(Document other)
protected override int compare(ODBEntity e)
{
if (object.ReferenceEquals(null, other))
return false;
Document other = e as Document;
ODBEntity[] keys = Keys.Union(other.Keys).ToArray();
ODBValue[] keys = Keys.Union(other.Keys).ToArray();
foreach (ODBValue key in keys)
foreach (ODBEntity key in keys)
{
ODBValue value = this[key];
if (!value.ValueEquals(other[key]))
return false;
}
return true;
}
ODBEntity mine = this[key];
ODBEntity yours = other[key];
public override bool ValueEquals(ODBValue other)
{
return ContentEquals(other as Document);
}
public int CompareContent(Document other)
{
ODBValue[] keys = Keys.Union(other.Keys).ToArray();
foreach (ODBValue key in keys)
{
ODBValue mine = this[key];
ODBValue yours = other[key];
int c = ODBValue.Compare(mine, yours);
int c = mine.CompareTo(yours);
if (c != 0)
return c;
@ -174,18 +162,11 @@ namespace ln.types.odb.ng
return 0;
}
public override int CompareInType(ODBValue other)
{
return CompareContent(other as Document);
}
public override int CompareValueInType(ODBValue other)
{
return CompareContent(other as Document);
}
public override T As<T>() => (T)Mapper.Default.UnmapValue(typeof(T), this);
static Document()
{
RegisterDeserializer(0x1001, (b,o,l) => new Document(Guid.Empty,b,o+16,l));
RegisterDeserializer(0x1001, (b,o,l) => new Document(b,o+16,l));
}
}
}

View File

@ -1,115 +0,0 @@
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);
}
}
}
}

View File

@ -4,7 +4,7 @@ namespace ln.types.odb.ng
{
public interface IODBMapping
{
ODBValue MapValue(Mapper mapper, object value);
object UnmapValue(Mapper mapper, ODBValue oval);
ODBEntity MapValue(Mapper mapper, object value);
object UnmapValue(Mapper mapper, ODBEntity oval);
}
}

View File

@ -118,8 +118,8 @@ namespace ln.types.odb.ng
return storage.GetDocumentIDs();
}
public IEnumerable<Guid> GetDocumentIDs<T>(string path, Predicate<ODBValue> predicate) => GetDocumentIDs(typeof(T), path, predicate);
public IEnumerable<Guid> GetDocumentIDs(Type type, string path, Predicate<ODBValue> predicate)
public IEnumerable<Guid> GetDocumentIDs<T>(string path, Predicate<ODBEntity> predicate) => GetDocumentIDs(typeof(T), path, predicate);
public IEnumerable<Guid> GetDocumentIDs(Type type, string path, Predicate<ODBEntity> predicate)
{
IStorage storage = StorageContainer.GetStorage(type.FullName);
return storage.GetDocumentIDs(path,predicate);

View File

@ -12,10 +12,10 @@ using ln.types.odb.ng.storage.fs;
namespace ln.types.odb.ng
{
public delegate ODBValue ODBMap(Mapper mapper, object value);
public delegate object ODBUnmap(Mapper mapper, ODBValue oval);
public delegate ODBValue ODBMap<T>(Mapper mapper, T value);
public delegate T ODBUnmap<T>(Mapper mapper, ODBValue oval);
public delegate ODBEntity ODBMap(Mapper mapper, object value);
public delegate object ODBUnmap(Mapper mapper, ODBEntity oval);
public delegate ODBEntity ODBMap<T>(Mapper mapper, T value);
public delegate T ODBUnmap<T>(Mapper mapper, ODBEntity oval);
public partial class Mapper : IDisposable
{
@ -39,74 +39,74 @@ namespace ln.types.odb.ng
RegisterMapping<string>(
(mapper, value) => new ODBStringValue(value),
(mapper, oval) => oval.AsString
(mapper, oval) => oval.As<String>()
);
RegisterMapping<int>(
(mapper, value) => new ODBInteger(value),
(mapper, oval) => oval.AsInt
(mapper, oval) => oval.As<int>()
);
RegisterMapping<short>(
(mapper, value) => new ODBInteger(value),
(mapper, oval) => oval.AsShort
(mapper, oval) => oval.As<short>()
);
RegisterMapping<byte>(
(mapper, value) => new ODBInteger(value),
(mapper, oval) => oval.AsByte
(mapper, oval) => oval.As<Byte>()
);
RegisterMapping<uint>(
(mapper, value) => new ODBUInteger(value),
(mapper, oval) => oval.AsUInt
(mapper, oval) => oval.As<uint>()
);
RegisterMapping<ushort>(
(mapper, value) => new ODBUInteger(value),
(mapper, oval) => oval.AsUShort
(mapper, oval) => oval.As<ushort>()
);
RegisterMapping<char>(
(mapper, value) => new ODBUInteger(value),
(mapper, oval) => oval.AsChar
(mapper, oval) => oval.As<Char>()
);
RegisterMapping<double>(
(mapper, value) => new ODBDouble(value),
(mapper, oval) => oval.AsDouble
(mapper, oval) => oval.As<double>()
);
RegisterMapping<float>(
(mapper, value) => new ODBDouble(value),
(mapper, oval) => oval.AsFloat
(mapper, oval) => oval.As<float>()
);
RegisterMapping<DateTime>(
(mapper, value) => new ODBLong(DateTime.MinValue.Equals(value) ? 0 : new DateTimeOffset(value.ToUniversalTime()).ToUnixTimeMilliseconds() ),
(mapper, oval) => DateTimeOffset.FromUnixTimeMilliseconds(oval.AsLong).DateTime
(mapper, oval) => DateTimeOffset.FromUnixTimeMilliseconds(oval.As<long>()).DateTime
);
RegisterMapping<TimeSpan>(
(mapper, value) => new ODBDouble(value.TotalMilliseconds),
(mapper, oval) => TimeSpan.FromMilliseconds(oval.AsDouble)
(mapper, oval) => TimeSpan.FromMilliseconds(oval.As<double>())
);
RegisterMapping<Guid>(
(mapper, value) => new ODBGuid(value),
(mapper, oval) => oval.AsGuid
(mapper, oval) => oval.As<Guid>()
);
RegisterMapping<long>(
(mapper, value) => new ODBLong(value),
(mapper, oval) => oval.AsLong
(mapper, oval) => oval.As<long>()
);
RegisterMapping<ulong>(
(mapper, value) => new ODBULong(value),
(mapper, oval) => oval.AsULong
(mapper, oval) => oval.As<ulong>()
);
RegisterMapping<bool>(
(mapper, value) => new ODBBool(value),
(mapper, oval) => oval.AsBool
(mapper, value) => (bool)value ? ODBBool.True : ODBBool.False,
(mapper, oval) => oval.As<bool>()
);
RegisterMapping<IPv4>(
(mapper, value) => new ODBUInteger(value.AsUInt),
(mapper, oval) => new IPv4(oval.AsUInt)
(mapper, oval) => new IPv4(oval.As<uint>())
);
ObjectMapping = new mappings.ObjectMapping();
@ -216,7 +216,7 @@ namespace ln.types.odb.ng
// return null;
//}
public virtual ODBValue MapValue(object value)
public virtual ODBEntity MapValue(object value)
{
if (value == null)
return ODBNull.Instance;
@ -227,7 +227,7 @@ namespace ln.types.odb.ng
throw new NotSupportedException(String.Format("Can't map {0} ({1})",value.GetType(),value));
}
public virtual object UnmapValue(Type targetType,ODBValue value)
public virtual object UnmapValue(Type targetType,ODBEntity value)
{
if (ODBNull.Instance.Equals(value))
return null;
@ -235,22 +235,23 @@ namespace ln.types.odb.ng
if (value is Document)
{
Document doc = value as Document;
String asmname = doc["__asm__"].AsString;
String typename = doc["__type__"].AsString;
String asmname = doc["__asm__"].As<string>();
String typename = doc["__type__"].As<string>();
if (typename != null)
targetType = Type.GetType(String.Format("{0}, {1}",typename,asmname)); //Assembly.Load(asmname).GetType(typename);
} else if (value is ODBTypedValue)
{
ODBTypedValue typedValue = value as ODBTypedValue;
targetType = typedValue.TargetType;
}
//else if (value is ODBTypedValue)
//{
// ODBTypedValue typedValue = value as ODBTypedValue;
// targetType = typedValue.TargetType;
//}
IODBMapping mapping = GetMapping(targetType);
if (mapping != null)
return mapping.UnmapValue(this,value);
return Convert.ChangeType(value.Value, targetType);
return value.As(targetType);
}
public virtual object TryImplicitMapping(object value,Type targetType)

View File

@ -36,37 +36,37 @@ namespace ln.types.odb.ng
}
public static Query Equals<T>(string propertyName, object value) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), Mapper.Default.MapValue(value));
public static Query Equals(String propertyName, ODBValue value)
public static Query Equals(String propertyName, ODBEntity value)
{
if (object.ReferenceEquals(value,null))
value = ODBNull.Instance;
return IF(propertyName, (v) => value.ValueEquals(v));
return IF(propertyName, (v) => value.Equals(v));
}
public static Query EqualsNot<T>(string propertyName, ODBValue value) => EqualsNot(IndexPath.TranslatePropertyPath(typeof(T), propertyName), value);
public static Query EqualsNot(String propertyName, ODBValue value)
public static Query EqualsNot<T>(string propertyName, ODBEntity value) => EqualsNot(IndexPath.TranslatePropertyPath(typeof(T), propertyName), value);
public static Query EqualsNot(String propertyName, ODBEntity value)
{
if (object.ReferenceEquals(value, null))
value = ODBNull.Instance;
return IF(propertyName, (v) => !value.ValueEquals(v));
return IF(propertyName, (v) => !value.Equals(v));
}
public static Query Equals<T>(string propertyName, ODBValue[] values) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), values);
public static Query Equals(String propertyName, ODBValue[] values)
public static Query Equals<T>(string propertyName, ODBEntity[] values) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), values);
public static Query Equals(String propertyName, ODBEntity[] values)
{
return IF(propertyName, (v) => values.Contains(v));
}
public static Query Contains<T, A>(string propertyName, IEnumerable<A> values)
{
ODBValue[] oValues = values.Select(v => Mapper.Default.MapValue(v)).ToArray();
ODBEntity[] oValues = values.Select(v => Mapper.Default.MapValue(v)).ToArray();
return IF(IndexPath.TranslatePropertyPath(typeof(T), propertyName), v => oValues.Contains(v));
}
public static Query IF<T>(string propertyName, Predicate<ODBValue> predicate) => IF(IndexPath.TranslatePropertyPath(typeof(T),propertyName), predicate);
public static Query IF(string propertyName,Predicate<ODBValue> predicate)
public static Query IF<T>(string propertyName, Predicate<ODBEntity> predicate) => IF(IndexPath.TranslatePropertyPath(typeof(T),propertyName), predicate);
public static Query IF(string propertyName,Predicate<ODBEntity> predicate)
{
return new IMPL.IF(propertyName, predicate);
}
@ -79,9 +79,9 @@ namespace ln.types.odb.ng
public class IF : Query
{
public string PropertyName { get; }
public Predicate<ODBValue> Predicate { get; }
public Predicate<ODBEntity> Predicate { get; }
public IF(string propertyName,Predicate<ODBValue> predicate)
public IF(string propertyName,Predicate<ODBEntity> predicate)
{
PropertyName = propertyName;
Predicate = predicate;

View File

@ -18,14 +18,14 @@ namespace ln.types.odb.ng.index
IndexName = IndexPath.Complete;
}
public virtual void Replace(Guid documentID, ODBValue value) {
public virtual void Replace(Guid documentID, ODBEntity value) {
Remove(documentID);
Add(documentID, value);
}
public abstract void Add(Guid documentID, ODBValue value);
public abstract void Add(Guid documentID, ODBEntity value);
public abstract void Remove(Guid documentID);
public abstract IEnumerable<Guid> GetDocumentIDs(Predicate<ODBValue> predicate);
public abstract IEnumerable<Guid> GetDocumentIDs(Predicate<ODBEntity> predicate);
public abstract bool LoadIndex(string basePath, long lastCloseTimestamp);
public abstract bool SaveIndex(string basePath, long lastCloseTimestamp);

View File

@ -25,16 +25,16 @@ namespace ln.types.odb.ng.index
public abstract bool Ensure(Path path);
public abstract bool Indexed(Path path);
public virtual void Replace(Guid documentID, ODBValue value)
public virtual void Replace(Guid documentID, ODBEntity value)
{
Remove(documentID);
Add(documentID, value);
}
public abstract void Add(Guid documentID, ODBValue value);
public abstract void Add(Guid documentID, ODBEntity value);
public abstract void Remove(Guid documentID);
public abstract IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBValue> predicate);
public virtual IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate)
public abstract IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate);
public virtual IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate)
{
return GetDocumentIDs(SplitPath(path), predicate);
}
@ -49,7 +49,7 @@ namespace ln.types.odb.ng.index
{
}
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBValue> predicate)
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate)
{
return children[path.Element].GetDocumentIDs(path.Next, predicate);
}
@ -72,14 +72,14 @@ namespace ln.types.odb.ng.index
next.Remove(documentID);
}
public override void Add(Guid documentID, ODBValue value)
public override void Add(Guid documentID, ODBEntity value)
{
foreach (string childName in children.Keys)
{
children[childName].Add(documentID, (value as Document)[childName]);
}
}
public override void Replace(Guid documentID, ODBValue value)
public override void Replace(Guid documentID, ODBEntity value)
{
foreach (string childName in children.Keys)
{
@ -126,7 +126,7 @@ namespace ln.types.odb.ng.index
}
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBValue> predicate)
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate)
{
return nextPath.GetDocumentIDs(path.Next, predicate);
}
@ -135,10 +135,10 @@ namespace ln.types.odb.ng.index
{
nextPath.Remove(documentID);
}
public override void Add(Guid documentID, ODBValue value)
public override void Add(Guid documentID, ODBEntity value)
{
if (!ODBNull.Instance.Equals(value))
foreach (ODBValue v in ((ODBList)value))
foreach (ODBEntity v in ((ODBList)value))
{
nextPath.Add(documentID, v);
}
@ -159,7 +159,7 @@ namespace ln.types.odb.ng.index
public override bool Indexed(Path path) => true;
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBValue> predicate)
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate)
{
return index.GetDocumentIDs(predicate);
}
@ -169,11 +169,11 @@ namespace ln.types.odb.ng.index
index.Remove(documentID);
}
public override void Add(Guid documentID, ODBValue value)
public override void Add(Guid documentID, ODBEntity value)
{
index.Add(documentID, value);
}
public override void Replace(Guid documentID, ODBValue value)
public override void Replace(Guid documentID, ODBEntity value)
{
index.Replace(documentID, value);
}

View File

@ -10,18 +10,18 @@ namespace ln.types.odb.ng.index
{
public class SimpleIndex : Index
{
BTreeValueList<ODBValue, Guid> valueIndex = new BTreeValueList<ODBValue, Guid>();
BTreeValueList<Guid, ODBValue> reverseIndex = new BTreeValueList<Guid, ODBValue>();
BTreeValueList<ODBEntity, Guid> valueIndex = new BTreeValueList<ODBEntity, Guid>();
BTreeValueList<Guid, ODBEntity> reverseIndex = new BTreeValueList<Guid, ODBEntity>();
public SimpleIndex(Path path)
: base(path)
{
}
public override IEnumerable<Guid> GetDocumentIDs(Predicate<ODBValue> predicate)
public override IEnumerable<Guid> GetDocumentIDs(Predicate<ODBEntity> predicate)
{
HashSet<Guid> matchedIDs = new HashSet<Guid>();
foreach (ODBValue value in valueIndex.Keys)
foreach (ODBEntity value in valueIndex.Keys)
{
if (predicate(value))
foreach (Guid id in valueIndex[value])
@ -30,7 +30,7 @@ namespace ln.types.odb.ng.index
return matchedIDs;
}
public override void Add(Guid documentID, ODBValue value)
public override void Add(Guid documentID, ODBEntity value)
{
valueIndex.Add(value, documentID);
reverseIndex.Add(documentID, value);
@ -40,7 +40,7 @@ namespace ln.types.odb.ng.index
{
if (reverseIndex.ContainsKey(documentID))
{
foreach (ODBValue value in reverseIndex[documentID].ToArray())
foreach (ODBEntity value in reverseIndex[documentID].ToArray())
{
valueIndex.Remove(value, documentID);
}
@ -54,9 +54,9 @@ namespace ln.types.odb.ng.index
using (FileStream fileStream = new FileStream(System.IO.Path.Combine(basePath, String.Format("{0}.idx", IndexName)), FileMode.Open))
{
byte[] indexBytes = fileStream.ReadBytes((int)fileStream.Length);
Document indexDocument = new Document(Guid.Empty, indexBytes, 16, indexBytes.Length - 16);
Document indexDocument = new Document(indexBytes, 16, indexBytes.Length - 16);
long idxLastCloseTimestamp = indexDocument["LastCloseTimestamp"].AsLong;
long idxLastCloseTimestamp = indexDocument["LastCloseTimestamp"].As<long>();
if (idxLastCloseTimestamp != lastCloseTimestamp)
{
Logging.Log(LogLevel.WARNING, "Index timestamp {0} is not matching ( {1} != {2} )", IndexName, idxLastCloseTimestamp, lastCloseTimestamp);
@ -64,13 +64,13 @@ namespace ln.types.odb.ng.index
}
else
{
foreach (ODBValue key in indexDocument.Keys)
foreach (ODBEntity key in indexDocument.Keys)
{
if (key is ODBGuid)
{
Guid documentID = key.AsGuid;
Guid documentID = key.As<Guid>();
ODBList valueList = indexDocument[key] as ODBList;
foreach (ODBValue value in valueList)
foreach (ODBEntity value in valueList)
{
Add(documentID, value);
}
@ -85,16 +85,16 @@ namespace ln.types.odb.ng.index
public override bool SaveIndex(string basePath, long lastCloseTimestamp)
{
Document indexDocument = new Document();
indexDocument["LastCloseTimestamp"] = lastCloseTimestamp;
indexDocument["LastCloseTimestamp"] = new ODBLong(lastCloseTimestamp);
foreach (Guid documentID in reverseIndex.Keys)
{
ODBList valueList = new ODBList();
valueList.AddRange(reverseIndex[documentID]);
indexDocument[documentID] = valueList;
indexDocument[new ODBGuid(documentID)] = valueList;
}
byte[] indexBytes = indexDocument.ToStorage();
byte[] indexBytes = indexDocument.GetStorageBytes();
using (FileStream fileStream = new FileStream(System.IO.Path.Combine(basePath, String.Format("{0}.idx", IndexName)), FileMode.Create))
{

View File

@ -65,7 +65,7 @@ namespace ln.types.odb.ng.mappings
return false;
}
public object UnmapValue(Mapper mapper,ODBValue oval)
public object UnmapValue(Mapper mapper,ODBEntity oval)
{
Document document = oval as Document;
object o = Activator.CreateInstance(MappedType, true);
@ -107,13 +107,13 @@ namespace ln.types.odb.ng.mappings
public Document MapDocument(Mapper mapper,Guid documentID,object value)
{
Document document = new Document(documentID);
document["__asm__"] = value.GetType().Assembly.GetName().Name;
document["__type__"] = value.GetType().FullName;
document["__asm__"] = new ODBStringValue(value.GetType().Assembly.GetName().Name);
document["__type__"] = new ODBStringValue(value.GetType().FullName);
foreach (FieldInfo fieldInfo in mappedFields)
{
object fv = fieldInfo.GetValue(value);
ODBValue ov = null;
ODBEntity ov = null;
if (false) //(fieldInfo.GetCustomAttribute<ByReferenceAttribute>() != null)
{
@ -135,7 +135,7 @@ namespace ln.types.odb.ng.mappings
return document;
}
public ODBValue MapValue(Mapper mapper,object value)
public ODBEntity MapValue(Mapper mapper,object value)
{
if (Object.ReferenceEquals(value, null))
return ODBNull.Instance;
@ -157,20 +157,20 @@ namespace ln.types.odb.ng.mappings
public class ObjectMapping : IODBMapping
{
public ODBValue MapValue(Mapper mapper, object value)
public ODBEntity MapValue(Mapper mapper, object value)
{
return new Document();
}
public object UnmapValue(Mapper mapper, ODBValue oval)
public object UnmapValue(Mapper mapper, ODBEntity oval)
{
if (oval is Document)
{
Document document = oval as Document;
if (!document.Contains("__type__"))
if (!document.Contains(new ODBStringValue("__type__")))
return new object();
Type dType = Type.GetType(String.Format("{0}, {1}",document["__type__"].AsString, document["__asm__"].AsString)); //Assembly.Load(document["__asm__"].AsString).GetType(document["__type__"].AsString);
Type dType = Type.GetType(String.Format("{0}, {1}",document["__type__"].As<String>(), document["__asm__"].As<String>()));
return mapper.UnmapValue(dType, oval);
} else if (oval is ODBList)
{
@ -220,10 +220,12 @@ namespace ln.types.odb.ng.mappings
return array;
}
else
else if (oval is ODBValue)
{
return oval.Value;
return (oval as ODBValue).Value;
}
throw new NotImplementedException();
}
}

View File

@ -13,7 +13,7 @@ namespace ln.types.odb.ng.mappings
{
}
public ODBValue MapValue(Mapper mapper, object value)
public ODBEntity MapValue(Mapper mapper, object value)
{
Type dType = value.GetType();
@ -22,8 +22,8 @@ namespace ln.types.odb.ng.mappings
IDictionary dictionary = value as IDictionary;
Document document = new Document();
document["__asm__"] = value.GetType().Assembly.GetName().Name;
document["__type__"] = value.GetType().FullName;
document["__asm__"] = new ODBStringValue(value.GetType().Assembly.GetName().Name);
document["__type__"] = new ODBStringValue(value.GetType().FullName);
Document kTypes = new Document();
Document vTypes = new Document();
@ -34,21 +34,21 @@ namespace ln.types.odb.ng.mappings
foreach (object key in dictionary.Keys)
{
object v = dictionary[key];
ODBValue okey = mapper.MapValue(key);
ODBEntity okey = mapper.MapValue(key);
document[okey] = mapper.MapValue(v);
kTypes[okey] = Mapper.GetTypeName(key?.GetType());
vTypes[okey] = Mapper.GetTypeName(v?.GetType());
kTypes[okey] = new ODBStringValue(Mapper.GetTypeName(key?.GetType()));
vTypes[okey] = new ODBStringValue(Mapper.GetTypeName(v?.GetType()));
}
return document;
}
throw new NotImplementedException();
}
public object UnmapValue(Mapper mapper, ODBValue oval)
public object UnmapValue(Mapper mapper, ODBEntity oval)
{
Document document = oval as Document;
Type dType = Type.GetType(String.Format("{0}, {1}",document["__type__"].AsString,document["__asm__"].AsString)); //;Assembly.Load(document["__asm__"].AsString).GetType(document["__type__"].AsString);
Type dType = Type.GetType(String.Format("{0}, {1}",document["__type__"].As<String>(),document["__asm__"].As<String>())); //;Assembly.Load(document["__asm__"].AsString).GetType(document["__type__"].AsString);
if (dType.IsGenericType)
{
@ -62,13 +62,13 @@ namespace ln.types.odb.ng.mappings
Document ktypes = document.Contains("__ktypes__") ? document["__ktypes__"] as Document : new Document();
Document vtypes = document.Contains("__vtypes__") ? document["__vtypes__"] as Document : new Document();
foreach (ODBValue key in document.Keys)
foreach (ODBEntity key in document.Keys)
{
string skey = key.AsString;
string skey = key.As<String>();
if (!skey.StartsWith("__", StringComparison.InvariantCulture) || !skey.EndsWith("__",StringComparison.InvariantCulture))
{
Type kt = ktypes.Contains(key) ? Type.GetType(ktypes[key].AsString) : kType;
Type vt = vtypes.Contains(key) ? Type.GetType(vtypes[key].AsString) : vType;
Type kt = ktypes.Contains(key) ? Type.GetType(ktypes[key].As<String>()) : kType;
Type vt = vtypes.Contains(key) ? Type.GetType(vtypes[key].As<String>()) : vType;
dictionary.Add(mapper.UnmapValue(kt, key), mapper.UnmapValue(vt, document[key]));
}

View File

@ -77,7 +77,7 @@ namespace ln.types.odb.ng.mappings
return list;
}
public object UnmapValue(Mapper mapper, ODBValue oval)
public object UnmapValue(Mapper mapper, ODBEntity oval)
{
if (TargetType.IsArray)
return UnmapArray(mapper, (ODBList)oval);
@ -97,7 +97,7 @@ namespace ln.types.odb.ng.mappings
throw new NotImplementedException();
}
public ODBValue MapValue(Mapper mapper, object value)
public ODBEntity MapValue(Mapper mapper, object value)
{
if (TargetType.IsArray)
return MapArray(mapper, (Array)value);
@ -131,7 +131,7 @@ namespace ln.types.odb.ng.mappings
public IEnumerator<T> GetEnumerator()
{
foreach (ODBValue item in list)
foreach (ODBEntity item in list)
yield return (T)mapper.UnmapValue(TargetType, item);
}

View File

@ -13,12 +13,12 @@ namespace ln.types.odb.ng.mappings
this.unmap = unmap;
}
public ODBValue MapValue(Mapper mapper, object value)
public ODBEntity MapValue(Mapper mapper, object value)
{
return map(mapper, value);
}
public object UnmapValue(Mapper mapper, ODBValue oval)
public object UnmapValue(Mapper mapper, ODBEntity oval)
{
return unmap(mapper, oval);
}

View File

@ -23,7 +23,7 @@ namespace ln.types.odb.ng.storage
bool Contains(Guid documentID);
IEnumerable<Guid> GetDocumentIDs();
IEnumerable<Guid> GetDocumentIDs(string path,Predicate<ODBValue> predicate);
IEnumerable<Guid> GetDocumentIDs(string path,Predicate<ODBEntity> predicate);
DateTime GetStorageTimestamp(Guid documentID);
void EnsureIndex(params string[] path);

View File

@ -78,9 +78,9 @@ namespace ln.types.odb.ng.storage
freeAreas.Add(fileArea);
}
}
public OrganizedFileArea Store(ODBValue value)
public OrganizedFileArea Store(ODBEntity value)
{
byte[] storageBytes = value.ToStorage();
byte[] storageBytes = value.GetStorageBytes();
return Store(storageBytes);
}
public OrganizedFileArea Store(byte[] bytes)

View File

@ -65,7 +65,7 @@ namespace ln.types.odb.ng.storage.bases
return Storage.GetDocumentIDs();
}
public virtual IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate)
public virtual IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate)
{
return Storage.GetDocumentIDs(path, predicate);
}

View File

@ -69,7 +69,7 @@ namespace ln.types.odb.ng.storage.bases
/* Enumeration */
public abstract IEnumerable<Guid> GetDocumentIDs();
public abstract IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate);
public abstract IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate);
/* Indeces */
public abstract void EnsureIndex(params string[] path);

View File

@ -52,7 +52,7 @@ namespace ln.types.odb.ng.storage.cache
public override void EnsureIndex(params string[] path) => storage.EnsureIndex(path);
public override IEnumerable<Guid> GetDocumentIDs() => storage.GetDocumentIDs();
public override IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate) => storage.GetDocumentIDs(path, predicate);
public override IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate) => storage.GetDocumentIDs(path, predicate);
public override Document Load(Guid documentID)
{

View File

@ -119,9 +119,9 @@ namespace ln.types.odb.ng.storage
byte[] indexLstBytes = indexLst.ReadBytes((int)indexLst.Length);
ODBList idxList = new ODBList(indexLstBytes, 0, indexLstBytes.Length);
foreach (ODBValue indexName in idxList)
foreach (ODBEntity indexName in idxList)
{
indexRoot.Ensure(IndexPath.SplitPath(indexName.AsString));
indexRoot.Ensure(IndexPath.SplitPath(indexName.As<String>()));
}
}
@ -165,10 +165,10 @@ namespace ln.types.odb.ng.storage
}
ODBList indexList = new ODBList();
indexList.AddRange(indexNames.Select((x) => ODBValue.FromNative(x)));
indexList.AddRange(indexNames.Select((x) => ODBEntity.FromNative(x)));
FileStream indexLst = new FileStream(System.IO.Path.Combine(StoragePath, "indeces.lst"), FileMode.Create);
indexLst.WriteBytes(indexList.ToStorage());
indexLst.WriteBytes(indexList.GetStorageBytes());
indexLst.Close();
indexLst.Dispose();
}
@ -203,7 +203,7 @@ namespace ln.types.odb.ng.storage
try
{
return new Document(segment.ID, storageBytes) { StorageTimeStamp = segment.TimeStamp, };
return new Document(storageBytes) { StorageTimeStamp = segment.TimeStamp, };
} catch (Exception e)
{
Logging.Log(LogLevel.DEBUG, "Exception while Deserializing Document from FSStorage: {1} ID={0}",segment.ID,StoragePath);
@ -220,7 +220,7 @@ namespace ln.types.odb.ng.storage
if (GetDocumentLocked(document.ID))
throw new LockingException();
byte[] storageBytes = document.ToStorage();
byte[] storageBytes = document.GetStorageBytes();
SegmentedFile.Segment segment = PopUnusedSegment(storageBytes.Length);
if (segment == null)
@ -299,7 +299,7 @@ namespace ln.types.odb.ng.storage
return default(DateTime);
}
public override IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate)
public override IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate)
{
lock (this)
{

View File

@ -8,39 +8,36 @@
// *
// **/
using System;
using NUnit.Framework;
namespace ln.types.odb.values
{
public class ODBBool : ODBValue
{
public override int CompareLevel => 254;
public static ODBBool True = new ODBBool(true);
public static ODBBool False = new ODBBool(false);
public ODBBool()
:base(0x04)
{}
bool isTrue;
public ODBBool(bool b)
:this()
private ODBBool(bool b)
:base(0x04,b)
{
Value = b;
isTrue = b;
}
public override byte[] ToStorage()
{
return new byte[] { AsBool ? (byte)0xFF : (byte)0x00 };
}
public override byte[] GetStorageBytes() => new byte[] { isTrue ? (byte)0xFF : (byte)0x00 };
public override int CompareInType(ODBValue other)
protected override int compare(ODBEntity other)
{
if (AsBool == other.AsBool)
if (Object.ReferenceEquals(this,other))
return 0;
if (AsBool)
if (isTrue)
return 1;
return -1;
}
static ODBBool()
{
RegisterDeserializer(0x04, (b, o, l) => new ODBBool(b[o] != 0));
RegisterDeserializer(0x04, (b, o, l) => (b[o] != 0) ? True : False);
}
}
}

View File

@ -3,27 +3,15 @@ namespace ln.types.odb.values
{
public class ODBDouble : ODBValue
{
public override int CompareLevel => 2;
public ODBDouble()
:base(0x18)
{
}
public ODBDouble(double value)
: this()
{
Value = value;
}
:base(0x18,value)
{}
public override byte[] ToStorage()
public override byte[] GetStorageBytes() => BitConverter.GetBytes((double)Value);
protected override int compare(ODBEntity other)
{
return BitConverter.GetBytes(AsDouble);
}
public override int CompareInType(ODBValue other)
{
double a = AsDouble;
double b = other.AsDouble;
double a = (double)Value;
double b = (double)(other as ODBValue).Value;
if (Math.Abs(a - b) < double.Epsilon)
return 0;
@ -34,9 +22,7 @@ namespace ln.types.odb.values
static ODBDouble()
{
RegisterDeserializer(0x0018, (b, o, l) => BitConverter.ToDouble(b, o));
//RegisterValueFactory(typeof(double), v => new ODBDouble((double)v));
//RegisterValueFactory(typeof(float), v => new ODBDouble((double)v));
RegisterDeserializer(0x0018, (b, o, l) => new ODBDouble(BitConverter.ToDouble(b, o)));
}
}
}

View File

@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.IO;
using ln.types.odb.ng;
using System.Reflection;
using System.Runtime.CompilerServices;
/**
* typeCode list
*
* 0x0000 ODBNull
* 0x0001 ODBStringValue
* 0x0002 ODBList
* 0x0003 ODBGuid
* 0x0004 ODBBool
*
* 0x0010 ODBInteger
* 0x0011 ODBUInteger
* 0x0012 ODBLong
* 0x0013 ODBULong
*
* 0x0018 ODBDouble
*
* 0x0020 ODBTypedMapping
*
* 0x1000 ODBDocument
* 0x1001 Document (ln.types.odb.ng)
*
*
*
**/
namespace ln.types.odb.values
{
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>
///
/// </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>
/// Return a .NET native value / object that semantically equals this ODBEntity instance.
/// </summary>
/// <returns>The native .NET value</returns>
/// <typeparam name="T">The type to which this ODBEntity should be casted/converted.</typeparam>
public abstract T As<T>();
/// <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[] GetStorageBytes();
public virtual void Write(BinaryWriter storage)
{
byte[] storageBytes = GetStorageBytes();
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 (obj is ODBEntity)
return Identity.Equals((obj as ODBEntity).Identity);
return false;
}
public virtual object As(Type targetType)
{
MethodInfo methodInfo = GetType().GetMethod("As");
return methodInfo.MakeGenericMethod(targetType).Invoke(this, new object[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.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 Read(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);
}
static ODBEntity()
{
RuntimeHelpers.RunClassConstructor(typeof(ODBNull).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(Document).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);
}
}
}

View File

@ -4,39 +4,19 @@ namespace ln.types.odb.values
{
public class ODBGuid : ODBValue
{
public override int CompareLevel => 20;
public ODBGuid()
:base(0x03)
{
Value = Guid.NewGuid();
}
:base(0x03, Guid.NewGuid())
{}
public ODBGuid(Guid guid)
:this()
{
Value = guid;
}
:base(0x03,guid)
{}
public override byte[] ToStorage()
{
return AsGuid.ToByteArray();
}
static Guid FromByteArray(byte[] b,int offset)
{
byte[] s = new byte[16];
Array.Copy(b, offset, s, 0, 16);
return new Guid(s);
}
public override int CompareInType(ODBValue other)
{
return AsGuid.CompareTo(other.AsGuid);
}
public override byte[] GetStorageBytes() => As<Guid>().ToByteArray();
protected override int compare(ODBEntity other) => ((Guid)Value).CompareTo((other as ODBGuid).Value);
static ODBGuid()
{
RegisterDeserializer(0x03, (b,o,l) => FromByteArray(b,o));
RegisterDeserializer(0x03, (b, o, l) => new ODBGuid(new Guid(b.Slice(o, 16))));
}
}

View File

@ -4,55 +4,28 @@ namespace ln.types.odb.values
{
public class ODBInteger : ODBValue
{
public ODBInteger()
: base(0x10)
{
}
public ODBInteger(int i)
: this()
{
Value = i;
}
public override bool AsBool => AsInt != 0;
public override int CompareLevel => 0;
public override byte[] ToStorage() => BitConverter.GetBytes(AsInt);
public override int CompareInType(ODBValue other)
{
return AsInt - other.AsInt;
}
: base(0x10,i)
{}
public override byte[] GetStorageBytes() => BitConverter.GetBytes((int)Value);
protected override int compare(ODBEntity other) => (int)Value - (int)(other as ODBValue).Value;
static ODBInteger()
{
RegisterDeserializer(0x10, (b, o, l) => BitConverter.ToInt32(b, o));
//RegisterValueFactory(typeof(int), v => new ODBInteger((int)v));
//RegisterValueFactory(typeof(short), v => new ODBInteger((int)(short)v));
//RegisterValueFactory(typeof(byte), v => new ODBInteger((int)(byte)v));
RegisterDeserializer(0x10, (b, o, l) => new ODBInteger(BitConverter.ToInt32(b, o)));
}
}
public class ODBUInteger : ODBValue
{
public override int CompareLevel => 5;
public ODBUInteger()
: base(0x11)
{
}
public ODBUInteger(uint i)
: this()
{
Value = i;
}
: base(0x11,i)
{}
public override byte[] ToStorage() => BitConverter.GetBytes(AsUInt);
public override int CompareInType(ODBValue other)
public override byte[] GetStorageBytes() => BitConverter.GetBytes((uint)Value);
protected override int compare(ODBEntity other)
{
long d = (long)AsUInt - (long)other.AsUInt;
long d = (long)Value - (long)(other as ODBValue).Value;
if (d == 0)
return 0;
if (d < 0)
@ -62,10 +35,7 @@ namespace ln.types.odb.values
static ODBUInteger()
{
RegisterDeserializer(0x11, (b, o, l) => BitConverter.ToUInt32(b, o));
//RegisterValueFactory(typeof(uint), v => new ODBUInteger((uint)v));
//RegisterValueFactory(typeof(ushort), v => new ODBUInteger((uint)(ushort)v));
//RegisterValueFactory(typeof(char), v => new ODBUInteger((uint)(char)v));
RegisterDeserializer(0x11, (b, o, l) => new ODBUInteger(BitConverter.ToUInt32(b, o)));
}
}

View File

@ -3,11 +3,15 @@ using System.Collections.Generic;
using System.IO;
using System.Collections;
using System.Runtime.CompilerServices;
using ln.types.odb.ng;
namespace ln.types.odb.values
{
public class ODBList : ODBValue, IEnumerable<ODBValue>
public class ODBList : ODBEntity, IEnumerable<ODBEntity>
{
List<ODBValue> items = new List<ODBValue>();
Guid identity = Guid.NewGuid();
public override ODBValue Identity => Identity;
List<ODBEntity> items = new List<ODBEntity>();
public ODBList()
:base(0x02)
@ -17,34 +21,36 @@ namespace ln.types.odb.values
:this()
{
MemoryStream stream = new MemoryStream(bytes, offset, length);
identity = new Guid(stream.ReadBytes(16));
int nItems = stream.ReadInteger();
for (int n = 0; n < nItems; n++)
items.Add(ODBValue.Read(stream));
items.Add(ODBEntity.Read(stream));
}
public ODBValue this[int i]
public ODBEntity this[int i]
{
get => items[i];
set => items[i] = value;
}
public ODBValue this[ODBValue i]
public ODBEntity this[ODBEntity i]
{
get => items[i.AsInt];
set => items[i.AsInt] = value;
get => items[i.As<int>()];
set => items[i.As<int>()] = value;
}
public void AddRange(IEnumerable<ODBValue> values)
public void AddRange(IEnumerable<ODBEntity> values)
{
foreach (ODBValue value in values)
foreach (ODBEntity value in values)
Add(value);
}
public void Add(ODBValue value)
public void Add(ODBEntity value)
{
items.Add(value);
}
public void Remove(ODBValue value)
public void Remove(ODBEntity value)
{
items.Remove(value);
}
@ -55,42 +61,32 @@ namespace ln.types.odb.values
public int Count => items.Count;
public override ODBValue Clone()
public override ODBEntity Clone()
{
ODBList clone = new ODBList();
clone.items.AddRange(this.items);
return clone;
clone.identity = identity;
foreach (ODBEntity item in items)
clone.items.Add(item.Clone());
return clone;
}
public override object Value {
get
{
object[] a = new object[items.Count];
((IList)items).CopyTo(a, 0);
return a;
}
protected set
{
throw new NotSupportedException();
}
}
public override int CompareLevel => 253;
public override byte[] ToStorage()
public override byte[] GetStorageBytes()
{
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(identity.ToByteArray());
writer.Write(items.Count);
foreach (ODBValue value in items)
value.Store(writer);
foreach (ODBEntity value in items)
value.Write(writer);
return stream.ToArray();
}
public override int CompareInType(ODBValue other)
protected override int compare(ODBEntity other)
{
ODBList you = other as ODBList;
@ -107,24 +103,7 @@ namespace ln.types.odb.values
return 0;
}
public override bool ValueEquals(ODBValue other)
{
if (other is ODBList)
{
ODBList you = other as ODBList;
if (Count != you.Count)
return false;
for (int n = 0; n < Count; n++)
if (!this[n].ValueEquals(you[n]))
return false;
return true;
}
return false;
}
public IEnumerator<ODBValue> GetEnumerator()
public IEnumerator<ODBEntity> GetEnumerator()
{
return items.GetEnumerator();
}
@ -134,6 +113,8 @@ namespace ln.types.odb.values
return items.GetEnumerator();
}
public override T As<T>() => (T)Mapper.Default.UnmapValue(typeof(T), this);
static ODBList()
{
RegisterDeserializer(0x02, (b, o, l) => new ODBList(b,o,l));

View File

@ -4,23 +4,17 @@ namespace ln.types.odb.values
{
public class ODBLong : ODBValue
{
public ODBLong()
: base(0x12)
{
}
public ODBLong(long i)
: this()
{
Value = i;
}
public ODBLong(long value)
: base(0x12, value)
{}
public override byte[] ToStorage() => BitConverter.GetBytes(AsLong);
public override byte[] GetStorageBytes() => BitConverter.GetBytes(As<long>());
public override int CompareInType(ODBValue other)
protected override int compare(ODBEntity other)
{
long a, b;
a = AsLong;
b = other.AsLong;
a = (long)Value;
b = (long)(other as ODBValue).Value;
long d = a - b;
if (d == 0)
@ -30,39 +24,28 @@ namespace ln.types.odb.values
return 1;
}
public override DateTime AsDateTime => DateTimeOffset.FromUnixTimeMilliseconds(AsLong).DateTime;
public override TimeSpan AsTimeSpan => TimeSpan.FromMilliseconds(AsDouble);
public static implicit operator DateTime(ODBLong l) => DateTimeOffset.FromUnixTimeMilliseconds((long)l.Value).DateTime;
public static implicit operator TimeSpan(ODBLong l) => TimeSpan.FromMilliseconds((long)l.Value);
public override int CompareLevel => 1;
static ODBLong()
{
RegisterDeserializer(0x12, (b, o, l) => BitConverter.ToInt64(b, o));
//RegisterValueFactory(typeof(long), v => new ODBLong((long)v));
//RegisterValueFactory(typeof(DateTime), v => new ODBLong(new DateTimeOffset((DateTime)v).ToUnixTimeMilliseconds()));
RegisterDeserializer(0x12, (b, o, l) => new ODBLong(BitConverter.ToInt64(b, o)));
}
}
public class ODBULong : ODBValue
{
public override int CompareLevel => 6;
public ODBULong(ulong value)
: base(0x13,value)
{}
public ODBULong()
: base(0x13)
public override byte[] GetStorageBytes() => BitConverter.GetBytes(As<ulong>());
protected override int compare(ODBEntity other)
{
}
public ODBULong(ulong i)
: this()
{
Value = i;
}
public override byte[] ToStorage() => BitConverter.GetBytes(AsULong);
public override int CompareInType(ODBValue other)
{
ulong a = AsULong;
ulong b = other.AsULong;
ulong a = (ulong)Value;
ulong b = (ulong)(other as ODBValue).Value;
if (a == b)
return 0;
@ -73,8 +56,7 @@ namespace ln.types.odb.values
static ODBULong()
{
RegisterDeserializer(0x13, (b, o, l) => BitConverter.ToUInt64(b, o));
//RegisterValueFactory(typeof(ulong), v => new ODBULong((ulong)v));
RegisterDeserializer(0x13, (b, o, l) => new ODBULong(BitConverter.ToUInt64(b, o)));
}
}

View File

@ -6,34 +6,19 @@ namespace ln.types.odb.values
{
public static readonly ODBNull Instance = new ODBNull();
public override int CompareLevel => 255;
private ODBNull()
: base(0x00,null)
{}
public ODBNull()
: base(0x00)
{ }
public override byte[] GetStorageBytes() => new byte[0];
protected override int compare(ODBEntity other) => 0;
public override byte[] ToStorage()
{
return new byte[0];
}
public override int GetHashCode() => 0;
public override bool Equals(object obj) => Object.ReferenceEquals(this, obj);
static ODBNull()
{
RegisterDeserializer(0x00, (b,o,l) => Instance);
}
public override int GetHashCode()
{
return 0;
}
public override bool Equals(object obj)
{
return (object.ReferenceEquals(obj,null)) || (obj is ODBNull);
}
public override int CompareInType(ODBValue other)
{
return 0;
}
}
}

View File

@ -5,39 +5,17 @@ namespace ln.types.odb.values
{
public class ODBStringValue : ODBValue
{
public override int CompareLevel => 10;
public ODBStringValue()
: base(0x01)
{ }
public ODBStringValue(String text)
: this()
{
Value = text;
}
public override byte[] ToStorage()
{
return Encoding.UTF8.GetBytes(AsString);
}
public override int CompareInType(ODBValue other)
{
return AsString.CompareTo(other.AsString);
}
public static implicit operator ODBStringValue(String text)
{
return new ODBStringValue(text);
}
public ODBStringValue(string s)
: base(0x01,s)
{}
public override byte[] GetStorageBytes() => Encoding.UTF8.GetBytes((string)Value);
protected override int compare(ODBEntity other) => ((string)Value).CompareTo((other as ODBValue).Value);
static ODBStringValue()
{
RegisterDeserializer(0x01, (b, o, l) => new ODBStringValue(Encoding.UTF8.GetString(b, o, l)));
// RegisterValueFactory(typeof(string), v => new ODBStringValue((string)v));
}
}
}

View File

@ -11,74 +11,74 @@ using System;
using System.IO;
namespace ln.types.odb.values
{
public class ODBTypedValue : ODBValue
{
public ODBValue ODBValue { get; private set; }
public Type TargetType { get; private set; }
//public class ODBTypedValue : ODBEntity
//{
// public ODBEntity ODBValue { get; private set; }
// public Type TargetType { get; private set; }
public override uint AsUInt => ODBValue.AsUInt;
// public override uint AsUInt => ODBValue.AsUInt;
internal ODBTypedValue()
: base(0x0020)
{
}
public ODBTypedValue(Type targetType,ODBValue value)
: this()
{
TargetType = targetType;
ODBValue = value;
}
public ODBTypedValue(byte[] bytes,int offset,int length)
: this()
{
String aname = ODBValue.Deserialize(bytes, ref offset).AsString;
String tname = ODBValue.Deserialize(bytes, ref offset).AsString;
ODBValue = ODBValue.Deserialize(bytes, ref offset);
// internal ODBTypedValue()
// : base(0x0020)
// {
// }
// public ODBTypedValue(Type targetType,ODBEntity value)
// : this()
// {
// TargetType = targetType;
// ODBValue = value;
// }
// public ODBTypedValue(byte[] bytes,int offset,int length)
// : this()
// {
// String aname = ODBEntity.Deserialize(bytes, ref offset).AsString;
// String tname = ODBEntity.Deserialize(bytes, ref offset).AsString;
// ODBValue = ODBEntity.Deserialize(bytes, ref offset);
TargetType = Type.GetType(String.Format("{0}, {1}", tname, aname));
}
// TargetType = Type.GetType(String.Format("{0}, {1}", tname, aname));
// }
public override int CompareLevel => 126;
// public override int CompareLevel => 126;
public override int CompareInType(ODBValue other)
{
ODBTypedValue typedValue = other as ODBTypedValue;
return ODBValue.CompareTo(typedValue.ODBValue);
}
// public override int CompareInType(ODBEntity other)
// {
// ODBTypedValue typedValue = other as ODBTypedValue;
// return ODBValue.CompareTo(typedValue.ODBValue);
// }
public override byte[] ToStorage()
{
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
// public override byte[] GetStorageBytes()
// {
// MemoryStream stream = new MemoryStream();
// BinaryWriter writer = new BinaryWriter(stream);
ODBStringValue aname = TargetType.Assembly.GetName().Name;
ODBStringValue tname = TargetType.FullName;
// ODBStringValue aname = TargetType.Assembly.GetName().Name;
// ODBStringValue tname = TargetType.FullName;
aname.Store(writer);
tname.Store(writer);
ODBValue.Store(writer);
// aname.Write(writer);
// tname.Write(writer);
// ODBValue.Write(writer);
return stream.ToArray();
}
// return stream.ToArray();
// }
public override int GetHashCode()
{
return ODBValue.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is ODBTypedValue)
{
ODBTypedValue typedValue = obj as ODBTypedValue;
return ODBValue.Equals(typedValue.ODBValue);
}
return false;
}
// public override int GetHashCode()
// {
// return ODBValue.GetHashCode();
// }
// public override bool Equals(object obj)
// {
// if (obj is ODBTypedValue)
// {
// ODBTypedValue typedValue = obj as ODBTypedValue;
// return ODBValue.Equals(typedValue.ODBValue);
// }
// return false;
// }
static ODBTypedValue()
{
RegisterDeserializer(0x0020, (b, o, l) => new ODBTypedValue(b,o,l));
}
}
// static ODBTypedValue()
// {
// RegisterDeserializer(0x0020, (b, o, l) => new ODBTypedValue(b,o,l));
// }
//}
}

View File

@ -1,251 +1,68 @@
using System;
using System.Collections.Generic;
using System.IO;
using ln.types.odb.ng;
/**
* typeCode list
*
* 0x0000 ODBNull
* 0x0001 ODBStringValue
* 0x0002 ODBList
* 0x0003 ODBGuid
* 0x0004 ODBBool
*
* 0x0010 ODBInteger
* 0x0011 ODBUInteger
* 0x0012 ODBLong
* 0x0013 ODBULong
*
* 0x0018 ODBDouble
*
* 0x0020 ODBTypedMapping
*
* 0x1000 ODBDocument
* 0x1001 Document (ln.types.odb.ng)
*
*
*
**/
// /**
// * File: ODBValue.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
namespace ln.types.odb.values
{
public delegate ODBValue ODBValueFactory(object value);
public delegate ODBValue ODBDeserialize(byte[] storageBytes, int offset, int length);
public abstract class ODBValue : IComparable<ODBValue>
/// <summary>
/// The base type of all immutable ODB types
/// </summary>
public abstract class ODBValue : ODBEntity
{
int storageTypeCode;
public object Value { get; }
public virtual object Value { get; protected set; }
protected ODBValue(int storageTypeCode)
{
this.storageTypeCode = storageTypeCode;
}
public override ODBValue Identity => this;
public override T As<T>() => Cast.To<T>(Value);
public override ODBEntity Clone() => this;
protected ODBValue(int storageTypeCode, object value)
: this(storageTypeCode)
: base(storageTypeCode)
{
Value = value;
}
public abstract int CompareLevel { get; }
public abstract int CompareInType(ODBValue other);
public virtual int CompareValueInType(ODBValue other) => CompareInType(other);
public abstract byte[] ToStorage();
public object AsObject => Value;
public virtual string AsString
{
get
{
return Value?.ToString();
}
}
public virtual bool AsBool
{
get
{
return (bool)Value;
}
}
public virtual byte AsByte => Convert.ToByte(Value);
public virtual char AsChar => (char)Value;
public virtual short AsShort => Convert.ToInt16(Value);
public virtual int AsInt => Convert.ToInt32(Value);
public virtual long AsLong => Convert.ToInt64(Value);
public virtual ushort AsUShort => Convert.ToUInt16(Value);
public virtual uint AsUInt => (uint)Value;
public virtual ulong AsULong => (ulong)Value;
public virtual double AsDouble => (double)Value;
public virtual float AsFloat => (float)Value;
public virtual Guid AsGuid => (Guid)Value;
public virtual DateTime AsDateTime => (DateTime)Mapper.Default.UnmapValue(typeof(DateTime), this);
public virtual TimeSpan AsTimeSpan => (TimeSpan)Mapper.Default.UnmapValue(typeof(TimeSpan), this);
public virtual ODBTypedValue AsTypedValue => this as ODBTypedValue;
public virtual Document AsDocument => (Document)this;
public virtual ODBValue Clone()
{
return this;
}
public virtual void Store(BinaryWriter storage)
{
byte[] storageBytes = ToStorage();
storage.Write(storageTypeCode);
storage.Write(storageBytes.Length);
storage.Write(storageBytes, 0, storageBytes.Length);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override int GetHashCode() => Value.GetHashCode();
public override bool Equals(object obj)
{
if (obj is ODBValue)
{
ODBValue you = obj as ODBValue;
return Value.Equals(you.Value);
}
return Value.Equals(obj);
}
public virtual bool ValueEquals(ODBValue other)
{
return Equals(other);
}
public static bool operator <(ODBValue a, ODBValue b)
{
return a.CompareTo(b) < 0;
}
public static bool operator >(ODBValue a, ODBValue b)
{
return a.CompareTo(b) > 0;
}
public static bool operator <=(ODBValue a, ODBValue b)
{
return a.CompareTo(b) <= 0;
}
public static bool operator >=(ODBValue a, ODBValue b)
{
return a.CompareTo(b) >= 0;
}
public static bool operator ==(ODBValue a, ODBValue b)
{
if (Object.ReferenceEquals(a, null))
return object.ReferenceEquals(b, null);
return a.CompareTo(b) == 0;
}
public static bool operator !=(ODBValue a, ODBValue b)
{
return a.CompareTo(b) != 0;
}
public static implicit operator ODBValue(ValueType v)
{
return Mapper.Default.MapValue(v);
}
public static implicit operator ODBValue(String v)
{
return Mapper.Default.MapValue(v);
}
public static ODBValue 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 ODBValue 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));
ODBValue value = valueDeserializers[storageTypeCode](buffer, offset + 8, storageLength);
offset += 8 + storageLength;
return value;
}
public static ODBValue Read(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 int CompareTo(ODBValue other)
{
if (CompareLevel != other.CompareLevel)
return CompareLevel - other.CompareLevel;
return CompareInType(other);
}
public virtual int CompareValueTo(ODBValue other)
{
if (CompareLevel != other.CompareLevel)
return CompareLevel - other.CompareLevel;
return CompareValueInType(other);
return Object.Equals(Value, (obj as ODBValue).Value);
if (obj is ODBEntity)
return Identity.Equals((obj as ODBEntity).Identity);
return false;
}
public override string ToString()
{
return String.Format("[ODBValue Value={0}]", Value);
return String.Format("[{0} Value={1}]", GetType().Name, Value);
}
public static int Compare(ODBValue a,ODBValue b)
{
return a.CompareTo(b);
}
public static int CompareValue(ODBValue a, ODBValue b)
{
return a.CompareValueTo(b);
}
static ODBValue()
{
new Document();
new ODBNull();
new ODBStringValue();
new ODBBool();
new ODBList();
new ODBInteger();
new ODBUInteger();
new ODBLong();
new ODBULong();
new ODBDouble();
new ODBGuid();
new ODBTypedValue();
}
}
//public virtual string AsString => As<string>();
//public virtual bool AsBool => As<bool>();
//public virtual byte AsByte => As<byte>();
//public virtual char AsChar => (char)Value;
//public virtual short AsShort => Convert.ToInt16(Value);
//public virtual int AsInt => Convert.ToInt32(Value);
//public virtual long AsLong => Convert.ToInt64(Value);
//public virtual ushort AsUShort => Convert.ToUInt16(Value);
//public virtual uint AsUInt => (uint)Value;
//public virtual ulong AsULong => (ulong)Value;
//public virtual double AsDouble => (double)Value;
//public virtual float AsFloat => (float)Value;
//public virtual Guid AsGuid => (Guid)Value;
//public virtual DateTime AsDateTime => (DateTime)Mapper.Default.UnmapValue(typeof(DateTime), this);
//public virtual TimeSpan AsTimeSpan => (TimeSpan)Mapper.Default.UnmapValue(typeof(TimeSpan), this);
}
}

View File

@ -132,25 +132,25 @@ namespace ln.types.test
{
Document origin = new Document();
origin["FeldA"] = "OriginalA";
origin["FeldB"] = "OriginalB";
origin["FeldC"] = "OriginalC";
origin["FeldA"] = new ODBStringValue("OriginalA");
origin["FeldB"] = new ODBStringValue("OriginalB");
origin["FeldC"] = new ODBStringValue("OriginalC");
storage1.Save(origin);
Document secondary = storage2.Load(origin.ID);
Assert.IsTrue(origin.ContentEquals(secondary));
Assert.IsTrue(origin.CompareTo(secondary) == 0);
secondary["FeldB"] = "ZweiB";
secondary["FeldB"] = new ODBStringValue("ZweiB");
storage2.Save(secondary);
Assert.IsFalse(origin.ContentEquals(secondary));
Assert.IsFalse(origin.CompareTo(secondary) == 0);
Document reloaded1 = storage1.Load(origin.ID);
Assert.AreSame(reloaded1, origin);
Assert.IsTrue(secondary.ContentEquals(reloaded1));
Assert.IsTrue(secondary.CompareTo(reloaded1) == 0);
}
}