ln.types/odb/ODB.cs

179 lines
5.2 KiB
C#

// /**
// * 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<T> : 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<Guid, PreparedObject> objectCache = new Dictionary<Guid, PreparedObject>();
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<T>(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<PreparedObject> PreparedToSave => preparedObjects.Values;
private Dictionary<Guid, PreparedObject> preparedObjects = new Dictionary<Guid, PreparedObject>();
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);
}
}
}
}
}
}