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 descriptors = new Dictionary(); internal Dictionary flatTypeMappings = new Dictionary(); 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() where T : Persistent => Add(typeof(T)); public OODB Add(Type type) { GetDescriptor(type); return this; } public void Save(IEnumerable 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(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 List() where T:Persistent => List(typeof(T)).Select((x) => (T)x); public IEnumerable List(Type type) { return ListIdentities(type).Select((x) => Load(x.Value, x.Key)); } private IEnumerable> 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() => 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); } } }