using Esiur.Data; using Esiur.Engine; using Esiur.Resource.Template; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Esiur.Resource { // Centeral Resource Issuer public static class Warehouse { //static byte prefixCounter; static List stores = new List(); static Dictionary resources = new Dictionary(); static uint resourceCounter = 0; static KeyList templates = new KeyList(); /// /// Get a store by its name. /// /// Store instance name /// public static IStore GetStore(string name) { foreach (var s in stores) if (s.Instance.Name == name) return s; return null; } /// /// Get a resource by instance Id. /// /// Instance Id /// public static AsyncReply Get(uint id) { if (resources.ContainsKey(id)) return new AsyncReply(resources[id]); else return null; } /// /// Open the warehouse. /// This function issues the initialize trigger to all stores and resources. /// /// True, if no problem occurred. public static AsyncReply Open() { var bag = new AsyncBag(); foreach (var store in stores) bag.Add(store.Trigger(ResourceTrigger.Initialize)); foreach (var store in stores) bag.Add(store.Trigger(ResourceTrigger.SystemInitialized)); bag.Seal(); var rt = new AsyncReply(); bag.Then((x) => { foreach(var b in x) if (!b) { rt.Trigger(false); return; } rt.Trigger(true); }); return rt; } /// /// Close the warehouse. /// This function issues terminate trigger to all resources and stores. /// /// True, if no problem occurred. public static AsyncReply Close() { var bag = new AsyncBag(); foreach (var resource in resources.Values) if (!(resource is IStore)) bag.Add(resource.Trigger(ResourceTrigger.Terminate)); foreach (var store in stores) bag.Add(store.Trigger(ResourceTrigger.Terminate)); foreach (var resource in resources.Values) if (!(resource is IStore)) bag.Add(resource.Trigger(ResourceTrigger.SystemTerminated)); foreach (var store in stores) bag.Add(store.Trigger(ResourceTrigger.SystemTerminated)); bag.Seal(); var rt = new AsyncReply(); bag.Then((x) => { foreach (var b in x) if (!b) { rt.Trigger(false); return; } rt.Trigger(true); }); return rt; } /// /// Get a resource by its path. /// Resource path is sperated by '/' character, e.g. "system/http". /// /// /// Resource instance. public static AsyncReply Get(string path) { var p = path.Split('/'); IResource res; foreach(IStore d in stores) if (p[0] == d.Instance.Name) { var i = 1; res = d; while(p.Length > i) { var si = i; foreach (IResource r in res.Instance.Children) if (r.Instance.Name == p[i]) { i++; res = r; break; } if (si == i) // not found, ask the store return d.Get(path.Substring(p[0].Length + 1)); } return new AsyncReply(res); } return new AsyncReply(null); } /// /// Put a resource in the warehouse. /// /// Resource instance. /// Resource name. /// IStore that manages the resource. Can be null if the resource is a store. /// Parent resource. if not presented the store becomes the parent for the resource. public static void Put(IResource resource, string name, IStore store = null, IResource parent = null) { resource.Instance = new Instance(resourceCounter++, name, resource, store); if (store == parent) parent = null; if (parent == null) { if (!(resource is IStore)) store.Instance.Children.Add(resource); } else parent.Instance.Children.Add(resource); if (resource is IStore) stores.Add(resource as IStore); else store.Put(resource); resources.Add(resource.Instance.Id, resource); } public static T New(string name, IStore store = null, IResource parent = null) { var res = Activator.CreateInstance(typeof(T)) as IResource; Put(res, name, store, parent); return (T)res; } /// /// Put a resource template in the templates warehouse. /// /// Resource template. public static void PutTemplate(ResourceTemplate template) { if (templates.ContainsKey(template.ClassId)) templates.Add(template.ClassId, template); } /// /// Get a template by type from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse. /// /// .Net type. /// Resource template. public static ResourceTemplate GetTemplate(Type type) { // loaded ? foreach (var t in templates.Values) if (t.ClassName == type.FullName) return t; var template = new ResourceTemplate(type); templates.Add(template.ClassId, template); return template; } /// /// Get a template by class Id from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse. /// /// Class Id. /// Resource template. public static AsyncReply GetTemplate(Guid classId) { if (templates.ContainsKey(classId)) return new AsyncReply(templates[classId]); return null; } /// /// Get a template by class name from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse. /// /// Class name. /// Resource template. public static AsyncReply GetTemplate(string className) { foreach (var t in templates.Values) if (t.ClassName == className) return new AsyncReply(t); return null; } } }