From 3d2f7a5ad055b16bbf69f55a15bda79d44db52a8 Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Fri, 20 Sep 2019 11:42:02 +0200 Subject: [PATCH] Fixed semantics of ODBEntities --- Cast.cs | 78 ++++++ ln.types.csproj | 8 +- ln.types.sln | 6 - ln.types.test/Program.cs | 269 --------------------- ln.types.test/Properties/AssemblyInfo.cs | 35 --- ln.types.test/ln.types.test.csproj | 53 ----- odb/ng/Document.cs | 107 ++++----- odb/ng/DocumentChanges.cs | 115 --------- odb/ng/IODBMapping.cs | 4 +- odb/ng/Mapper.API.cs | 4 +- odb/ng/Mapper.cs | 61 ++--- odb/ng/Query.cs | 24 +- odb/ng/index/Index.cs | 6 +- odb/ng/index/IndexPath.cs | 26 +- odb/ng/index/SimpleIndex.cs | 28 +-- odb/ng/mappings/ClassMapping.cs | 24 +- odb/ng/mappings/DictionaryMapping.cs | 24 +- odb/ng/mappings/ListMapping.cs | 6 +- odb/ng/mappings/SimpleMapping.cs | 4 +- odb/ng/storage/IStorage.cs | 2 +- odb/ng/storage/OrganizedFile.cs | 4 +- odb/ng/storage/bases/ChainedStorage.cs | 2 +- odb/ng/storage/bases/StorageBase.cs | 2 +- odb/ng/storage/cache/CachingStorage.cs | 2 +- odb/ng/storage/fs/SegmentedFileStorage.cs | 14 +- odb/values/ODBBool.cs | 27 +-- odb/values/ODBDouble.cs | 28 +-- odb/values/ODBEntity.cs | 193 +++++++++++++++ odb/values/ODBGuid.cs | 34 +-- odb/values/ODBInteger.cs | 52 +--- odb/values/ODBList.cs | 83 +++---- odb/values/ODBLong.cs | 56 ++--- odb/values/ODBNull.cs | 29 +-- odb/values/ODBStringValue.cs | 32 +-- odb/values/ODBTypedValue.cs | 116 ++++----- odb/values/ODBValue.cs | 277 ++++------------------ {ln.types.test => test}/CacheTests.cs | 0 {ln.types.test => test}/ODBTests.cs | 14 +- {ln.types.test => test}/TypesTests.cs | 0 39 files changed, 653 insertions(+), 1196 deletions(-) create mode 100644 Cast.cs delete mode 100644 ln.types.test/Program.cs delete mode 100644 ln.types.test/Properties/AssemblyInfo.cs delete mode 100644 ln.types.test/ln.types.test.csproj delete mode 100644 odb/ng/DocumentChanges.cs create mode 100644 odb/values/ODBEntity.cs rename {ln.types.test => test}/CacheTests.cs (100%) rename {ln.types.test => test}/ODBTests.cs (92%) rename {ln.types.test => test}/TypesTests.cs (100%) diff --git a/Cast.cs b/Cast.cs new file mode 100644 index 0000000..f82810d --- /dev/null +++ b/Cast.cs @@ -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(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; + } + + + } +} diff --git a/ln.types.csproj b/ln.types.csproj index 73d5109..99d395b 100644 --- a/ln.types.csproj +++ b/ln.types.csproj @@ -46,7 +46,7 @@ - + @@ -94,7 +94,6 @@ - @@ -112,6 +111,11 @@ + + + + + diff --git a/ln.types.sln b/ln.types.sln index 9f39f43..ed0e64e 100644 --- a/ln.types.sln +++ b/ln.types.sln @@ -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 diff --git a/ln.types.test/Program.cs b/ln.types.test/Program.cs deleted file mode 100644 index 718bae2..0000000 --- a/ln.types.test/Program.cs +++ /dev/null @@ -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()) - mapper.Delete(documentID); - - Logging.Log(LogLevel.INFO, "Storage counts {0} entities", mapper.GetDocumentIDs().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().ToArray(); - Random random = new Random(); - - //for (int n = 0; n < 20; n++) - //{ - // Guid choosenID = documentIDs[random.Next(documentIDs.Length)]; - // Person person = mapper.Load(choosenID); - - // Logging.Log(LogLevel.INFO, "Querying: {0}", person.FirstName); - - // IEnumerable ids = Timing.Meassure(() => mapper.GetDocumentIDs(Query.Equals("MiddleNames[]", person.FirstName))); - // Guid[] matchedIDs = ids.ToArray(); - - // Logging.Log(LogLevel.INFO, "Found {0} persons.", matchedIDs.Length); - //} - - IODBMapping pMapping = mapper.GetMapping(); - - 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("MiddleNames[]"); - mapper.EnsureIndex("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(choosenID); - - IEnumerable ids = Timing.Meassure(() => mapper.GetDocumentIDs(Query.Equals("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(choosenID); - - IEnumerable ids = Timing.Meassure(() => mapper.GetDocumentIDs( - Query.AND( - Query.Equals("MiddleNames[]", person.FirstName), - Query.Equals("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); - } - - - } - -} diff --git a/ln.types.test/Properties/AssemblyInfo.cs b/ln.types.test/Properties/AssemblyInfo.cs deleted file mode 100644 index d21506a..0000000 --- a/ln.types.test/Properties/AssemblyInfo.cs +++ /dev/null @@ -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("")] diff --git a/ln.types.test/ln.types.test.csproj b/ln.types.test/ln.types.test.csproj deleted file mode 100644 index 16fa70a..0000000 --- a/ln.types.test/ln.types.test.csproj +++ /dev/null @@ -1,53 +0,0 @@ - - - - Debug - AnyCPU - {E39D8B11-7CF6-4C78-B723-F7E100121704} - Exe - ln.types.test - ln.types.test - v4.7 - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - true - - - true - bin\Release - prompt - 4 - true - - - - - nunit - - - - - - - - - - - - {8D9AB9A5-E513-4BA7-A450-534F6456BF28} - ln.types - - - {D471A566-9FB6-41B2-A777-3C32874ECD0E} - ln.logging - - - - \ No newline at end of file diff --git a/odb/ng/Document.cs b/odb/ng/Document.cs index 8f101e2..69884cb 100644 --- a/odb/ng/Document.cs +++ b/odb/ng/Document.cs @@ -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 properties = new Dictionary(); + public override ODBValue Identity => new ODBGuid(ID); + + private Dictionary properties = new Dictionary(); 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 this[new ODBStringValue(propName)]; + set => this[new ODBStringValue(propName)] = value; + } - public IEnumerable Keys => properties.Keys; + public IEnumerable 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)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)); } } } diff --git a/odb/ng/DocumentChanges.cs b/odb/ng/DocumentChanges.cs deleted file mode 100644 index e5ad643..0000000 --- a/odb/ng/DocumentChanges.cs +++ /dev/null @@ -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 changes = new List(); - 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(), src, dst); - private void diffDocument(Stack path,Document src,Document dst) - { - HashSet keys = new HashSet(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 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 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 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); - } - - } - - } -} diff --git a/odb/ng/IODBMapping.cs b/odb/ng/IODBMapping.cs index 0fe4f6d..65b2b84 100644 --- a/odb/ng/IODBMapping.cs +++ b/odb/ng/IODBMapping.cs @@ -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); } } diff --git a/odb/ng/Mapper.API.cs b/odb/ng/Mapper.API.cs index add9f4b..24115f0 100644 --- a/odb/ng/Mapper.API.cs +++ b/odb/ng/Mapper.API.cs @@ -118,8 +118,8 @@ namespace ln.types.odb.ng return storage.GetDocumentIDs(); } - public IEnumerable GetDocumentIDs(string path, Predicate predicate) => GetDocumentIDs(typeof(T), path, predicate); - public IEnumerable GetDocumentIDs(Type type, string path, Predicate predicate) + public IEnumerable GetDocumentIDs(string path, Predicate predicate) => GetDocumentIDs(typeof(T), path, predicate); + public IEnumerable GetDocumentIDs(Type type, string path, Predicate predicate) { IStorage storage = StorageContainer.GetStorage(type.FullName); return storage.GetDocumentIDs(path,predicate); diff --git a/odb/ng/Mapper.cs b/odb/ng/Mapper.cs index fbfc647..1731f53 100644 --- a/odb/ng/Mapper.cs +++ b/odb/ng/Mapper.cs @@ -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(Mapper mapper, T value); - public delegate T ODBUnmap(Mapper mapper, ODBValue oval); + public delegate ODBEntity ODBMap(Mapper mapper, object value); + public delegate object ODBUnmap(Mapper mapper, ODBEntity oval); + public delegate ODBEntity ODBMap(Mapper mapper, T value); + public delegate T ODBUnmap(Mapper mapper, ODBEntity oval); public partial class Mapper : IDisposable { @@ -39,74 +39,74 @@ namespace ln.types.odb.ng RegisterMapping( (mapper, value) => new ODBStringValue(value), - (mapper, oval) => oval.AsString + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBInteger(value), - (mapper, oval) => oval.AsInt + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBInteger(value), - (mapper, oval) => oval.AsShort + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBInteger(value), - (mapper, oval) => oval.AsByte + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBUInteger(value), - (mapper, oval) => oval.AsUInt + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBUInteger(value), - (mapper, oval) => oval.AsUShort + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBUInteger(value), - (mapper, oval) => oval.AsChar + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBDouble(value), - (mapper, oval) => oval.AsDouble + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBDouble(value), - (mapper, oval) => oval.AsFloat + (mapper, oval) => oval.As() ); RegisterMapping( (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()).DateTime ); RegisterMapping( (mapper, value) => new ODBDouble(value.TotalMilliseconds), - (mapper, oval) => TimeSpan.FromMilliseconds(oval.AsDouble) + (mapper, oval) => TimeSpan.FromMilliseconds(oval.As()) ); RegisterMapping( (mapper, value) => new ODBGuid(value), - (mapper, oval) => oval.AsGuid + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBLong(value), - (mapper, oval) => oval.AsLong + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBULong(value), - (mapper, oval) => oval.AsULong + (mapper, oval) => oval.As() ); RegisterMapping( - (mapper, value) => new ODBBool(value), - (mapper, oval) => oval.AsBool + (mapper, value) => (bool)value ? ODBBool.True : ODBBool.False, + (mapper, oval) => oval.As() ); RegisterMapping( (mapper, value) => new ODBUInteger(value.AsUInt), - (mapper, oval) => new IPv4(oval.AsUInt) + (mapper, oval) => new IPv4(oval.As()) ); 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 typename = doc["__type__"].As(); 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) diff --git a/odb/ng/Query.cs b/odb/ng/Query.cs index b09246e..be2c97e 100644 --- a/odb/ng/Query.cs +++ b/odb/ng/Query.cs @@ -36,37 +36,37 @@ namespace ln.types.odb.ng } public static Query Equals(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(string propertyName, ODBValue value) => EqualsNot(IndexPath.TranslatePropertyPath(typeof(T), propertyName), value); - public static Query EqualsNot(String propertyName, ODBValue value) + public static Query EqualsNot(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(string propertyName, ODBValue[] values) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), values); - public static Query Equals(String propertyName, ODBValue[] values) + public static Query Equals(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(string propertyName, IEnumerable 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(string propertyName, Predicate predicate) => IF(IndexPath.TranslatePropertyPath(typeof(T),propertyName), predicate); - public static Query IF(string propertyName,Predicate predicate) + public static Query IF(string propertyName, Predicate predicate) => IF(IndexPath.TranslatePropertyPath(typeof(T),propertyName), predicate); + public static Query IF(string propertyName,Predicate 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 Predicate { get; } + public Predicate Predicate { get; } - public IF(string propertyName,Predicate predicate) + public IF(string propertyName,Predicate predicate) { PropertyName = propertyName; Predicate = predicate; diff --git a/odb/ng/index/Index.cs b/odb/ng/index/Index.cs index 52ecad3..000512a 100644 --- a/odb/ng/index/Index.cs +++ b/odb/ng/index/Index.cs @@ -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 GetDocumentIDs(Predicate predicate); + public abstract IEnumerable GetDocumentIDs(Predicate predicate); public abstract bool LoadIndex(string basePath, long lastCloseTimestamp); public abstract bool SaveIndex(string basePath, long lastCloseTimestamp); diff --git a/odb/ng/index/IndexPath.cs b/odb/ng/index/IndexPath.cs index 7f1ae51..10d047c 100644 --- a/odb/ng/index/IndexPath.cs +++ b/odb/ng/index/IndexPath.cs @@ -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 GetDocumentIDs(Path path, Predicate predicate); - public virtual IEnumerable GetDocumentIDs(string path, Predicate predicate) + public abstract IEnumerable GetDocumentIDs(Path path, Predicate predicate); + public virtual IEnumerable GetDocumentIDs(string path, Predicate predicate) { return GetDocumentIDs(SplitPath(path), predicate); } @@ -49,7 +49,7 @@ namespace ln.types.odb.ng.index { } - public override IEnumerable GetDocumentIDs(Path path, Predicate predicate) + public override IEnumerable GetDocumentIDs(Path path, Predicate 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 GetDocumentIDs(Path path, Predicate predicate) + public override IEnumerable GetDocumentIDs(Path path, Predicate 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 GetDocumentIDs(Path path, Predicate predicate) + public override IEnumerable GetDocumentIDs(Path path, Predicate 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); } diff --git a/odb/ng/index/SimpleIndex.cs b/odb/ng/index/SimpleIndex.cs index 320e2ac..09df882 100644 --- a/odb/ng/index/SimpleIndex.cs +++ b/odb/ng/index/SimpleIndex.cs @@ -10,18 +10,18 @@ namespace ln.types.odb.ng.index { public class SimpleIndex : Index { - BTreeValueList valueIndex = new BTreeValueList(); - BTreeValueList reverseIndex = new BTreeValueList(); + BTreeValueList valueIndex = new BTreeValueList(); + BTreeValueList reverseIndex = new BTreeValueList(); public SimpleIndex(Path path) : base(path) { } - public override IEnumerable GetDocumentIDs(Predicate predicate) + public override IEnumerable GetDocumentIDs(Predicate predicate) { HashSet matchedIDs = new HashSet(); - 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(); 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(); 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)) { diff --git a/odb/ng/mappings/ClassMapping.cs b/odb/ng/mappings/ClassMapping.cs index c118158..7625a63 100644 --- a/odb/ng/mappings/ClassMapping.cs +++ b/odb/ng/mappings/ClassMapping.cs @@ -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() != 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(), document["__asm__"].As())); 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(); } } diff --git a/odb/ng/mappings/DictionaryMapping.cs b/odb/ng/mappings/DictionaryMapping.cs index bfc58fa..949831d 100644 --- a/odb/ng/mappings/DictionaryMapping.cs +++ b/odb/ng/mappings/DictionaryMapping.cs @@ -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(),document["__asm__"].As())); //;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(); 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()) : kType; + Type vt = vtypes.Contains(key) ? Type.GetType(vtypes[key].As()) : vType; dictionary.Add(mapper.UnmapValue(kt, key), mapper.UnmapValue(vt, document[key])); } diff --git a/odb/ng/mappings/ListMapping.cs b/odb/ng/mappings/ListMapping.cs index a37a2f9..d381d07 100644 --- a/odb/ng/mappings/ListMapping.cs +++ b/odb/ng/mappings/ListMapping.cs @@ -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 GetEnumerator() { - foreach (ODBValue item in list) + foreach (ODBEntity item in list) yield return (T)mapper.UnmapValue(TargetType, item); } diff --git a/odb/ng/mappings/SimpleMapping.cs b/odb/ng/mappings/SimpleMapping.cs index 7317035..d4c38b3 100644 --- a/odb/ng/mappings/SimpleMapping.cs +++ b/odb/ng/mappings/SimpleMapping.cs @@ -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); } diff --git a/odb/ng/storage/IStorage.cs b/odb/ng/storage/IStorage.cs index 81d0b52..b66fd5d 100644 --- a/odb/ng/storage/IStorage.cs +++ b/odb/ng/storage/IStorage.cs @@ -23,7 +23,7 @@ namespace ln.types.odb.ng.storage bool Contains(Guid documentID); IEnumerable GetDocumentIDs(); - IEnumerable GetDocumentIDs(string path,Predicate predicate); + IEnumerable GetDocumentIDs(string path,Predicate predicate); DateTime GetStorageTimestamp(Guid documentID); void EnsureIndex(params string[] path); diff --git a/odb/ng/storage/OrganizedFile.cs b/odb/ng/storage/OrganizedFile.cs index 9f0740f..87c8a64 100644 --- a/odb/ng/storage/OrganizedFile.cs +++ b/odb/ng/storage/OrganizedFile.cs @@ -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) diff --git a/odb/ng/storage/bases/ChainedStorage.cs b/odb/ng/storage/bases/ChainedStorage.cs index 2eb9567..094854c 100644 --- a/odb/ng/storage/bases/ChainedStorage.cs +++ b/odb/ng/storage/bases/ChainedStorage.cs @@ -65,7 +65,7 @@ namespace ln.types.odb.ng.storage.bases return Storage.GetDocumentIDs(); } - public virtual IEnumerable GetDocumentIDs(string path, Predicate predicate) + public virtual IEnumerable GetDocumentIDs(string path, Predicate predicate) { return Storage.GetDocumentIDs(path, predicate); } diff --git a/odb/ng/storage/bases/StorageBase.cs b/odb/ng/storage/bases/StorageBase.cs index 9d99f51..ace2060 100644 --- a/odb/ng/storage/bases/StorageBase.cs +++ b/odb/ng/storage/bases/StorageBase.cs @@ -69,7 +69,7 @@ namespace ln.types.odb.ng.storage.bases /* Enumeration */ public abstract IEnumerable GetDocumentIDs(); - public abstract IEnumerable GetDocumentIDs(string path, Predicate predicate); + public abstract IEnumerable GetDocumentIDs(string path, Predicate predicate); /* Indeces */ public abstract void EnsureIndex(params string[] path); diff --git a/odb/ng/storage/cache/CachingStorage.cs b/odb/ng/storage/cache/CachingStorage.cs index 32cd63e..270dcb5 100644 --- a/odb/ng/storage/cache/CachingStorage.cs +++ b/odb/ng/storage/cache/CachingStorage.cs @@ -52,7 +52,7 @@ namespace ln.types.odb.ng.storage.cache public override void EnsureIndex(params string[] path) => storage.EnsureIndex(path); public override IEnumerable GetDocumentIDs() => storage.GetDocumentIDs(); - public override IEnumerable GetDocumentIDs(string path, Predicate predicate) => storage.GetDocumentIDs(path, predicate); + public override IEnumerable GetDocumentIDs(string path, Predicate predicate) => storage.GetDocumentIDs(path, predicate); public override Document Load(Guid documentID) { diff --git a/odb/ng/storage/fs/SegmentedFileStorage.cs b/odb/ng/storage/fs/SegmentedFileStorage.cs index 8ad5f20..6449cb9 100644 --- a/odb/ng/storage/fs/SegmentedFileStorage.cs +++ b/odb/ng/storage/fs/SegmentedFileStorage.cs @@ -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())); } } @@ -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 GetDocumentIDs(string path, Predicate predicate) + public override IEnumerable GetDocumentIDs(string path, Predicate predicate) { lock (this) { diff --git a/odb/values/ODBBool.cs b/odb/values/ODBBool.cs index 4c294f4..965b488 100644 --- a/odb/values/ODBBool.cs +++ b/odb/values/ODBBool.cs @@ -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); } } } diff --git a/odb/values/ODBDouble.cs b/odb/values/ODBDouble.cs index 9313c61..f194858 100644 --- a/odb/values/ODBDouble.cs +++ b/odb/values/ODBDouble.cs @@ -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))); } } } diff --git a/odb/values/ODBEntity.cs b/odb/values/ODBEntity.cs new file mode 100644 index 0000000..69f45c1 --- /dev/null +++ b/odb/values/ODBEntity.cs @@ -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); + + /// + /// ODBEntity. The base of all ODB types. + /// + /// + /// + /// + /// + public abstract class ODBEntity : IComparable + { + int storageTypeCode; + + /// + /// Gets the identity of this Entity. + /// + /// The identity. + public virtual ODBValue Identity { get; } + + /// + /// Return a .NET native value / object that semantically equals this ODBEntity instance. + /// + /// The native .NET value + /// The type to which this ODBEntity should be casted/converted. + public abstract T As(); + + /// + /// Independently clone this instance. + /// + /// + /// For immutable values this returns the instance itself. + /// Complex ODBEntities will return a copy of themself that is completly independend of the source. + /// + /// The clone. + public abstract ODBEntity Clone(); + + /// + /// Implements the internal comparison within the same subclass of ODBEntity. + /// + /// The compare. + /// Other. + 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 valueDeserializers = new Dictionary(); + 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); + } + } +} diff --git a/odb/values/ODBGuid.cs b/odb/values/ODBGuid.cs index dacd3db..180dbe8 100644 --- a/odb/values/ODBGuid.cs +++ b/odb/values/ODBGuid.cs @@ -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().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)))); } } diff --git a/odb/values/ODBInteger.cs b/odb/values/ODBInteger.cs index b2e4aaf..0e9e097 100644 --- a/odb/values/ODBInteger.cs +++ b/odb/values/ODBInteger.cs @@ -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))); } } diff --git a/odb/values/ODBList.cs b/odb/values/ODBList.cs index c042045..23b0c11 100644 --- a/odb/values/ODBList.cs +++ b/odb/values/ODBList.cs @@ -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 + public class ODBList : ODBEntity, IEnumerable { - List items = new List(); + Guid identity = Guid.NewGuid(); + public override ODBValue Identity => Identity; + + List items = new List(); 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()]; + set => items[i.As()] = value; } - public void AddRange(IEnumerable values) + public void AddRange(IEnumerable 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 GetEnumerator() + public IEnumerator GetEnumerator() { return items.GetEnumerator(); } @@ -134,6 +113,8 @@ namespace ln.types.odb.values return items.GetEnumerator(); } + public override T As() => (T)Mapper.Default.UnmapValue(typeof(T), this); + static ODBList() { RegisterDeserializer(0x02, (b, o, l) => new ODBList(b,o,l)); diff --git a/odb/values/ODBLong.cs b/odb/values/ODBLong.cs index 20195b6..289d73f 100644 --- a/odb/values/ODBLong.cs +++ b/odb/values/ODBLong.cs @@ -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()); - 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()); + 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))); } } diff --git a/odb/values/ODBNull.cs b/odb/values/ODBNull.cs index c06f488..9245383 100644 --- a/odb/values/ODBNull.cs +++ b/odb/values/ODBNull.cs @@ -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; - } } } diff --git a/odb/values/ODBStringValue.cs b/odb/values/ODBStringValue.cs index 247ac91..5c5ae34 100644 --- a/odb/values/ODBStringValue.cs +++ b/odb/values/ODBStringValue.cs @@ -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)); } - } } diff --git a/odb/values/ODBTypedValue.cs b/odb/values/ODBTypedValue.cs index 0ab03bc..0cc9626 100644 --- a/odb/values/ODBTypedValue.cs +++ b/odb/values/ODBTypedValue.cs @@ -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)); + // } + //} } diff --git a/odb/values/ODBValue.cs b/odb/values/ODBValue.cs index 75ac845..5cfa384 100644 --- a/odb/values/ODBValue.cs +++ b/odb/values/ODBValue.cs @@ -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 + /// + /// The base type of all immutable ODB types + /// + 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() => Cast.To(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 valueDeserializers = new Dictionary(); - 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(); + //public virtual bool AsBool => As(); + //public virtual byte AsByte => As(); + //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); + } } diff --git a/ln.types.test/CacheTests.cs b/test/CacheTests.cs similarity index 100% rename from ln.types.test/CacheTests.cs rename to test/CacheTests.cs diff --git a/ln.types.test/ODBTests.cs b/test/ODBTests.cs similarity index 92% rename from ln.types.test/ODBTests.cs rename to test/ODBTests.cs index 90e0b59..158e2e7 100644 --- a/ln.types.test/ODBTests.cs +++ b/test/ODBTests.cs @@ -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); } } diff --git a/ln.types.test/TypesTests.cs b/test/TypesTests.cs similarity index 100% rename from ln.types.test/TypesTests.cs rename to test/TypesTests.cs