using System;
using System.Collections.Generic;
using JD.Kernel.Classes;
using JD.Kernel.Structs;
using JD.LogService;
using JD.TeaBoxAddinSystem.Addins.Attributes;
using JD.TeaBoxAddinSystem.Addins.Description;
namespace JD.TeaBoxAddinSystem.Addins.Internal
{
///
/// A generic node.
///
public abstract class Node
{
#region Inner Types
private class DeserializationLoggingContext : LoggingContext
{
protected override void OnEventLogged(ItemEventArgs e)
{
AddinManager.Log(e.Item);
base.OnEventLogged(e);
}
}
#endregion
#region Constants
#if DEBUG
private static Dictionary m_standardAttributes = new Dictionary();
#endif
#endregion
#region Variables
// Set through Initialize
private Module m_module;
private NodeType m_type;
#endregion
#region Constructor
static Node()
{
#if DEBUG
m_standardAttributes.Add("id", null);
m_standardAttributes.Add("insertbefore", null);
m_standardAttributes.Add("insertafter", null);
#endif
}
///
/// Internal constructor to forbid inheritance by other assemblies.
///
internal Node()
{
}
#endregion
#region Properties
///
/// Gets the file location of the extension node.
///
///
public virtual FileLocation FileLocation
{
get
{
return m_module.FileLocation.GetValueOrDefault();
}
}
///
/// Addin of this node.
///
public Addin Addin
{
get
{
return m_module.Addin;
}
}
///
/// Module of this node.
///
public Module Module
{
get
{
return m_module;
}
}
///
/// Type of this node.
///
public NodeType Type
{
get
{
return m_type;
}
}
#endregion
#region Methods
///
/// Reads the node from a .
///
///
/// Consider using s to deserialize automatically.
///
/// Context to deserialize from.
protected virtual void Read(DeserializationContext context)
{
}
///
/// Watch out, do not call this method! Use Initialize of derived class.
///
///
///
///
///
internal bool Initialize(Module module, NodeDescription description, NodeType type)
{
System.Diagnostics.Debug.Assert(module != null);
m_module = module;
m_type = type;
if (description != null)
{
try
{
if (!ReadDefault(description))
{
return false;
}
LoggingContext loggingContext = new DeserializationLoggingContext();
Read(new DeserializationContext(description, loggingContext));
if (loggingContext.Errors.Count > 0)
{
return false;
}
}
catch (Exception e)
{
description.LogError("Unexpected error while deserializing node of type {0}: {1}", GetType().FullName, e.Message);
return false;
}
}
return true;
}
private bool ReadDefault(NodeDescription description)
{
System.Diagnostics.Debug.Assert(description != null);
System.Diagnostics.Debug.Assert(Type != null);
System.Diagnostics.Debug.Assert(Type.Type != null);
System.Diagnostics.Debug.Assert(Type.Descriptors != null);
StringPropertyConverter deserializer = new StringPropertyConverter();
deserializer.ErrorLogger = delegate(string errorMsg)
{
description.LogError(errorMsg);
};
#if DEBUG
deserializer.SuperfluousPropertiesProduceErrors = true;
deserializer.SuperfluousPropertyLogger = delegate(string property)
{
if (!m_standardAttributes.ContainsKey(property.ToLowerInvariant()))
{
AddinManager.Log(new Error(LogCategory.Warning, "Attribute '{0}' is an unknown attribute for extension node '{1}'", property, Type));
}
};
#endif
deserializer.CustomConverter = delegate(System.Type targetType, string value, out object convertedValue)
{
object[] attributes = targetType.GetCustomAttributes(typeof(AddinConverterAttribute), true);
if (attributes.Length > 0)
{
convertedValue = ((AddinConverterAttribute)attributes[0]).Convert(targetType, value, this);
return true;
}
convertedValue = null;
return false;
};
return deserializer.Deserialize(this, Type.Descriptors, description.Attributes);
}
internal static T CreateNode(string nodeTypeName, NodeType type) where T : Node
{
System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(nodeTypeName));
System.Diagnostics.Debug.Assert(type != null);
Type nodeType = type.Type;
if (nodeType == null)
{
// Something went wrong
return null;
}
T node = null;
try
{
node = Activator.CreateInstance(nodeType) as T;
}
catch (System.MissingMethodException)
{
type.LogError("Cannot create {0} node of type {1} because it doesn't have a parameterless public constructor", nodeTypeName, nodeType.FullName);
return null;
}
catch (System.Reflection.TargetInvocationException e)
{
type.LogError("Unexpected exception thrown while creating {0} node of type {1}: {2}", nodeTypeName, nodeType.FullName, e.InnerException.Message);
return null;
}
catch (Exception e)
{
type.LogError("Unexpected error while creating {0} node of type {0}: {1}", nodeTypeName, nodeType.FullName, e.Message);
return null;
}
if (node == null)
{
string correctName = nodeTypeName.ToUpper()[0] + nodeTypeName.Substring(1);
type.LogError("{0} node type {1} must be a subclass of {2}", correctName, nodeType.FullName, typeof(T).Name);
return null;
}
return node;
}
#endregion
}
}