179 lines
5.2 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|