using System; using System.Collections.Generic; using System.Collections.ObjectModel; using JD.Kernel.StaticHelpers; using JD.Kernel.Structs; using JD.TeaBoxAddinSystem.Addins.Description; using JD.TeaBoxAddinSystem.Addins.Description.Conditions; using JD.TeaBoxAddinSystem.Addins.Internal; namespace JD.TeaBoxAddinSystem.Addins { /// /// An addin is a plugin that adds or extends some functionality. It can also define extension points for other addins. /// public sealed class Addin { #region Inner Types private class ExtensionTypeSetCollection : AddinObjectKeyedCollection { #region Constructor internal ExtensionTypeSetCollection(Module owner) : base(owner) { } #endregion #region Methods /// /// Overriden. /// /// /// protected override string GetKeyForItem(ExtensionTypeSet item) { if (item == null) { throw new ArgumentNullException("item"); } System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(item.Name)); return item.Name; } #endregion } private class ModuleCollection : Collection { #region Variables private readonly Addin m_addin; #endregion #region Constructor public ModuleCollection(Addin addin) { m_addin = addin; } #endregion #region Methods protected override void InsertItem(int index, Module item) { m_addin.ThrowIfLoaded(); base.InsertItem(index, item); item.SetAddin(m_addin); } protected override void SetItem(int index, Module item) { m_addin.ThrowIfLoaded(); this[index].SetAddin(null); base.SetItem(index, item); item.SetAddin(m_addin); } protected override void RemoveItem(int index) { m_addin.ThrowIfLoaded(); this[index].SetAddin(null); base.RemoveItem(index); } protected override void ClearItems() { m_addin.ThrowIfLoaded(); foreach (Module module in this) { module.SetAddin(null); } base.ClearItems(); } #endregion } #endregion #region Variables private readonly AddinManifest m_manifest; private readonly Module m_mainModule = new Module(); private readonly ModuleCollection m_modules; private readonly ExtensionPointCollection m_extensionPoints; private readonly ExtensionTypeSetCollection m_extensionTypeSets; private readonly NodeTypeCollection m_conditionTypes; private FileLocation? m_fileLocation; private readonly List m_partialAddinFilenames = new List(); #endregion #region Constructor /// /// Constructor. /// public Addin() : this(null) { } /// /// Constructor. /// /// public Addin(string id) { m_manifest = new AddinManifest(this, id); m_mainModule.SetAddin(this); m_modules = new ModuleCollection(this); m_extensionPoints = new ExtensionPointCollection(MainModule); m_extensionTypeSets = new ExtensionTypeSetCollection(MainModule); m_conditionTypes = new NodeTypeCollection(MainModule); } #endregion #region Properties /// /// Full id of the addin. /// public string FullId { get { return Manifest.FullId; } } /// /// Returns whether this addin is laoded. /// public bool IsLoaded { get { return AddinManager.IsAddinLoaded(this); } } /// /// Manifest of this addin. /// public AddinManifest Manifest { get { return m_manifest; } } /// /// Main module. /// public Module MainModule { get { return m_mainModule; } } /// /// All modules, including the main module. /// public IEnumerable AllModules { get { yield return MainModule; foreach (Module module in Modules) { yield return module; } } } /// /// Optional modules of this addin. /// public IList Modules { get { return m_modules; } } /// /// s defined in this addin. /// public KeyedCollection ExtensionPoints { get { return m_extensionPoints; } } /// /// The s defined in this addin. /// public KeyedCollection ExtensionTypeSets { get { return m_extensionTypeSets; } } /// /// The s defined in this addin. /// public KeyedCollection ConditionTypes { get { return m_conditionTypes; } } /// /// File Location of the addin. /// public FileLocation? FileLocation { get { return m_fileLocation; } set { ThrowIfLoaded(); m_fileLocation = value; } } /// /// Filenames of the partial addins that contributed to this addin. /// public IList PartialAddinFilenames { get { return m_partialAddinFilenames.AsReadOnly(); } } #endregion #region Methods internal void AddPartialAddinFilename(string filename) { m_partialAddinFilenames.Add(filename); } internal void ThrowIfLoaded() { Throw.InvalidOperationIf(IsLoaded, "Cannot modify an addin while it is loaded."); } /// /// Overriden. /// /// public override string ToString() { return $"[{Manifest.FullId}{(IsLoaded ? string.Empty : " (not loaded)")}: {Modules.Count} optional modules, {ExtensionPoints.Count} extension points, {ExtensionTypeSets.Count} extension type sets]"; } #endregion } }