220 lines
8.0 KiB
C#
220 lines
8.0 KiB
C#
|
using ln.types.btree;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System;
|
|||
|
using ln.types.odb.ng.index;
|
|||
|
using System.Linq;
|
|||
|
using System.Collections;
|
|||
|
using ln.types.odb.ng.storage;
|
|||
|
using ln.types.odb.ng.mappings;
|
|||
|
using ln.objects.catalog;
|
|||
|
|
|||
|
namespace ln.types.odb.ng
|
|||
|
{
|
|||
|
|
|||
|
public partial class Mapper
|
|||
|
{
|
|||
|
BTree<Guid, CachedObject> forwardCache = new BTree<Guid, CachedObject>();
|
|||
|
Dictionary<object, CachedObject> reverseCache = new Dictionary<object, CachedObject>();
|
|||
|
|
|||
|
public IEnumerable<T> Load<T>() => Load(typeof(T),false).Cast<T>();
|
|||
|
public IEnumerable<T> Load<T>(bool refresh) => Load(typeof(T),refresh).Cast<T>();
|
|||
|
public IEnumerable Load(Type type) => Load(type, false);
|
|||
|
public IEnumerable Load(Type type,bool refresh)
|
|||
|
{
|
|||
|
return new MappedObjectEnumeration(this, type, GetDocumentIDs(type),refresh);
|
|||
|
}
|
|||
|
public object[] LoadArray(Type type) => LoadArray(type, false);
|
|||
|
public object[] LoadArray(Type type, bool refresh)
|
|||
|
{
|
|||
|
MappedObjectEnumeration mappedObjectEnumeration = new MappedObjectEnumeration(this, type, GetDocumentIDs(type), refresh);
|
|||
|
object[] objects = new object[mappedObjectEnumeration.Count];
|
|||
|
int n = 0;
|
|||
|
foreach (object o in mappedObjectEnumeration)
|
|||
|
objects[n++] = o;
|
|||
|
return objects;
|
|||
|
}
|
|||
|
public T Load<T>(Guid documentID) => (T)Load(typeof(T), documentID, false);
|
|||
|
public T Load<T>(Guid documentID,bool refresh) => (T)Load(typeof(T), documentID, refresh);
|
|||
|
public object Load(Type type, Guid documentID) => Load(type, documentID, false);
|
|||
|
public object Load(Type type, Guid documentID,bool refresh)
|
|||
|
{
|
|||
|
lock (this)
|
|||
|
{
|
|||
|
if (forwardCache.ContainsKey(documentID))
|
|||
|
{
|
|||
|
CachedObject cachedObject = forwardCache[documentID];
|
|||
|
if (refresh)
|
|||
|
Refresh(type, cachedObject.Instance);
|
|||
|
return cachedObject.Instance;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
IStorage storage = StorageContainer.GetStorage(type.FullName);
|
|||
|
Document document = storage.Load(documentID);
|
|||
|
|
|||
|
object instance = ObjectMapping.UnmapValue(this, document);
|
|||
|
|
|||
|
CachedObject cachedObject = new CachedObject(document, instance);
|
|||
|
forwardCache.Add(cachedObject.Document.ID, cachedObject);
|
|||
|
reverseCache.Add(cachedObject.Instance, cachedObject);
|
|||
|
|
|||
|
return cachedObject.Instance;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
public IEnumerable<T> Load<T>(Query query) => Load(typeof(T), query, false).Cast<T>();
|
|||
|
public IEnumerable<T> Load<T>(Query query,bool refresh) => Load(typeof(T), query, refresh).Cast<T>();
|
|||
|
public IEnumerable Load(Type type, Query query) => Load(type, query, false);
|
|||
|
public IEnumerable Load(Type type,Query query,bool refresh)
|
|||
|
{
|
|||
|
IEnumerable<Guid> matchedIDs = GetDocumentIDs(type,query);
|
|||
|
|
|||
|
return new MappedObjectEnumeration(this, type, matchedIDs,refresh);
|
|||
|
}
|
|||
|
|
|||
|
public bool Refresh<T>(T instance) => Refresh(typeof(T), instance);
|
|||
|
public bool Refresh(Type type,object instance)
|
|||
|
{
|
|||
|
if (!reverseCache.TryGetValue(instance, out CachedObject cachedObject))
|
|||
|
return false;
|
|||
|
|
|||
|
IStorage storage = StorageContainer.GetStorage(type.FullName);
|
|||
|
if (storage.Refresh(cachedObject.Document))
|
|||
|
{
|
|||
|
(GetMapping(type) as ClassMapping).Apply(this,cachedObject.Document,cachedObject.Instance);
|
|||
|
return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public void Save<T>(T instance) => Save(typeof(T), instance);
|
|||
|
public void Save(Type type, object instance)
|
|||
|
{
|
|||
|
lock (this)
|
|||
|
{
|
|||
|
IStorage storage = GetStorage(type);
|
|||
|
CachedObject cachedObject;
|
|||
|
Document document;
|
|||
|
|
|||
|
if (reverseCache.ContainsKey(instance))
|
|||
|
{
|
|||
|
cachedObject = reverseCache[instance];
|
|||
|
document = (GetMapping(type) as mappings.ClassMapping).MapDocument(this, cachedObject.Document.ID, instance);
|
|||
|
|
|||
|
storage.Save(document);
|
|||
|
|
|||
|
cachedObject.Document = document;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
document = (GetMapping(type) as mappings.ClassMapping).MapDocument(this, Guid.NewGuid(), instance) as Document;
|
|||
|
cachedObject = new CachedObject(document, instance);
|
|||
|
|
|||
|
storage.Save(document);
|
|||
|
|
|||
|
forwardCache.Add(cachedObject.Document.ID, cachedObject);
|
|||
|
reverseCache.Add(instance, cachedObject);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Delete<T>(T instance) => Delete(typeof(T),instance);
|
|||
|
public void Delete(Type type,object instance)
|
|||
|
{
|
|||
|
lock (this)
|
|||
|
{
|
|||
|
if (reverseCache.ContainsKey(instance))
|
|||
|
{
|
|||
|
CachedObject cachedObject = reverseCache[instance];
|
|||
|
reverseCache.Remove(instance);
|
|||
|
forwardCache.Remove(cachedObject.Document.ID);
|
|||
|
|
|||
|
GetStorage(type).Delete(cachedObject.Document.ID);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
public void Delete<T>(Guid documentID) => Delete(typeof(T), documentID);
|
|||
|
public void Delete(Type type, Guid documentID)
|
|||
|
{
|
|||
|
lock (this)
|
|||
|
{
|
|||
|
if (forwardCache.ContainsKey(documentID))
|
|||
|
{
|
|||
|
CachedObject cachedObject = forwardCache[documentID];
|
|||
|
reverseCache.Remove(cachedObject.Instance);
|
|||
|
forwardCache.Remove(cachedObject.Document.ID);
|
|||
|
}
|
|||
|
|
|||
|
GetStorage(type).Delete(documentID);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public IEnumerable<Guid> GetDocumentIDs<T>() => GetDocumentIDs(typeof(T));
|
|||
|
public IEnumerable<Guid> GetDocumentIDs(Type type)
|
|||
|
{
|
|||
|
IStorage storage = StorageContainer.GetStorage(type.FullName);
|
|||
|
return storage.GetDocumentIDs();
|
|||
|
}
|
|||
|
|
|||
|
public IEnumerable<Guid> GetDocumentIDs<T>(string path, Predicate<ODBEntity> predicate) => GetDocumentIDs(typeof(T), path, predicate);
|
|||
|
public IEnumerable<Guid> GetDocumentIDs(Type type, string path, Predicate<ODBEntity> predicate)
|
|||
|
{
|
|||
|
IStorage storage = StorageContainer.GetStorage(type.FullName);
|
|||
|
return storage.GetDocumentIDs(path,predicate);
|
|||
|
}
|
|||
|
|
|||
|
public IEnumerable<Guid> GetDocumentIDs<T>(Query query) => GetDocumentIDs(typeof(T), query);
|
|||
|
public IEnumerable<Guid> GetDocumentIDs(Type type,Query query)
|
|||
|
{
|
|||
|
IStorage storage = StorageContainer.GetStorage(type.FullName);
|
|||
|
return query.Execute(storage);
|
|||
|
}
|
|||
|
|
|||
|
public void EnsureIndex<T>(string path) => EnsureIndex(typeof(T), path);
|
|||
|
public void EnsureIndex(Type type,string path)
|
|||
|
{
|
|||
|
path = IndexPath.TranslatePropertyPath(type, path);
|
|||
|
IStorage storage = StorageContainer.GetStorage(type.FullName);
|
|||
|
storage.EnsureIndex(path);
|
|||
|
}
|
|||
|
|
|||
|
struct CachedObject
|
|||
|
{
|
|||
|
public object Instance;
|
|||
|
public Document Document;
|
|||
|
|
|||
|
public CachedObject(Document document, object instance)
|
|||
|
{
|
|||
|
Document = document;
|
|||
|
Instance = instance;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
class MappedObjectEnumeration : IEnumerable
|
|||
|
{
|
|||
|
Mapper mapper;
|
|||
|
Type type;
|
|||
|
IEnumerable<Guid> documentIDs;
|
|||
|
bool refresh;
|
|||
|
|
|||
|
public int Count => documentIDs.Count();
|
|||
|
|
|||
|
public MappedObjectEnumeration(Mapper mapper,Type type,IEnumerable<Guid> documentIDs,bool refresh)
|
|||
|
{
|
|||
|
this.mapper = mapper;
|
|||
|
this.type = type;
|
|||
|
this.documentIDs = documentIDs;
|
|||
|
this.refresh = refresh;
|
|||
|
}
|
|||
|
|
|||
|
public IEnumerator GetEnumerator()
|
|||
|
{
|
|||
|
foreach (Guid documentID in documentIDs)
|
|||
|
yield return mapper.Load(type, documentID, refresh);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|