// /** // * File: ODB.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.IO; using System.Collections.Generic; using Castle.DynamicProxy; using ln.types.serialize; using Castle.Components.DictionaryAdapter; using System.Linq; namespace ln.types.odb { public class ODB : ODB where T: IPersistent { public T Root { get => (T)RootObject; } public ODB(String basePath) :base(basePath, typeof(T)) { } } public class ODB { public String BasePath { get; set; } public IPersistent RootObject { get; protected set; } private Type RootType; private Storage Storage { get; set; } private Dictionary objectCache = new Dictionary(); public ODB(string basePath) { BasePath = Path.GetFullPath(basePath); Storage = new ODBFileStorage(basePath); } public ODB(String basePath, Type rootType) : this(basePath) { RootType = rootType; Initialize(); } public ODB(String basePath,IPersistent rootObject) : this(basePath) { RootType = rootObject.GetType(); RootObject = rootObject; Initialize(); } private void Initialize() { if (RootObject == null) { string rootHint = Path.Combine(BasePath, "root.hint"); if (File.Exists(rootHint)) { string rootID = File.ReadAllText(rootHint); Guid persistenceID = Guid.Parse(rootID); RootObject = LoadPersistent(persistenceID); } else { RootObject = (IPersistent)Activator.CreateInstance(RootType); string rootID = RootObject.GetPersistenceID().ToString(); SavePersistent(RootObject); File.WriteAllText(rootHint, rootID); } } } public bool Contains(Guid persistenceID) { return Storage.Contains(persistenceID) || objectCache.ContainsKey(persistenceID); } public void SavePersistent(IPersistent o) => SavePersistent(o, true); public void SavePersistent(IPersistent o,bool recurse) { lock (this) { SaveCollector saveCollector = new SaveCollector(this); saveCollector.Add(o); foreach (PreparedObject preparedObject in saveCollector.PreparedToSave) { Storage.Store(preparedObject); objectCache[preparedObject.PersistenceID] = preparedObject; } } } public T LoadPersistent(Guid persistenceID) => (T)LoadPersistent(persistenceID); public IPersistent LoadPersistent(Guid persistenceID) { if (!Contains(persistenceID)) throw new KeyNotFoundException(); PreparedObject preparedObject = GetCachedPersistent(persistenceID); if (preparedObject == null) { preparedObject = new PreparedObject(this, typeof(IPersistent), persistenceID); if (!Storage.Load(preparedObject)) throw new IOException(String.Format("unable to load IPersistent({0})",persistenceID)); preparedObject.CreateInstance(); objectCache.Add(persistenceID,preparedObject); } return preparedObject.Instance; } private PreparedObject GetCachedPersistent(Guid persistenceID) { lock (this) { if (objectCache.ContainsKey(persistenceID)) { return objectCache[persistenceID]; } } return null; } class SaveCollector { public ODB ODB { get; } public IEnumerable PreparedToSave => preparedObjects.Values; private Dictionary preparedObjects = new Dictionary(); public SaveCollector(ODB odb) { ODB = odb; } public void Add(IPersistent persistent) { PreparedObject preparedObject = new PreparedObject(ODB,persistent); PreparedObject cachedObject = ODB.GetCachedPersistent(preparedObject.PersistenceID); if (!preparedObject.InstanceEquals(cachedObject) && !preparedObjects.ContainsKey(preparedObject.PersistenceID)) { preparedObjects.Add(preparedObject.PersistenceID, preparedObject); foreach (IPersistent referencedPersistent in preparedObject.ReferencedPersistents) { Add(referencedPersistent); } } } } } }