// // // // // $Revision: 3287 $ // using System; using System.Collections; using System.Collections.Generic; namespace ICSharpCode.Core { /// /// Represents an extension path in the . /// public sealed class AddInTreeNode { Dictionary childNodes = new Dictionary(); List codons = new List(); bool isSorted = false; /// /// A dictionary containing the child paths. /// public Dictionary ChildNodes { get { return childNodes; } } /// /// A list of child s. /// public List Codons { get { return codons; } } // // public void BinarySerialize(BinaryWriter writer) // { // if (!isSorted) { // (new SortCodons(this)).Execute(); // isSorted = true; // } // writer.Write((ushort)codons.Count); // foreach (Codon codon in codons) { // codon.BinarySerialize(writer); // } // // writer.Write((ushort)childNodes.Count); // foreach (KeyValuePair child in childNodes) { // writer.Write(AddInTree.GetNameOffset(child.Key)); // child.Value.BinarySerialize(writer); // } // } /// /// Supports sorting codons using InsertBefore/InsertAfter /// sealed class TopologicalSort { List codons; bool[] visited; List sortedCodons; Dictionary indexOfName; public TopologicalSort(List codons) { this.codons = codons; visited = new bool[codons.Count]; sortedCodons = new List(codons.Count); indexOfName = new Dictionary(codons.Count); // initialize visited to false and fill the indexOfName dictionary for (int i = 0; i < codons.Count; ++i) { visited[i] = false; indexOfName[codons[i].Id] = i; } } void InsertEdges() { // add the InsertBefore to the corresponding InsertAfter for (int i = 0; i < codons.Count; ++i) { string before = codons[i].InsertBefore; if (before != null && before != "") { if (indexOfName.ContainsKey(before)) { string after = codons[indexOfName[before]].InsertAfter; if (after == null || after == "") { codons[indexOfName[before]].InsertAfter = codons[i].Id; } else { codons[indexOfName[before]].InsertAfter = after + ',' + codons[i].Id; } } else { LoggingService.WarnFormatted("Codon ({0}) specified in the insertbefore of the {1} codon does not exist!", before, codons[i]); } } } } public List Execute() { InsertEdges(); // Visit all codons for (int i = 0; i < codons.Count; ++i) { Visit(i); } return sortedCodons; } void Visit(int codonIndex) { if (visited[codonIndex]) { return; } string[] after = codons[codonIndex].InsertAfter.Split(new char[] {','}); foreach (string s in after) { if (s == null || s.Length == 0) { continue; } if (indexOfName.ContainsKey(s)) { Visit(indexOfName[s]); } else { LoggingService.WarnFormatted("Codon ({0}) specified in the insertafter of the {1} codon does not exist!", codons[codonIndex].InsertAfter, codons[codonIndex]); } } sortedCodons.Add(codons[codonIndex]); visited[codonIndex] = true; } } /// /// Builds the child items in this path. Ensures that all items have the type T. /// /// The owner used to create the objects. public List BuildChildItems(object caller) { List items = new List(codons.Count); if (!isSorted) { codons = (new TopologicalSort(codons)).Execute(); isSorted = true; } foreach (Codon codon in codons) { ArrayList subItems = null; if (childNodes.ContainsKey(codon.Id)) { subItems = childNodes[codon.Id].BuildChildItems(caller); } object result = codon.BuildItem(caller, subItems); if (result == null) continue; IBuildItemsModifier mod = result as IBuildItemsModifier; if (mod != null) { mod.Apply(items); } else if (result is T) { items.Add((T)result); } else { throw new InvalidCastException("The AddInTreeNode <" + codon.Name + " id='" + codon.Id + "' returned an instance of " + result.GetType().FullName + " but the type " + typeof(T).FullName + " is expected."); } } return items; } /// /// Builds the child items in this path. /// /// The owner used to create the objects. public ArrayList BuildChildItems(object caller) { ArrayList items = new ArrayList(codons.Count); if (!isSorted) { codons = (new TopologicalSort(codons)).Execute(); isSorted = true; } foreach (Codon codon in codons) { ArrayList subItems = null; if (childNodes.ContainsKey(codon.Id)) { subItems = childNodes[codon.Id].BuildChildItems(caller); } object result = codon.BuildItem(caller, subItems); if (result == null) continue; IBuildItemsModifier mod = result as IBuildItemsModifier; if (mod != null) { mod.Apply(items); } else { items.Add(result); } } return items; } /// /// Builds a specific child items in this path. /// /// /// The ID of the child item to build. /// /// The owner used to create the objects. /// The subitems to pass to the doozer /// /// Occurs when does not exist in this path. /// public object BuildChildItem(string childItemID, object caller, ArrayList subItems) { foreach (Codon codon in codons) { if (codon.Id == childItemID) { return codon.BuildItem(caller, subItems); } } throw new TreePathNotFoundException(childItemID); } } }