ln.manage/ManagedObjectProvider.cs

204 lines
8.0 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Security.Cryptography;
using System.Reflection;
using ln.types.btree;
using ln.json;
using ln.logging;
using ln.json.mapping;
namespace ln.manage
{
public abstract class ManagedObjectProvider
{
public Type ManagedType { get; }
ManagedObjectProvider container;
public ManagedObjectProvider Container {
get => container;
set {
if (Object.Equals(container, this))
throw new ArgumentOutOfRangeException(nameof(value));
container?.RemoveChildProvider(this);
container = value;
container?.AddChildProvider(this);
if (!Object.ReferenceEquals(null,container))
{
List<string> path = new List<string>();
fillpath(path);
pathlist = PathList.ToArray();
}
else
{
pathlist = new string[0];
}
}
}
public string Name { get; private set; }
public string[] pathlist = new string[0];
public string[] PathList => (string[])pathlist.Clone();
public string Path => String.Join("/", PathList);
protected MappingBTree<string, ManagedObjectPropertyDescriptor> propertyDescriptors = new MappingBTree<string, ManagedObjectPropertyDescriptor>((mopd)=>mopd.PropertyName);
public virtual IEnumerable<ManagedObjectPropertyDescriptor> PropertyDescriptors => propertyDescriptors.Values;
public String UniqueIdentifierPropertyName { get; protected set; }
Dictionary<string, ManagedObjectProvider> children = new Dictionary<string,ManagedObjectProvider>();
public IEnumerable<ManagedObjectProvider> Children => children.Values;
public ManagedObjectProvider(Type type): this(type, type.Name, null) { }
public ManagedObjectProvider(Type type, String name) : this(type, name, null) { }
public ManagedObjectProvider(Type type, String name, ManagedObjectProvider container) : this(true, type, name, container) { }
protected ManagedObjectProvider(bool buildPropertyDescriptors,Type type,String name,ManagedObjectProvider container)
{
ManagedType = type;
Name = name;
Container = container;
if (buildPropertyDescriptors)
BuildPropertyDescriptors();
}
private void AddChildProvider(ManagedObjectProvider childProvider)
{
children.Add(childProvider.Name, childProvider);
childProvider.container = this;
}
private void RemoveChildProvider(ManagedObjectProvider childProvider)
{
if (children.TryGetValue(childProvider.Name, out ManagedObjectProvider child) && Object.Equals(child, childProvider))
{
children.Remove(childProvider.Name);
childProvider.container = null;
}
else
throw new KeyNotFoundException();
}
protected virtual void CollectObjects(ISet<Tuple<ManagedObjectProvider, object>> set) { CollectLocalObjects(set); CollectChildObjects(set); }
protected virtual void CollectChildObjects(ISet<Tuple<ManagedObjectProvider, object>> set)
{
foreach (ManagedObjectProvider childProvider in Children)
{
if (childProvider.ManagedType.IsSubclassOf(ManagedType))
{
foreach (Tuple<ManagedObjectProvider, object> childObject in childProvider.EnumerateProviderItems())
set.Add(childObject);
}
}
}
protected virtual void CollectLocalObjects(ISet<Tuple<ManagedObjectProvider, object>> set) { }
public virtual IEnumerable<object> EnumerateItems() => EnumerateProviderItems().Select((arg) => arg.Item2);
public virtual IEnumerable<Tuple<ManagedObjectProvider,object>> EnumerateProviderItems()
{
HashSet<Tuple<ManagedObjectProvider, object>> childObjects = new HashSet<Tuple<ManagedObjectProvider, object>>();
CollectObjects(childObjects);
return childObjects;
}
public abstract object GetManagedObject(object uniqueIdentifier);
public abstract ManagedObjectState GetManagedObjectState(object o);
public virtual object CreateManagedObject(IEnumerable<KeyValuePair<string, object>> properties) => throw new NotSupportedException();
public virtual object CreateManagedObject() => CreateManagedObject(null);
public virtual void ChangeObject(object o, IEnumerable<KeyValuePair<string, object>> properties)
{
try
{
foreach (KeyValuePair<string, object> property in properties)
propertyDescriptors[property.Key].SetValue(o, property.Value);
}
catch (Exception e)
{
Logging.Log(e);
throw e;
}
}
public abstract void RemoveObject(object o);
public abstract void Enable(object o);
public abstract void Disable(object o);
private void fillpath(List<string> path)
{
if (Container != null)
Container.fillpath(path);
path.Add(Name);
}
protected void BuildPropertyDescriptors()
{
if (ManagedType == null)
return;
foreach (FieldInfo fieldInfo in ManagedType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
if (fieldInfo.IsPublic || fieldInfo.GetCustomAttribute<ManagedPropertyAttribute>() != null)
{
propertyDescriptors.Add(new ManagedObjectPropertyDescriptor(this, fieldInfo));
}
}
foreach (PropertyInfo propertyInfo in ManagedType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
if (propertyInfo.GetMethod.IsPublic || propertyInfo.GetCustomAttribute<ManagedPropertyAttribute>() != null)
{
propertyDescriptors.Add(new ManagedObjectPropertyDescriptor(this, propertyInfo));
}
}
}
public virtual JSONObject CreateJsonDescriptor()
{
JSONObject descriptor = new JSONObject();
descriptor["name"] = Name;
descriptor["readonly"] = false;
descriptor["cosmetic"] = false;
descriptor["hint"] = "";
descriptor["key"] = UniqueIdentifierPropertyName;
JSONObject jproperties = new JSONObject();
foreach (ManagedObjectPropertyDescriptor propertyDescriptor in PropertyDescriptors)
jproperties[propertyDescriptor.PropertyName] = propertyDescriptor.CreateJsonDescriptor();
descriptor["properties"] = jproperties;
JSONObject jchildren = new JSONObject();
foreach (ManagedObjectProvider managedObjectProvider in Children)
jchildren[managedObjectProvider.Name] = managedObjectProvider.CreateJsonDescriptor();
descriptor["children"] = jchildren;
return descriptor;
}
public virtual JSONObject CreateJsonObject(object o)
{
if (!ManagedType.Equals(o.GetType()) && !ManagedType.IsSubclassOf(o.GetType()))
throw new ArgumentException();
JSONObject jObject = new JSONObject();
jObject["provider"] = this.Path;
//jObject["state"] = GetManagedObjectState(o);
JSONObject jProperties = new JSONObject();
foreach (ManagedObjectPropertyDescriptor descriptor in PropertyDescriptors)
jProperties[descriptor.PropertyName] = JSONMapper.DefaultMapper.ToJson(descriptor.GetValue(o));
jObject["properties"] = jProperties;
return jObject;
}
}
}