//
//
//
//
// $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);
}
}
}