using System;
using System.Collections.Generic;
using JD.Collections.Extensions;
using JD.Collections.Interfaces;
using JD.Kernel.Structs;
using JD.TeaBoxAddinSystem.Addins.Description;
using JD.TeaBoxAddinSystem.Addins.Description.Conditions;
using JD.TeaBoxAddinSystem.Addins.Internal;
namespace JD.TeaBoxAddinSystem.Addins
{
///
/// Extension Nodes are the objects that are created and placed in the extension tree.
///
public class ExtensionNode : Node
{
#region Inner Types
private class ExtensionNodeCollection : System.Collections.ObjectModel.ReadOnlyCollection, IKeyedList
{
#region Constructor
internal ExtensionNodeCollection(IList list)
: base(list)
{
}
#endregion
#region Properties
public ExtensionNode this[string key]
{
get
{
foreach (ExtensionNode node in this)
{
if (node.Id == key)
{
return node;
}
}
return null;
}
}
#endregion
#region Methods
public bool ContainsKey(string key)
{
return (this[key] != null);
}
public bool Remove(string key)
{
throw new NotSupportedException();
}
public bool TryGetValue(string key, out ExtensionNode value)
{
value = this[key];
return value != null;
}
#endregion
}
#endregion
#region Variables
private object m_cachedInstance;
// Set through Initialize
private TreeNode m_node;
// Lazy-constructed
private List m_childNodes;
private object m_lock = new object();
#endregion
#region Properties
///
/// Gets the file location of the extension node.
///
///
public override sealed FileLocation FileLocation
{
get
{
if (m_node != null)
{
return m_node.ExtensionNodeDescription.FileLocation.GetValueOrDefault();
}
return FileLocation.Empty;
}
}
///
/// Type of this extension node.
///
public new ExtensionType Type
{
get
{
return (ExtensionType)base.Type;
}
}
///
/// Id of the extension node.
///
public string Id
{
get
{
return m_node.Id;
}
}
///
/// Gets whether the of this was defined by the user or automatically generated.
///
public bool HasIdDefined
{
get
{
return m_node.HasIdDefined;
}
}
///
/// Full path of the extension node.
///
public string FullPath
{
get
{
return m_node.FullPath;
}
}
///
/// Child nodes of this extension node.
///
public IKeyedList ChildNodes
{
get
{
if (m_childNodes == null)
{
lock (m_lock)
{
if (m_childNodes == null)
{
List nodes = new List(m_node.ChildNodes.Count);
foreach (TreeNode childNode in m_node.ChildNodes)
{
ExtensionNode childExtensionNode = childNode.ExtensionNode;
if (childExtensionNode != null)
{
nodes.Add(childExtensionNode);
}
}
m_childNodes = nodes;
}
}
}
System.Diagnostics.Debug.Assert(m_childNodes != null);
return new ExtensionNodeCollection(m_childNodes);
}
}
///
/// Extension Object of this node.
///
///
/// This method is only valid on s
///
/// The node is not a .
public virtual object ExtensionObject
{
get
{
if (m_cachedInstance == null)
{
m_cachedInstance = CreateExtensionObject();
}
return m_cachedInstance;
}
}
#endregion
#region Methods
///
/// Creates an extension object for this node.
///
///
/// This method is only valid on certain extension node types like .
///
///
/// This extension node doesn't support extension objects.
public virtual object CreateExtensionObject()
{
throw new InvalidOperationException("ExtensionObjects are only available on TypeExtensionNodes");
}
///
/// Gets a collection of extension objects contained in this extension node.
///
///
/// All objects created by child nodes MUST be of type .
///
///
///
public IList GetExtensionObjects()
{
return ChildNodes.Project(node => (T)node.ExtensionObject);
}
internal T GetExtensionObject()
{
return (T)ExtensionObject;
}
///
/// Called by a when its collection of child nodes is modified.
///
internal void NotifyChildNodesChanged(ExtensionNodeChangedEventArgs e)
{
// This will trigger a recreation of the nodes on demand.
m_childNodes = null;
OnChanged(e);
}
internal bool Initialize(TreeNode node, Module module, ExtensionNodeDescription description, ExtensionType type)
{
System.Diagnostics.Debug.Assert(node != null);
m_node = node;
if (!base.Initialize(module, description, type))
{
return false;
}
// Validate conditional targets
if (description != null) // Description can be null in case of extension point's fake extension nodes.
{
foreach (ConditionInfo conditionInfo in description.Conditions)
{
if (!string.IsNullOrEmpty(conditionInfo.Target) && !type.ConditionAttributes.Contains(conditionInfo.Target))
{
description.LogWarning("Cannot apply condition {0} on target {1} of node {2} because it is not supported on extension nodes of type {3}",
conditionInfo.Condition,
conditionInfo.Target,
description.DisplayId,
type.Name);
}
}
}
return true;
}
#endregion
#region Events
///
/// Triggered when this extension node changes.
///
public event EventHandler Changed
{
add
{
AddinManager.SessionService.AddExtensionChangedHandler(FullPath, value);
}
remove
{
AddinManager.SessionService.RemoveExtensionChangedHandler(FullPath, value);
}
}
///
/// Triggers a event.
///
/// Event Args.
protected virtual void OnChanged(ExtensionNodeChangedEventArgs e)
{
AddinManager.SessionService.ChangedHandlerManager.OnChanged(e);
}
#endregion
}
}