Initial Commit
commit
a4108ac920
|
@ -0,0 +1,41 @@
|
||||||
|
# Autosave files
|
||||||
|
*~
|
||||||
|
|
||||||
|
# build
|
||||||
|
[Oo]bj/
|
||||||
|
[Bb]in/
|
||||||
|
packages/
|
||||||
|
TestResults/
|
||||||
|
|
||||||
|
# globs
|
||||||
|
Makefile.in
|
||||||
|
*.DS_Store
|
||||||
|
*.sln.cache
|
||||||
|
*.suo
|
||||||
|
*.cache
|
||||||
|
*.pidb
|
||||||
|
*.userprefs
|
||||||
|
*.usertasks
|
||||||
|
config.log
|
||||||
|
config.make
|
||||||
|
config.status
|
||||||
|
aclocal.m4
|
||||||
|
install-sh
|
||||||
|
autom4te.cache/
|
||||||
|
*.user
|
||||||
|
*.tar.gz
|
||||||
|
tarballs/
|
||||||
|
test-results/
|
||||||
|
Thumbs.db
|
||||||
|
.vs/
|
||||||
|
|
||||||
|
# Mac bundle stuff
|
||||||
|
*.dmg
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# resharper
|
||||||
|
*_Resharper.*
|
||||||
|
*.Resharper
|
||||||
|
|
||||||
|
# dotCover
|
||||||
|
*.dotCover
|
|
@ -0,0 +1,186 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using oodb.descriptor;
|
||||||
|
using oodb.mapping;
|
||||||
|
using oodb.persistence;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
|
using System.CodeDom;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Reflection;
|
||||||
|
using oodb.mapping.collections;
|
||||||
|
namespace oodb
|
||||||
|
{
|
||||||
|
public class OODB
|
||||||
|
{
|
||||||
|
|
||||||
|
public PersistenceCache PersistenceCache { get; }
|
||||||
|
public StorageAdapter StorageAdapter { get; }
|
||||||
|
|
||||||
|
internal Dictionary<Type, Descriptor> descriptors = new Dictionary<Type, Descriptor>();
|
||||||
|
internal Dictionary<Type, FlatTypeMapping> flatTypeMappings = new Dictionary<Type, FlatTypeMapping>();
|
||||||
|
|
||||||
|
|
||||||
|
public OODB(String storagePath)
|
||||||
|
:this(new DirectoryInfo(storagePath))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public OODB(DirectoryInfo storageDirectory)
|
||||||
|
{
|
||||||
|
PersistenceCache = new PersistenceCache(this);
|
||||||
|
StorageAdapter = new StorageAdapter(this,storageDirectory);
|
||||||
|
|
||||||
|
PopulateFlatMappings();
|
||||||
|
|
||||||
|
AppDomain.CurrentDomain.ProcessExit += (sender, e) => this.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
StorageAdapter.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Prepare()
|
||||||
|
{
|
||||||
|
foreach (Descriptor descriptor in descriptors.Values)
|
||||||
|
{
|
||||||
|
descriptor.Initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public OODB Add<T>() where T : Persistent => Add(typeof(T));
|
||||||
|
public OODB Add(Type type)
|
||||||
|
{
|
||||||
|
GetDescriptor(type);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(IEnumerable<Persistent> persistents)
|
||||||
|
{
|
||||||
|
foreach (Persistent persistent in persistents)
|
||||||
|
Save(persistent);
|
||||||
|
}
|
||||||
|
public void Save(Persistent o)
|
||||||
|
{
|
||||||
|
PersistenceCache.Touch(o);
|
||||||
|
StorageAdapter.Save(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Ensure(Persistent o)
|
||||||
|
{
|
||||||
|
if (!StorageAdapter.Knows(o.GetType(), o.PersistenceID))
|
||||||
|
Save(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Load<T>(Guid persistenceID) where T: Persistent
|
||||||
|
{
|
||||||
|
return (T)Load(typeof(T), persistenceID);
|
||||||
|
}
|
||||||
|
public Persistent Load(Type type,Guid persistenceID)
|
||||||
|
{
|
||||||
|
if (persistenceID.Equals(Guid.Empty))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return PersistenceCache.Get(type, persistenceID);
|
||||||
|
} catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
Type realType = StorageAdapter.GetDiscriminator(type, persistenceID);
|
||||||
|
Persistent persistent = Activator.CreateInstance(type,true) as Persistent;
|
||||||
|
|
||||||
|
persistent.PersistenceID = persistenceID;
|
||||||
|
PersistenceCache.Touch(persistent);
|
||||||
|
|
||||||
|
GetDescriptor(realType).Attach(persistent);
|
||||||
|
|
||||||
|
StorageAdapter.Restore(persistent);
|
||||||
|
|
||||||
|
return persistent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<T> List<T>() where T:Persistent => List(typeof(T)).Select((x) => (T)x);
|
||||||
|
public IEnumerable<Persistent> List(Type type)
|
||||||
|
{
|
||||||
|
return ListIdentities(type).Select((x) => Load(x.Value, x.Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<KeyValuePair<Guid,Type>> ListIdentities(Type type)
|
||||||
|
{
|
||||||
|
return StorageAdapter.List(GetDescriptor(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Type LookupType(string fullName)
|
||||||
|
{
|
||||||
|
foreach (Type t in descriptors.Keys)
|
||||||
|
if (t.FullName.Equals(fullName))
|
||||||
|
return t;
|
||||||
|
throw new KeyNotFoundException(fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Descriptor GetDescriptor(Type type)
|
||||||
|
{
|
||||||
|
if (!descriptors.ContainsKey(type))
|
||||||
|
{
|
||||||
|
descriptors[type] = new Descriptor(this, type);
|
||||||
|
}
|
||||||
|
return descriptors[type];
|
||||||
|
}
|
||||||
|
public Descriptor GetDescriptor<T>() => GetDescriptor(typeof(T));
|
||||||
|
|
||||||
|
public FlatTypeMapping GetFlatTypeMapping(Type type)
|
||||||
|
{
|
||||||
|
if (!flatTypeMappings.ContainsKey(type))
|
||||||
|
{
|
||||||
|
if (type.IsArray)
|
||||||
|
{
|
||||||
|
flatTypeMappings[type] = new ArrayMapping(this, type);
|
||||||
|
}
|
||||||
|
else if (type.IsSubclassOf(typeof(Persistent)))
|
||||||
|
{
|
||||||
|
Add(type);
|
||||||
|
}
|
||||||
|
else if (type.IsGenericType && ((type.GetGenericTypeDefinition() == typeof(List<>)) || (type.GetGenericTypeDefinition() == typeof(IList<>))))
|
||||||
|
{
|
||||||
|
FlatTypeMapping elementMapping = GetFlatTypeMapping(type.GetGenericArguments()[0]);
|
||||||
|
flatTypeMappings[type] = new ListMapping(this, type);
|
||||||
|
} else {
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flatTypeMappings[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedFieldHandling CreateExtendedFieldHandling(FieldInfo fieldInfo)
|
||||||
|
{
|
||||||
|
if (fieldInfo.FieldType.IsGenericType){
|
||||||
|
Type genericTypeDefinition = fieldInfo.FieldType.GetGenericTypeDefinition();
|
||||||
|
|
||||||
|
if (genericTypeDefinition == typeof(ISet<>))
|
||||||
|
{
|
||||||
|
return new ISetExtendedHandling(this, fieldInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void PopulateFlatMappings()
|
||||||
|
{
|
||||||
|
flatTypeMappings[typeof(string)] = new StringMapping(this);
|
||||||
|
flatTypeMappings[typeof(int)] = new IntegerMapping(this);
|
||||||
|
flatTypeMappings[typeof(short)] = new IntegerMapping(this);
|
||||||
|
flatTypeMappings[typeof(byte)] = new IntegerMapping(this);
|
||||||
|
flatTypeMappings[typeof(float)] = new DoubleMapping(this);
|
||||||
|
flatTypeMappings[typeof(double)] = new DoubleMapping(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
namespace oodb
|
||||||
|
{
|
||||||
|
public abstract class Persistent
|
||||||
|
{
|
||||||
|
public Guid PersistenceID { get; internal set; }
|
||||||
|
|
||||||
|
public Persistent()
|
||||||
|
{
|
||||||
|
PersistenceID = Guid.NewGuid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
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("sharp-oodb")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("")]
|
||||||
|
[assembly: AssemblyCopyright("${AuthorCopyright}")]
|
||||||
|
[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("")]
|
|
@ -0,0 +1,221 @@
|
||||||
|
using System;
|
||||||
|
using oodb.descriptor;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Remoting.Metadata;
|
||||||
|
using System.Runtime.Remoting.Messaging;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Xml.Xsl.Runtime;
|
||||||
|
using oodb.index;
|
||||||
|
namespace oodb
|
||||||
|
{
|
||||||
|
public class QueryField
|
||||||
|
{
|
||||||
|
public string FieldName { get; }
|
||||||
|
|
||||||
|
public QueryField(String fieldName)
|
||||||
|
{
|
||||||
|
FieldName = fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Predicate Contains(object value)
|
||||||
|
{
|
||||||
|
return new Predicate.Contains(this, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Predicate
|
||||||
|
{
|
||||||
|
public QueryField QueryField { get; }
|
||||||
|
|
||||||
|
public Predicate(QueryField queryField)
|
||||||
|
{
|
||||||
|
QueryField = queryField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool MatchesTextValues => false;
|
||||||
|
|
||||||
|
public virtual bool TextMatch(string textValue) { throw new NotSupportedException(); }
|
||||||
|
public abstract bool Match(object value);
|
||||||
|
|
||||||
|
public OrPredicate Or => new OrPredicate(this);
|
||||||
|
|
||||||
|
|
||||||
|
public class OrPredicate : Predicate
|
||||||
|
{
|
||||||
|
public HashSet<Predicate> Predicates { get; } = new HashSet<Predicate>();
|
||||||
|
|
||||||
|
public OrPredicate(Predicate creator)
|
||||||
|
:base(creator.QueryField)
|
||||||
|
{
|
||||||
|
Predicates.Add(creator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrPredicate Contains(object value)
|
||||||
|
{
|
||||||
|
Predicates.Add(new Predicate.Contains(this.QueryField, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool MatchesTextValues
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
foreach (Predicate predicate in Predicates)
|
||||||
|
if (!predicate.MatchesTextValues)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TextMatch(string textValue)
|
||||||
|
{
|
||||||
|
foreach (Predicate predicate in Predicates)
|
||||||
|
if (predicate.TextMatch(textValue))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Match(object value)
|
||||||
|
{
|
||||||
|
foreach (Predicate predicate in Predicates)
|
||||||
|
if (predicate.Match(value))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Contains : Predicate
|
||||||
|
{
|
||||||
|
public object Value { get; }
|
||||||
|
|
||||||
|
public Contains(QueryField queryField,object value)
|
||||||
|
:base(queryField)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Match(object value)
|
||||||
|
{
|
||||||
|
if ((Value == null) || String.Empty.Equals(Value))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (value as string).Contains(Value as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Query<T> where T: Persistent
|
||||||
|
{
|
||||||
|
public virtual AlternativesQuery<T> Or(Query<T> alternativeQuery) => new AlternativesQuery<T>(this, alternativeQuery);
|
||||||
|
public virtual AlternativesQuery<T> Or(params Predicate[] predicates) => new AlternativesQuery<T>(this, new Query<T>(predicates));
|
||||||
|
|
||||||
|
public HashSet<Predicate> Predicates { get; } = new HashSet<Predicate>();
|
||||||
|
|
||||||
|
|
||||||
|
protected Query()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query(IEnumerable<Predicate> predicates)
|
||||||
|
{
|
||||||
|
foreach (Predicate predicate in predicates)
|
||||||
|
{
|
||||||
|
Predicates.Add(predicate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query(params Predicate[] predicates)
|
||||||
|
{
|
||||||
|
foreach (Predicate predicate in predicates)
|
||||||
|
{
|
||||||
|
Predicates.Add(predicate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Predicate> GetPredicates(QueryField queryField)
|
||||||
|
{
|
||||||
|
return Predicates.Where((x) => x.QueryField == queryField);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<T> Search(OODB oodb)
|
||||||
|
{
|
||||||
|
Descriptor descriptor = oodb.GetDescriptor<T>();
|
||||||
|
HashSet<QueryField> predicateFields = new HashSet<QueryField>();
|
||||||
|
|
||||||
|
foreach (Predicate predicate in Predicates)
|
||||||
|
{
|
||||||
|
predicateFields.Add(predicate.QueryField);
|
||||||
|
}
|
||||||
|
|
||||||
|
Guid[] results = null;
|
||||||
|
|
||||||
|
foreach (QueryField queryField in predicateFields)
|
||||||
|
{
|
||||||
|
FieldInfo fieldInfo = descriptor.GetFieldInfo(queryField.FieldName);
|
||||||
|
if (!oodb.StorageAdapter.HasSearchIndex(fieldInfo))
|
||||||
|
throw new NotSupportedException("Queries must use indexed fields");
|
||||||
|
|
||||||
|
SearchIndex searchIndex = oodb.StorageAdapter.GetSearchIndex(fieldInfo);
|
||||||
|
|
||||||
|
foreach (Predicate predicate in GetPredicates(queryField))
|
||||||
|
{
|
||||||
|
IEnumerable<Guid> myresults = searchIndex.Query(predicate);
|
||||||
|
if (results == null)
|
||||||
|
{
|
||||||
|
results = myresults.ToArray();
|
||||||
|
} else {
|
||||||
|
results = results.Intersect(myresults).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.Select((id)=>oodb.Load<T>(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AlternativesQuery<T> : Query<T> where T:Persistent
|
||||||
|
{
|
||||||
|
public HashSet<Query<T>> Alternatives = new HashSet<Query<T>>();
|
||||||
|
|
||||||
|
public AlternativesQuery(params Query<T>[] queries)
|
||||||
|
{
|
||||||
|
foreach (Query<T> alternative in queries)
|
||||||
|
Alternatives.Add(alternative);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override AlternativesQuery<T> Or(Query<T> alternativeQuery)
|
||||||
|
{
|
||||||
|
Alternatives.Add(alternativeQuery);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override AlternativesQuery<T> Or(params Predicate[] predicates)
|
||||||
|
{
|
||||||
|
Alternatives.Add(new Query<T>(predicates));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<T> Search(OODB oodb)
|
||||||
|
{
|
||||||
|
return Alternatives.SelectMany((alternative) => alternative.Search(oodb)).Distinct();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,271 @@
|
||||||
|
using System;
|
||||||
|
using oodb.descriptor;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using oodb.mapping;
|
||||||
|
using sharp.logging;
|
||||||
|
using System.Linq;
|
||||||
|
using oodb.index;
|
||||||
|
namespace oodb
|
||||||
|
{
|
||||||
|
public class StorageAdapter
|
||||||
|
{
|
||||||
|
public OODB OODB { get; }
|
||||||
|
public DirectoryInfo BaseDirectory { get; }
|
||||||
|
|
||||||
|
Dictionary<Type, TypeStorage> typeStorages = new Dictionary<Type, TypeStorage>();
|
||||||
|
|
||||||
|
public StorageAdapter(OODB oodb,DirectoryInfo baseDirectory)
|
||||||
|
{
|
||||||
|
OODB = oodb;
|
||||||
|
BaseDirectory = baseDirectory;
|
||||||
|
|
||||||
|
if (!BaseDirectory.Exists)
|
||||||
|
BaseDirectory.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<Type,TypeStorage> kvp in typeStorages)
|
||||||
|
{
|
||||||
|
foreach (Index index in kvp.Value.indeces)
|
||||||
|
index.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(Persistent persistent)
|
||||||
|
{
|
||||||
|
GetTypeStorage(persistent.GetType()).Save(persistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Restore(Persistent persistent)
|
||||||
|
{
|
||||||
|
GetTypeStorage(persistent.GetType()).Restore(persistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Knows(Type type,Guid persistenceID)
|
||||||
|
{
|
||||||
|
return GetTypeStorage(type).Knows(persistenceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reference(Persistent persistent, FieldInfo referencing)
|
||||||
|
{
|
||||||
|
GetTypeStorage(persistent.GetType()).Reference(persistent, referencing);
|
||||||
|
}
|
||||||
|
public void UnReference(Persistent persistent, FieldInfo referencing)
|
||||||
|
{
|
||||||
|
GetTypeStorage(persistent.GetType()).UnReference(persistent, referencing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<KeyValuePair<Guid,Type>> List(Descriptor descriptor)
|
||||||
|
{
|
||||||
|
return GetTypeStorage(descriptor.NativeType).List();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type GetDiscriminator(Type type,Guid persistenceID)
|
||||||
|
{
|
||||||
|
return GetTypeStorage(type).GetDiscriminator(persistenceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SearchIndex GetSearchIndex(FieldInfo fieldInfo)
|
||||||
|
{
|
||||||
|
return GetTypeStorage(fieldInfo.DeclaringType).GetSearchIndex(fieldInfo);
|
||||||
|
}
|
||||||
|
public bool HasSearchIndex(FieldInfo fieldInfo)
|
||||||
|
{
|
||||||
|
return GetTypeStorage(fieldInfo.DeclaringType).HasSearchIndex(fieldInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TypeStorage GetTypeStorage(Type type)
|
||||||
|
{
|
||||||
|
if (!typeStorages.ContainsKey(type))
|
||||||
|
{
|
||||||
|
typeStorages[type] = new TypeStorage(this, type);
|
||||||
|
}
|
||||||
|
return typeStorages[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TypeStorage
|
||||||
|
{
|
||||||
|
public StorageAdapter StorageAdapter { get; }
|
||||||
|
|
||||||
|
public Type PersistentType { get; }
|
||||||
|
public DirectoryInfo Directory { get; }
|
||||||
|
|
||||||
|
public Descriptor Descriptor { get; }
|
||||||
|
public TypeStorage BaseStorage { get; }
|
||||||
|
|
||||||
|
public HashSet<Index> indeces = new HashSet<Index>();
|
||||||
|
public Dictionary<FieldInfo, SearchIndex> searchIndeces = new Dictionary<FieldInfo, SearchIndex>();
|
||||||
|
|
||||||
|
public TypeStorage(StorageAdapter storageAdapter, Type type)
|
||||||
|
{
|
||||||
|
StorageAdapter = storageAdapter;
|
||||||
|
PersistentType = type;
|
||||||
|
|
||||||
|
Directory = new DirectoryInfo(Path.Combine(StorageAdapter.BaseDirectory.FullName, type.FullName));
|
||||||
|
if (!Directory.Exists)
|
||||||
|
Directory.Create();
|
||||||
|
|
||||||
|
Descriptor = storageAdapter.OODB.GetDescriptor(type);
|
||||||
|
if (Descriptor.BaseDescriptor != null)
|
||||||
|
{
|
||||||
|
BaseStorage = StorageAdapter.GetTypeStorage(Descriptor.BaseDescriptor.NativeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddIndex(Index index)
|
||||||
|
{
|
||||||
|
return indeces.Add(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasSearchIndex(FieldInfo fieldInfo) => searchIndeces.ContainsKey(fieldInfo);
|
||||||
|
|
||||||
|
public SearchIndex GetSearchIndex(FieldInfo fieldInfo)
|
||||||
|
{
|
||||||
|
if (!searchIndeces.ContainsKey(fieldInfo))
|
||||||
|
{
|
||||||
|
SearchIndex searchIndex = new SearchIndex(StorageAdapter.OODB, fieldInfo);
|
||||||
|
searchIndeces.Add(fieldInfo, searchIndex);
|
||||||
|
}
|
||||||
|
return searchIndeces[fieldInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveDiscriminator(Guid persistenceID)
|
||||||
|
{
|
||||||
|
foreach (Index index in indeces)
|
||||||
|
{
|
||||||
|
index.Remove(persistenceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.Delete(Path.Combine(Directory.FullName, String.Format("{0}.discriminator", persistenceID.ToString())));
|
||||||
|
if (BaseStorage != null)
|
||||||
|
BaseStorage.RemoveDiscriminator(persistenceID);
|
||||||
|
}
|
||||||
|
private String ReadDiscriminator(Guid persistenceID)
|
||||||
|
{
|
||||||
|
byte[] discriminator = File.ReadAllBytes(Path.Combine(Directory.FullName, String.Format("{0}.discriminator", persistenceID.ToString())));
|
||||||
|
return Encoding.UTF8.GetString(discriminator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteDiscriminator(Persistent persistent)
|
||||||
|
{
|
||||||
|
foreach (Index index in indeces)
|
||||||
|
{
|
||||||
|
index.Add(persistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (FileStream fileStream = new FileStream(Path.Combine(Directory.FullName,String.Format("{0}.discriminator",persistent.PersistenceID.ToString())),FileMode.Create))
|
||||||
|
{
|
||||||
|
byte[] discriminator = Encoding.UTF8.GetBytes(persistent.GetType().FullName);
|
||||||
|
fileStream.Write(discriminator, 0, discriminator.Length);
|
||||||
|
fileStream.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BaseStorage != null)
|
||||||
|
BaseStorage.WriteDiscriminator(persistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Knows(Guid persistenceID)
|
||||||
|
{
|
||||||
|
return File.Exists(Path.Combine(Directory.FullName, String.Format("{0}.discriminator", persistenceID.ToString())));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Save(Persistent persistent)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
WriteDiscriminator(persistent);
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Default.Log(e);
|
||||||
|
RemoveDiscriminator(persistent.PersistenceID);
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Descriptor descriptor = StorageAdapter.OODB.GetDescriptor(persistent.GetType());
|
||||||
|
|
||||||
|
XmlDocument xmlDocument = new XmlDocument();
|
||||||
|
XmlElement persistetInstance = xmlDocument.CreateElement("PersistetInstance");
|
||||||
|
|
||||||
|
xmlDocument.AppendChild(persistetInstance);
|
||||||
|
|
||||||
|
foreach (KeyValuePair<FieldInfo, FlatTypeMapping> flatField in descriptor.FlatMappings)
|
||||||
|
{
|
||||||
|
XmlElement fieldElement = xmlDocument.CreateElement("Field");
|
||||||
|
fieldElement.SetAttribute("Name", flatField.Key.Name);
|
||||||
|
fieldElement.AppendChild(flatField.Value.ToXml(xmlDocument, flatField.Key.GetValue(persistent)));
|
||||||
|
|
||||||
|
persistetInstance.AppendChild(fieldElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlDocument.Save(Path.Combine(Directory.FullName, String.Format("{0}.xml", persistent.PersistenceID.ToString())));
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Default.Log(LogLevel.ERROR, "StorageAdapter.Save(): {0}", e);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Restore(Persistent persistent)
|
||||||
|
{
|
||||||
|
Descriptor descriptor = StorageAdapter.OODB.GetDescriptor(persistent.GetType());
|
||||||
|
|
||||||
|
XmlDocument xmlDocument = new XmlDocument();
|
||||||
|
xmlDocument.Load(Path.Combine(Directory.FullName, String.Format("{0}.xml", persistent.PersistenceID.ToString())));
|
||||||
|
|
||||||
|
foreach (XmlElement fieldElement in xmlDocument.SelectNodes("PersistetInstance/Field"))
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
FieldInfo fieldInfo = Descriptor.GetFieldInfo(fieldElement.GetAttribute("Name"));
|
||||||
|
FlatTypeMapping flatTypeMapping = Descriptor.GetFlatTypeMapping(fieldInfo);
|
||||||
|
|
||||||
|
fieldInfo.SetValue(persistent, flatTypeMapping.FromXml(fieldElement.SelectSingleNode("Value") as XmlElement));
|
||||||
|
|
||||||
|
} catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
Logger.Default.Log(LogLevel.WARNING, "data for unknown field {0} ignored", fieldElement.GetAttribute("Name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reference(Persistent persistent, FieldInfo referencing)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
public void UnReference(Persistent persistent, FieldInfo referencing)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<KeyValuePair<Guid,Type>> List()
|
||||||
|
{
|
||||||
|
KeyValuePair<Guid,Type> create(FileInfo fileInfo)
|
||||||
|
{
|
||||||
|
Guid persistenceID = Guid.Parse(fileInfo.Name.Substring(0, fileInfo.Name.Length - fileInfo.Extension.Length));
|
||||||
|
return new KeyValuePair<Guid, Type>(persistenceID,GetDiscriminator(persistenceID));
|
||||||
|
}
|
||||||
|
return Directory.GetFiles("*.discriminator").Select(create);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type GetDiscriminator(Guid persistenceID)
|
||||||
|
{
|
||||||
|
String typeName = ReadDiscriminator(persistenceID);
|
||||||
|
return StorageAdapter.OODB.LookupType(typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
namespace oodb.attributes
|
||||||
|
{
|
||||||
|
public class IndexedAttribute : Attribute
|
||||||
|
{
|
||||||
|
public IndexedAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
namespace oodb.attributes
|
||||||
|
{
|
||||||
|
public class ReferencedFieldAttribute : Attribute
|
||||||
|
{
|
||||||
|
public String FieldName { get; }
|
||||||
|
|
||||||
|
public ReferencedFieldAttribute(String FieldName)
|
||||||
|
{
|
||||||
|
this.FieldName = FieldName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
namespace oodb.attributes
|
||||||
|
{
|
||||||
|
public class UniqueAttribute : Attribute
|
||||||
|
{
|
||||||
|
public UniqueAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using oodb.mapping;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using sharp.logging;
|
||||||
|
using oodb.attributes;
|
||||||
|
using oodb.index;
|
||||||
|
namespace oodb.descriptor
|
||||||
|
{
|
||||||
|
public class Descriptor
|
||||||
|
{
|
||||||
|
public OODB OODB { get; }
|
||||||
|
public Type NativeType { get; }
|
||||||
|
|
||||||
|
public Descriptor BaseDescriptor { get; }
|
||||||
|
public IEnumerable<KeyValuePair<FieldInfo, FlatTypeMapping>> FlatMappings => flatMappings;
|
||||||
|
|
||||||
|
|
||||||
|
Dictionary<FieldInfo, FlatTypeMapping> flatMappings = new Dictionary<FieldInfo, FlatTypeMapping>();
|
||||||
|
Dictionary<FieldInfo, ExtendedFieldHandling> extendedFieldHandlers = new Dictionary<FieldInfo, ExtendedFieldHandling>();
|
||||||
|
|
||||||
|
public Descriptor(OODB oodb,Type type)
|
||||||
|
{
|
||||||
|
OODB = oodb;
|
||||||
|
NativeType = type;
|
||||||
|
|
||||||
|
OODB.descriptors.Add(NativeType, this);
|
||||||
|
OODB.flatTypeMappings[type] = new ReferenceMapping(oodb, type);
|
||||||
|
|
||||||
|
if (type.BaseType != typeof(Persistent))
|
||||||
|
{
|
||||||
|
BaseDescriptor = OODB.GetDescriptor(type.BaseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstructMappings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
foreach (ExtendedFieldHandling extendedFieldHandling in extendedFieldHandlers.Values)
|
||||||
|
{
|
||||||
|
extendedFieldHandling.Initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Attach(Persistent persistent)
|
||||||
|
{
|
||||||
|
foreach (ExtendedFieldHandling extendedFieldHandling in extendedFieldHandlers.Values)
|
||||||
|
{
|
||||||
|
extendedFieldHandling.Attach(persistent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Detach(Persistent persistent)
|
||||||
|
{
|
||||||
|
foreach (ExtendedFieldHandling extendedFieldHandling in extendedFieldHandlers.Values)
|
||||||
|
{
|
||||||
|
extendedFieldHandling.Detach(persistent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FieldInfo GetFieldInfo(string fieldName)
|
||||||
|
{
|
||||||
|
foreach (FieldInfo fieldInfo in flatMappings.Keys)
|
||||||
|
if (fieldInfo.Name.Equals(fieldName))
|
||||||
|
return fieldInfo;
|
||||||
|
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlatTypeMapping GetFlatTypeMapping(FieldInfo fieldInfo)
|
||||||
|
{
|
||||||
|
return flatMappings[fieldInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void ConstructMappings()
|
||||||
|
{
|
||||||
|
if (BaseDescriptor != null)
|
||||||
|
{
|
||||||
|
foreach (FieldInfo baseField in BaseDescriptor.flatMappings.Keys)
|
||||||
|
{
|
||||||
|
flatMappings.Add(baseField, BaseDescriptor.flatMappings[baseField]);
|
||||||
|
}
|
||||||
|
foreach (FieldInfo baseField in BaseDescriptor.extendedFieldHandlers.Keys)
|
||||||
|
{
|
||||||
|
extendedFieldHandlers.Add(baseField, BaseDescriptor.extendedFieldHandlers[baseField]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (FieldInfo fieldInfo in NativeType.GetFields(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic))
|
||||||
|
{
|
||||||
|
if (fieldInfo.GetCustomAttribute<IndexedAttribute>() != null)
|
||||||
|
{
|
||||||
|
OODB.StorageAdapter.GetSearchIndex(fieldInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FlatTypeMapping flatTypeMapping = OODB.GetFlatTypeMapping(fieldInfo.FieldType);
|
||||||
|
flatMappings.Add(fieldInfo, flatTypeMapping);
|
||||||
|
|
||||||
|
if (fieldInfo.GetCustomAttribute<UniqueAttribute>() != null)
|
||||||
|
{
|
||||||
|
Unique uniqueIndex = new Unique(OODB, fieldInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
ExtendedFieldHandling extendedFieldHandling = OODB.CreateExtendedFieldHandling(fieldInfo);
|
||||||
|
extendedFieldHandlers.Add(fieldInfo, extendedFieldHandling);
|
||||||
|
|
||||||
|
} catch (NotSupportedException)
|
||||||
|
{
|
||||||
|
Logger.Default.Log("Ignoring unsupported Field {0}", fieldInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml;
|
||||||
|
using oodb.mapping;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
using System.Linq;
|
||||||
|
namespace oodb.index
|
||||||
|
{
|
||||||
|
public abstract class Index
|
||||||
|
{
|
||||||
|
public OODB OODB { get; }
|
||||||
|
public FieldInfo FieldInfo { get; }
|
||||||
|
|
||||||
|
public String FileName { get; }
|
||||||
|
|
||||||
|
public FlatTypeMapping ValueMapping { get; }
|
||||||
|
public FlatTypeMapping StorageMapping { get; protected set; }
|
||||||
|
|
||||||
|
public Index(OODB oodb, FieldInfo fieldInfo)
|
||||||
|
{
|
||||||
|
OODB = oodb;
|
||||||
|
FieldInfo = fieldInfo;
|
||||||
|
|
||||||
|
ValueMapping = OODB.GetFlatTypeMapping(fieldInfo.FieldType);
|
||||||
|
StorageMapping = ValueMapping;
|
||||||
|
|
||||||
|
FileName = Path.Combine(
|
||||||
|
OODB.StorageAdapter.GetTypeStorage(FieldInfo.DeclaringType).Directory.FullName,
|
||||||
|
String.Format("index_{0}_{1}_{2}.xml", GetType().Name, FieldInfo.DeclaringType.Name, FieldInfo.Name)
|
||||||
|
);
|
||||||
|
|
||||||
|
OODB.StorageAdapter.GetTypeStorage(fieldInfo.DeclaringType).AddIndex(this);
|
||||||
|
|
||||||
|
Prepare();
|
||||||
|
|
||||||
|
Load();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void Prepare();
|
||||||
|
|
||||||
|
public abstract IEnumerable<KeyValuePair<Guid, object>> RetrieveIndexValues();
|
||||||
|
public abstract void RestoreIndexValues(IEnumerable<KeyValuePair<Guid, object>> indexValues);
|
||||||
|
|
||||||
|
public abstract void Add(Persistent persistent);
|
||||||
|
public abstract void Remove(Guid persistenceID);
|
||||||
|
|
||||||
|
public void Remove(Persistent persistent)
|
||||||
|
{
|
||||||
|
Remove(persistent.PersistenceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract IEnumerable<Guid> Query();
|
||||||
|
|
||||||
|
|
||||||
|
public void Load()
|
||||||
|
{
|
||||||
|
if (File.Exists(FileName))
|
||||||
|
{
|
||||||
|
XmlDocument xmlDocument = new XmlDocument();
|
||||||
|
xmlDocument.Load(FileName);
|
||||||
|
|
||||||
|
RestoreIndexValues(
|
||||||
|
xmlDocument.SelectNodes("/Index/Entry").Cast<XmlElement>().Select((entry) => new KeyValuePair<Guid, object>(Guid.Parse(entry.GetAttribute("PersistenceID")), StorageMapping.FromXml(entry.SelectSingleNode("Value") as XmlElement)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
XmlDocument xmlDocument = new XmlDocument();
|
||||||
|
XmlElement indexElement = xmlDocument.CreateElement("Index");
|
||||||
|
indexElement.SetAttribute("Type", GetType().FullName);
|
||||||
|
|
||||||
|
xmlDocument.AppendChild(indexElement);
|
||||||
|
|
||||||
|
|
||||||
|
foreach (KeyValuePair<Guid,object> entry in RetrieveIndexValues())
|
||||||
|
{
|
||||||
|
XmlElement xmlEntry = xmlDocument.CreateElement("Entry");
|
||||||
|
xmlEntry.SetAttribute("PersistenceID", entry.Key.ToString());
|
||||||
|
xmlEntry.AppendChild(StorageMapping.ToXml(xmlDocument, entry.Value));
|
||||||
|
indexElement.AppendChild(xmlEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlDocument.Save(FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return FileName.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is Index)
|
||||||
|
{
|
||||||
|
Index other = obj as Index;
|
||||||
|
return FileName.Equals(other.FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using oodb.mapping;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections;
|
||||||
|
namespace oodb.index
|
||||||
|
{
|
||||||
|
public class SearchIndex : Index
|
||||||
|
{
|
||||||
|
|
||||||
|
Dictionary<string, ISet<Guid>> index = new Dictionary<string, ISet<Guid>>();
|
||||||
|
Dictionary<Guid, string> reverseIndex = new Dictionary<Guid, string>();
|
||||||
|
|
||||||
|
public SearchIndex(OODB oodb,FieldInfo fieldInfo)
|
||||||
|
:base(oodb,fieldInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Prepare()
|
||||||
|
{
|
||||||
|
StorageMapping = OODB.GetFlatTypeMapping(typeof(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISet<Guid> GetBucket(string value)
|
||||||
|
{
|
||||||
|
if (!index.ContainsKey(value))
|
||||||
|
{
|
||||||
|
index.Add(value, new HashSet<Guid>());
|
||||||
|
}
|
||||||
|
return index[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(string value,Guid persistenceID)
|
||||||
|
{
|
||||||
|
if (reverseIndex.ContainsKey(persistenceID))
|
||||||
|
{
|
||||||
|
if (!reverseIndex[persistenceID].Equals(value))
|
||||||
|
{
|
||||||
|
GetBucket(reverseIndex[persistenceID]).Remove(persistenceID);
|
||||||
|
GetBucket(value).Add(persistenceID);
|
||||||
|
reverseIndex[persistenceID] = value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reverseIndex[persistenceID] = value;
|
||||||
|
GetBucket(value).Add(persistenceID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Add(Persistent persistent)
|
||||||
|
{
|
||||||
|
Add(ValueMapping.ToText(FieldInfo.GetValue(persistent)), persistent.PersistenceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<Guid> Query()
|
||||||
|
{
|
||||||
|
return reverseIndex.Keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Guid> QueryTextValue(string textValue)
|
||||||
|
{
|
||||||
|
return GetBucket(textValue);
|
||||||
|
}
|
||||||
|
public IEnumerable<Guid> Query(object value)
|
||||||
|
{
|
||||||
|
return QueryTextValue(ValueMapping.ToText(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Guid> Query(Predicate predicate)
|
||||||
|
{
|
||||||
|
if (predicate.MatchesTextValues)
|
||||||
|
{
|
||||||
|
return reverseIndex.Where((kvp) => predicate.TextMatch(kvp.Value)).Select((kvp) => kvp.Key);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return reverseIndex.Where((kvp) => predicate.Match(ValueMapping.FromText(kvp.Value))).Select((kvp) => kvp.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Remove(Guid persistenceID)
|
||||||
|
{
|
||||||
|
if (reverseIndex.ContainsKey(persistenceID))
|
||||||
|
{
|
||||||
|
GetBucket(reverseIndex[persistenceID]).Remove(persistenceID);
|
||||||
|
reverseIndex.Remove(persistenceID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RestoreIndexValues(IEnumerable<KeyValuePair<Guid, object>> indexValues)
|
||||||
|
{
|
||||||
|
reverseIndex.Clear();
|
||||||
|
index.Clear();
|
||||||
|
|
||||||
|
foreach (KeyValuePair<Guid,object> kvp in indexValues)
|
||||||
|
{
|
||||||
|
Add(kvp.Value as string, kvp.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<KeyValuePair<Guid, object>> RetrieveIndexValues()
|
||||||
|
{
|
||||||
|
return reverseIndex.Select((x) => new KeyValuePair<Guid, object>(x.Key, x.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
namespace oodb.index
|
||||||
|
{
|
||||||
|
public class Unique : Index
|
||||||
|
{
|
||||||
|
|
||||||
|
Dictionary<Guid, object> uniqueForward = new Dictionary<Guid, object>();
|
||||||
|
Dictionary<object, Guid> uniqueReverse = new Dictionary<object, Guid>();
|
||||||
|
|
||||||
|
public Unique(OODB oodb,FieldInfo fieldInfo)
|
||||||
|
:base(oodb,fieldInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Prepare()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Add(Persistent persistent)
|
||||||
|
{
|
||||||
|
object value = FieldInfo.GetValue(persistent);
|
||||||
|
Guid persistenceId = persistent.PersistenceID;
|
||||||
|
|
||||||
|
if (uniqueReverse.ContainsKey(value))
|
||||||
|
{
|
||||||
|
if (uniqueReverse[value].Equals(persistenceId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw new ArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uniqueForward.ContainsKey(persistenceId))
|
||||||
|
Remove(persistenceId);
|
||||||
|
|
||||||
|
uniqueForward.Add(persistenceId, value);
|
||||||
|
uniqueReverse.Add(value, persistenceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<Guid> Query()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Remove(Guid persistenceID)
|
||||||
|
{
|
||||||
|
if (uniqueForward.ContainsKey(persistenceID))
|
||||||
|
{
|
||||||
|
uniqueReverse.Remove(uniqueForward[persistenceID]);
|
||||||
|
uniqueForward.Remove(persistenceID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void RestoreIndexValues(IEnumerable<KeyValuePair<Guid, object>> indexValues)
|
||||||
|
{
|
||||||
|
uniqueForward.Clear();
|
||||||
|
uniqueReverse.Clear();
|
||||||
|
|
||||||
|
foreach (KeyValuePair<Guid,object> entry in indexValues)
|
||||||
|
{
|
||||||
|
uniqueForward.Add(entry.Key, entry.Value);
|
||||||
|
uniqueReverse.Add(entry.Value, entry.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public override IEnumerable<KeyValuePair<Guid, object>> RetrieveIndexValues()
|
||||||
|
{
|
||||||
|
return uniqueForward;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace oodb.mapping
|
||||||
|
{
|
||||||
|
public class ArrayMapping : ListMapping
|
||||||
|
{
|
||||||
|
public ArrayMapping(OODB oodb,Type type)
|
||||||
|
:base(oodb,typeof(List<>).MakeGenericType(type.GetElementType()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override XmlElement ToXml(XmlDocument xmlDocument, object value)
|
||||||
|
{
|
||||||
|
IList list = value as IList;
|
||||||
|
Array array = Array.CreateInstance(ElementMapping.NativeType, list.Count);
|
||||||
|
(list as IList).CopyTo(array, 0);
|
||||||
|
|
||||||
|
return base.ToXml(xmlDocument,list);
|
||||||
|
}
|
||||||
|
public override object FromXml(XmlElement xmlValue)
|
||||||
|
{
|
||||||
|
IList list = base.FromXml(xmlValue) as IList;
|
||||||
|
Array array = Array.CreateInstance(ElementMapping.NativeType, list.Count) as Array;
|
||||||
|
list.CopyTo(array, list.Count);
|
||||||
|
return array;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace oodb.mapping
|
||||||
|
{
|
||||||
|
public class DoubleMapping : NaiveMapping
|
||||||
|
{
|
||||||
|
public DoubleMapping(OODB oodb)
|
||||||
|
: base(oodb, typeof(double))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object FromText(string text)
|
||||||
|
{
|
||||||
|
double iValue = double.Parse(text, CultureInfo.InvariantCulture);
|
||||||
|
if (NativeType != typeof(double))
|
||||||
|
{
|
||||||
|
return Convert.ChangeType(iValue, NativeType);
|
||||||
|
}
|
||||||
|
return iValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToText(object value)
|
||||||
|
{
|
||||||
|
double iValue = (double)value;
|
||||||
|
return iValue.ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Xml;
|
||||||
|
namespace oodb.mapping
|
||||||
|
{
|
||||||
|
public abstract class ExtendedFieldHandling
|
||||||
|
{
|
||||||
|
public OODB OODB { get; }
|
||||||
|
public FieldInfo FieldInfo { get; }
|
||||||
|
|
||||||
|
public ExtendedFieldHandling(OODB oodb,FieldInfo fieldInfo)
|
||||||
|
{
|
||||||
|
OODB = oodb;
|
||||||
|
FieldInfo = fieldInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Initialize(){}
|
||||||
|
|
||||||
|
public abstract void Save(XmlElement persistenceElement,Persistent persistent);
|
||||||
|
public abstract void Load(XmlElement persistenceElement,Persistent persistent);
|
||||||
|
|
||||||
|
public abstract void Attach(Persistent persistent);
|
||||||
|
public abstract void Detach(Persistent persistent);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace oodb.mapping
|
||||||
|
{
|
||||||
|
public abstract class FlatTypeMapping
|
||||||
|
{
|
||||||
|
public OODB OODB { get; }
|
||||||
|
public Type NativeType { get; }
|
||||||
|
|
||||||
|
public FlatTypeMapping(OODB oodb, Type nativeType)
|
||||||
|
{
|
||||||
|
OODB = oodb;
|
||||||
|
NativeType = nativeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlElement CreateEmptyValueElement(XmlDocument xmlDocument)
|
||||||
|
{
|
||||||
|
XmlElement value = xmlDocument.CreateElement("Value");
|
||||||
|
value.SetAttribute("Type", NativeType.FullName);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract XmlElement ToXml(XmlDocument xmlDocument, object value);
|
||||||
|
public abstract object FromXml(XmlElement xmlValue);
|
||||||
|
|
||||||
|
public abstract String ToText(object value);
|
||||||
|
public abstract object FromText(string text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class NaiveMapping : FlatTypeMapping
|
||||||
|
{
|
||||||
|
public NaiveMapping(OODB oodb, Type nativeType)
|
||||||
|
:base(oodb,nativeType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object FromXml(XmlElement xmlValue)
|
||||||
|
{
|
||||||
|
if (!NativeType.FullName.Equals(xmlValue.GetAttribute("Type")))
|
||||||
|
throw new ArgumentException("Type != NativeType", nameof(xmlValue));
|
||||||
|
|
||||||
|
return FromText(xmlValue.InnerText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override XmlElement ToXml(XmlDocument xmlDocument, object value)
|
||||||
|
{
|
||||||
|
XmlElement valueElement = CreateEmptyValueElement(xmlDocument);
|
||||||
|
if (value != null)
|
||||||
|
valueElement.InnerText = ToText(value);
|
||||||
|
|
||||||
|
return valueElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace oodb.mapping
|
||||||
|
{
|
||||||
|
public class IntegerMapping : NaiveMapping
|
||||||
|
{
|
||||||
|
public IntegerMapping(OODB oodb)
|
||||||
|
: base(oodb, typeof(int))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object FromText(String text)
|
||||||
|
{
|
||||||
|
int iValue = int.Parse(text, CultureInfo.InvariantCulture);
|
||||||
|
if (NativeType != typeof(int))
|
||||||
|
{
|
||||||
|
return Convert.ChangeType(iValue, NativeType);
|
||||||
|
}
|
||||||
|
return iValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToText(object value)
|
||||||
|
{
|
||||||
|
int iValue = (int)value;
|
||||||
|
return iValue.ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace oodb.mapping
|
||||||
|
{
|
||||||
|
public class ListMapping : NaiveMapping
|
||||||
|
{
|
||||||
|
public FlatTypeMapping ElementMapping { get; }
|
||||||
|
|
||||||
|
public ListMapping(OODB oodb, Type type)
|
||||||
|
: base(oodb, type)
|
||||||
|
{
|
||||||
|
ElementMapping = OODB.GetFlatTypeMapping(type.GetGenericArguments()[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object FromXml(XmlElement xmlValue)
|
||||||
|
{
|
||||||
|
if (!NativeType.FullName.Equals(xmlValue.GetAttribute("Type")))
|
||||||
|
throw new ArgumentException("Type != NativeType", nameof(xmlValue));
|
||||||
|
|
||||||
|
IList list = Activator.CreateInstance(typeof(List<>).MakeGenericType(ElementMapping.NativeType)) as IList;
|
||||||
|
foreach (XmlNode elementNode in xmlValue.ChildNodes)
|
||||||
|
{
|
||||||
|
if ((elementNode is XmlElement) && ((((XmlElement)elementNode).Name.Equals("Value"))))
|
||||||
|
{
|
||||||
|
list.Add(ElementMapping.FromXml(elementNode as XmlElement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override XmlElement ToXml(XmlDocument xmlDocument, object value)
|
||||||
|
{
|
||||||
|
XmlElement valueElement = CreateEmptyValueElement(xmlDocument);
|
||||||
|
|
||||||
|
IList list = value as IList;
|
||||||
|
|
||||||
|
for (int n = 0; n < list.Count; n++)
|
||||||
|
{
|
||||||
|
valueElement.AppendChild(ElementMapping.ToXml(xmlDocument, list[n]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return valueElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToText(object value)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object FromText(string text)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace oodb.mapping
|
||||||
|
{
|
||||||
|
public class ReferenceMapping : NaiveMapping
|
||||||
|
{
|
||||||
|
public ReferenceMapping(OODB oodb, Type type)
|
||||||
|
: base(oodb, type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object FromText(string text)
|
||||||
|
{
|
||||||
|
if (String.Empty.Equals(text))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Guid persistenceID = Guid.Parse(text);
|
||||||
|
return OODB.Load(NativeType, persistenceID);
|
||||||
|
}
|
||||||
|
public override string ToText(object value)
|
||||||
|
{
|
||||||
|
Persistent reference = value as Persistent;
|
||||||
|
|
||||||
|
if (reference == null)
|
||||||
|
{
|
||||||
|
return Guid.Empty.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string text = reference.PersistenceID.ToString();
|
||||||
|
OODB.Ensure(reference);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace oodb.mapping
|
||||||
|
{
|
||||||
|
public class StringMapping : NaiveMapping
|
||||||
|
{
|
||||||
|
public StringMapping(OODB oodb)
|
||||||
|
: base(oodb, typeof(string))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object FromText(string text)
|
||||||
|
{
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToText(object value)
|
||||||
|
{
|
||||||
|
return value as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Xml;
|
||||||
|
using oodb.attributes;
|
||||||
|
|
||||||
|
namespace oodb.mapping.collections
|
||||||
|
{
|
||||||
|
public class ISetExtendedHandling : ExtendedFieldHandling
|
||||||
|
{
|
||||||
|
public Type ReferencedType { get; }
|
||||||
|
public FieldInfo ReferencedField { get; protected set; }
|
||||||
|
|
||||||
|
public Type ImplementationType { get; }
|
||||||
|
|
||||||
|
public ISetExtendedHandling(OODB oodb,FieldInfo fieldInfo)
|
||||||
|
:base(oodb,fieldInfo)
|
||||||
|
{
|
||||||
|
ReferencedType = fieldInfo.FieldType.GetGenericArguments()[0];
|
||||||
|
ImplementationType = typeof(ISetImplementation<>).MakeGenericType(ReferencedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
ReferencedFieldAttribute referencedFieldAttribute = FieldInfo.GetCustomAttribute<ReferencedFieldAttribute>();
|
||||||
|
string refFieldName = referencedFieldAttribute != null ? referencedFieldAttribute.FieldName : FieldInfo.DeclaringType.Name;
|
||||||
|
ReferencedField = ReferencedType.GetField(refFieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
OODB.StorageAdapter.GetSearchIndex(ReferencedField);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Attach(Persistent persistent)
|
||||||
|
{
|
||||||
|
object iset = FieldInfo.GetValue(persistent);
|
||||||
|
|
||||||
|
if (ImplementationType != iset.GetType())
|
||||||
|
{
|
||||||
|
object impl = Activator.CreateInstance(ImplementationType,OODB,FieldInfo,persistent);
|
||||||
|
FieldInfo.SetValue(persistent, impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Detach(Persistent persistent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Load(XmlElement persistenceElement, Persistent persistent)
|
||||||
|
{
|
||||||
|
Attach(persistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Save(XmlElement persistenceElement, Persistent persistent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using oodb.attributes;
|
||||||
|
using oodb.index;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace oodb.mapping.collections
|
||||||
|
{
|
||||||
|
public class ISetImplementation<T> : ISet<T> where T: Persistent
|
||||||
|
{
|
||||||
|
public OODB OODB { get; }
|
||||||
|
public FieldInfo FieldInfo { get; }
|
||||||
|
|
||||||
|
public Persistent Owner { get; }
|
||||||
|
|
||||||
|
public FieldInfo ReferencedField { get; }
|
||||||
|
public Type ReferencedType { get; }
|
||||||
|
|
||||||
|
public SearchIndex SearchIndex { get; }
|
||||||
|
|
||||||
|
public ISetImplementation(OODB oodb,FieldInfo fieldInfo,Persistent owner)
|
||||||
|
{
|
||||||
|
OODB = oodb;
|
||||||
|
FieldInfo = fieldInfo;
|
||||||
|
Owner = owner;
|
||||||
|
|
||||||
|
ReferencedType = fieldInfo.FieldType.GetGenericArguments()[0];
|
||||||
|
|
||||||
|
ReferencedFieldAttribute referencedFieldAttribute = FieldInfo.GetCustomAttribute<ReferencedFieldAttribute>();
|
||||||
|
string refFieldName = referencedFieldAttribute != null ? referencedFieldAttribute.FieldName : FieldInfo.DeclaringType.Name;
|
||||||
|
ReferencedField = ReferencedType.GetField(refFieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
SearchIndex = OODB.StorageAdapter.GetSearchIndex(ReferencedField);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Guid> ElementPersistenceIDs => SearchIndex.QueryTextValue(Owner.PersistenceID.ToString());
|
||||||
|
|
||||||
|
public int Count => ElementPersistenceIDs.Count();
|
||||||
|
public bool IsReadOnly => false;
|
||||||
|
|
||||||
|
public bool Add(T item)
|
||||||
|
{
|
||||||
|
if (!Contains(item))
|
||||||
|
{
|
||||||
|
ReferencedField.SetValue(item, Owner);
|
||||||
|
OODB.Save(item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(T item)
|
||||||
|
{
|
||||||
|
if (Contains(item))
|
||||||
|
{
|
||||||
|
ReferencedField.SetValue(item, null);
|
||||||
|
OODB.Save(item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
foreach (T item in this)
|
||||||
|
Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(T item)
|
||||||
|
{
|
||||||
|
Persistent persistentItem = item as Persistent;
|
||||||
|
foreach (Guid elementID in ElementPersistenceIDs)
|
||||||
|
if (elementID.Equals(persistentItem.PersistenceID))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(T[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExceptWith(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<T> GetEnumerator()
|
||||||
|
{
|
||||||
|
return ElementPersistenceIDs.Select((id) => OODB.Load<T>(id)).GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IntersectWith(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsProperSubsetOf(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsProperSupersetOf(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSubsetOf(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSupersetOf(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Overlaps(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetEquals(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SymmetricExceptWith(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnionWith(IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICollection<T>.Add(T item)
|
||||||
|
{
|
||||||
|
Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using oodb.descriptor;
|
||||||
|
using System.Dynamic;
|
||||||
|
namespace oodb.persistence
|
||||||
|
{
|
||||||
|
public class PersistenceCache
|
||||||
|
{
|
||||||
|
public OODB OODB { get; }
|
||||||
|
|
||||||
|
|
||||||
|
Dictionary<Type, TypeCache> typeCaches = new Dictionary<Type, TypeCache>();
|
||||||
|
|
||||||
|
|
||||||
|
public PersistenceCache(OODB oodb)
|
||||||
|
{
|
||||||
|
OODB = oodb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeCache GetTypeCache(Type type)
|
||||||
|
{
|
||||||
|
if (!typeCaches.ContainsKey(type))
|
||||||
|
typeCaches[type] = new TypeCache(this,type);
|
||||||
|
return typeCaches[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Persistent Get(Type type,Guid persistenceID)
|
||||||
|
{
|
||||||
|
return GetTypeCache(type).Get(persistenceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Touch(Persistent persistent)
|
||||||
|
{
|
||||||
|
GetTypeCache(persistent.GetType()).Touch(persistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(Persistent persistent)
|
||||||
|
{
|
||||||
|
GetTypeCache(persistent.GetType()).Remove(persistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TypeCache
|
||||||
|
{
|
||||||
|
PersistenceCache PersistenceCache { get; }
|
||||||
|
TypeCache BaseCache { get; }
|
||||||
|
|
||||||
|
Type CacheType { get; }
|
||||||
|
|
||||||
|
Descriptor Descriptor { get; }
|
||||||
|
|
||||||
|
Dictionary<Guid, WeakReference> cache = new Dictionary<Guid, WeakReference>();
|
||||||
|
|
||||||
|
public TypeCache(PersistenceCache persistenceCache,Type type)
|
||||||
|
{
|
||||||
|
PersistenceCache = persistenceCache;
|
||||||
|
CacheType = type;
|
||||||
|
Descriptor = persistenceCache.OODB.GetDescriptor(type);
|
||||||
|
|
||||||
|
if (Descriptor.BaseDescriptor != null)
|
||||||
|
BaseCache = persistenceCache.GetTypeCache(Descriptor.BaseDescriptor.NativeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Persistent Get(Guid persistenceID)
|
||||||
|
{
|
||||||
|
WeakReference weakReference = cache[persistenceID];
|
||||||
|
if (!weakReference.IsAlive)
|
||||||
|
{
|
||||||
|
Remove(persistenceID);
|
||||||
|
throw new KeyNotFoundException(persistenceID.ToString());
|
||||||
|
}
|
||||||
|
return weakReference.Target as Persistent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Touch(Persistent persistent)
|
||||||
|
{
|
||||||
|
cache[persistent.PersistenceID] = new WeakReference(persistent);
|
||||||
|
if (Descriptor.BaseDescriptor != null)
|
||||||
|
PersistenceCache.GetTypeCache(Descriptor.BaseDescriptor.NativeType).Touch(persistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(Persistent persistent)
|
||||||
|
{
|
||||||
|
Remove(persistent.PersistenceID);
|
||||||
|
}
|
||||||
|
public void Remove(Guid persistenceID)
|
||||||
|
{
|
||||||
|
cache.Remove(persistenceID);
|
||||||
|
if (Descriptor.BaseDescriptor != null)
|
||||||
|
{
|
||||||
|
PersistenceCache.GetTypeCache(Descriptor.BaseDescriptor.NativeType).Remove(persistenceID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProjectGuid>{FF9FA8D2-5E89-4609-83F0-B9512DF777BE}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<RootNamespace>oodb</RootNamespace>
|
||||||
|
<AssemblyName>sharp-oodb</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<ExternalConsole>true</ExternalConsole>
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release</OutputPath>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<ExternalConsole>true</ExternalConsole>
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="OODB.cs" />
|
||||||
|
<Compile Include="mapping\FlatTypeMapping.cs" />
|
||||||
|
<Compile Include="Persistent.cs" />
|
||||||
|
<Compile Include="descriptor\Descriptor.cs" />
|
||||||
|
<Compile Include="mapping\ListMapping.cs" />
|
||||||
|
<Compile Include="mapping\StringMapping.cs" />
|
||||||
|
<Compile Include="mapping\IntegerMapping.cs" />
|
||||||
|
<Compile Include="mapping\DoubleMapping.cs" />
|
||||||
|
<Compile Include="mapping\ReferenceMapping.cs" />
|
||||||
|
<Compile Include="persistence\PersistenceCache.cs" />
|
||||||
|
<Compile Include="StorageAdapter.cs" />
|
||||||
|
<Compile Include="mapping\ArrayMapping.cs" />
|
||||||
|
<Compile Include="index\Index.cs" />
|
||||||
|
<Compile Include="index\Unique.cs" />
|
||||||
|
<Compile Include="attributes\UniqueAttribute.cs" />
|
||||||
|
<Compile Include="attributes\ReferencedFieldAttribute.cs" />
|
||||||
|
<Compile Include="mapping\collections\ISetImplementation.cs" />
|
||||||
|
<Compile Include="Query.cs" />
|
||||||
|
<Compile Include="index\SearchIndex.cs" />
|
||||||
|
<Compile Include="mapping\ExtendedFieldHandling.cs" />
|
||||||
|
<Compile Include="mapping\collections\ISetExtendedHandling.cs" />
|
||||||
|
<Compile Include="attributes\IndexedAttribute.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="mapping\" />
|
||||||
|
<Folder Include="descriptor\" />
|
||||||
|
<Folder Include="persistence\" />
|
||||||
|
<Folder Include="index\" />
|
||||||
|
<Folder Include="attributes\" />
|
||||||
|
<Folder Include="mapping\collections\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\sharp-logging\sharp.logging.csproj">
|
||||||
|
<Project>{D471A566-9FB6-41B2-A777-3C32874ECD0E}</Project>
|
||||||
|
<Name>sharp.logging</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
Loading…
Reference in New Issue