using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Reflection; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.Serialization; using System.Xml.Serialization; using System.Security.Permissions; [assembly: SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", Scope = "member", Target = "Common.NodeTree`1+EnumeratorBase`1.Count", MessageId = "o")] [assembly: SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair+BaseNodesEnumerableCollection.Count", MessageId = "o")] [assembly: SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.GetNodeTree(Common.INode`1):Common.NodeTree`1")] [assembly: SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.GetNodeTree(Common.ITree`1):Common.NodeTree`1")] [assembly: SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.NewTree():Common.ITree`1")] [assembly: SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.NewNode():Common.INode`1")] [assembly: SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.XmlAdapterTag")] [assembly: SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.XmlDeserialize(System.IO.Stream):Common.ITree`1")] [assembly: SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.IEnumerableCollectionPair`1.Nodes")] [assembly: SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.NodeTree`1.Nodes")] [assembly: SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.NodeTree`1+AllEnumerator.Nodes")] [assembly: SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair.Nodes")] [assembly: SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair+BaseNodesEnumerableCollection.GetEnumerator():System.Collections.Generic.IEnumerator`1>")] [assembly: SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+AllEnumerator")] [assembly: SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair")] [assembly: SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+RootObject")] [assembly: SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+NodeXmlSerializationAdapter")] [assembly: SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+NodeXmlSerializationAdapter+IXmlCollection")] [assembly: SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+TreeXmlSerializationAdapter")] [assembly: SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "Common.NodeTree`1.Dispose():System.Void")] [assembly: SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "Common.NodeTree`1.Finalize():System.Void")] [assembly: SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair+BaseNodesEnumerableCollection.Dispose():System.Void")] [assembly: SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair+BaseNodesEnumerableCollection.Finalize():System.Void")] [assembly: SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Common.NodeTree`1.XmlAdapterTag")] [assembly: SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Scope = "member", Target = "Common.NodeTree`1+NodeXmlSerializationAdapter.Children")] namespace Common { //----------------------------------------------------------------------------- // IDeepCopy public interface IDeepCopy { object CreateDeepCopy(); } //----------------------------------------------------------------------------- // IEnumerableCollection public interface IEnumerableCollection : IEnumerable, ICollection { bool Contains(T item); } //----------------------------------------------------------------------------- // IEnumerableCollectionPair public interface IEnumerableCollectionPair { IEnumerableCollection> Nodes { get; } IEnumerableCollection Values { get; } INode Find(T item); INode Find(Predicate predicate); } //----------------------------------------------------------------------------- // EventArgs public class NodeTreeDataEventArgs : EventArgs { private T _Data = default(T); public T Data { get { return _Data; } } public NodeTreeDataEventArgs(T data) { _Data = data; } } public class NodeTreeNodeEventArgs : EventArgs { private INode _Node = null; public INode Node { get { return _Node; } } public NodeTreeNodeEventArgs(INode node) { _Node = node; } } public enum NodeTreeInsertOperation { Previous, Next, Child, Tree } public class NodeTreeInsertEventArgs : EventArgs { private NodeTreeInsertOperation _Operation; public NodeTreeInsertOperation Operation { get { return _Operation; } } private INode _Node = null; public INode Node { get { return _Node; } } public NodeTreeInsertEventArgs(NodeTreeInsertOperation operation, INode node) { _Operation = operation; _Node = node; } } //----------------------------------------------------------------------------- // INode /// /// Uwe Keim start. /// public delegate string ToStringRecursiveAction(T obj); /// /// Uwe Keim end. /// public interface INode : IEnumerableCollectionPair, IDisposable//, ICollection { T Data { get; set; } string ToStringRecursive(); /// /// Uwe Keim start. /// string ToStringRecursive(ToStringRecursiveAction> action); /// /// Uwe Keim end. /// int Depth { get; } int BranchIndex { get; } int BranchCount { get; } int Count { get; } int DirectChildCount { get; } INode Parent { get; } INode Previous { get; } INode Next { get; } INode Child { get; } ITree Tree { get; } INode Root { get; } INode Top { get; } INode First { get; } INode Last { get; } INode LastChild { get; } bool IsTree { get; } bool IsRoot { get; } bool IsTop { get; } bool HasParent { get; } bool HasPrevious { get; } bool HasNext { get; } bool HasChild { get; } bool IsFirst { get; } bool IsLast { get; } INode this[T item] { get; } bool Contains(INode item); bool Contains(T item); INode InsertPrevious(T o); INode InsertNext(T o); INode InsertChild(T o); INode Add(T o); INode AddChild(T o); void InsertPrevious(ITree tree); void InsertNext(ITree tree); void InsertChild(ITree tree); void Add(ITree tree); void AddChild(ITree tree); ITree Cut(T o); ITree Copy(T o); ITree DeepCopy(T o); bool Remove(T o); ITree Cut(); ITree Copy(); ITree DeepCopy(); void Remove(); bool CanMoveToParent { get; } bool CanMoveToPrevious { get; } bool CanMoveToNext { get; } bool CanMoveToChild { get; } bool CanMoveToFirst { get; } bool CanMoveToLast { get; } void MoveToParent(); void MoveToPrevious(); void MoveToNext(); void MoveToChild(); void MoveToFirst(); void MoveToLast(); IEnumerableCollectionPair All { get; } IEnumerableCollectionPair AllChildren { get; } IEnumerableCollectionPair DirectChildren { get; } IEnumerableCollectionPair DirectChildrenInReverse { get; } void SortAllChildren(); void SortAllChildren(Comparison comparison); void SortAllChildren(IComparer comparer); void SortDirectChildren(); void SortDirectChildren(Comparison comparison); void SortDirectChildren(IComparer comparer); event EventHandler> Validate; event EventHandler> Setting; event EventHandler> SetDone; event EventHandler> Inserting; event EventHandler> Inserted; event EventHandler Cutting; event EventHandler CutDone; event EventHandler> Copying; event EventHandler> Copied; event EventHandler> DeepCopying; event EventHandler> DeepCopied; } //----------------------------------------------------------------------------- // ITree public interface ITree : IEnumerableCollectionPair, IDisposable//, ICollection { Type DataType { get; } IEqualityComparer DataComparer { get; set; } void XmlSerialize(Stream stream); void Clear(); int Count { get; } int DirectChildCount { get; } INode Root { get; } INode this[T o] { get; } string ToStringRecursive(); /// /// Uwe Keim start. /// string ToStringRecursive(ToStringRecursiveAction> action); /// /// Uwe Keim end. /// bool Contains(T item); bool Contains(INode item); INode InsertChild(T o); INode AddChild(T o); void InsertChild(ITree tree); void AddChild(ITree tree); ITree Cut(T o); ITree Copy(T o); ITree DeepCopy(T o); bool Remove(T o); ITree Copy(); ITree DeepCopy(); IEnumerableCollectionPair All { get; } IEnumerableCollectionPair AllChildren { get; } IEnumerableCollectionPair DirectChildren { get; } IEnumerableCollectionPair DirectChildrenInReverse { get; } void SortAllChildren(); void SortAllChildren(Comparison comparison); void SortAllChildren(IComparer comparer); event EventHandler> Validate; event EventHandler Clearing; event EventHandler Cleared; event EventHandler> Setting; event EventHandler> SetDone; event EventHandler> Inserting; event EventHandler> Inserted; event EventHandler Cutting; event EventHandler CutDone; event EventHandler> Copying; event EventHandler> Copied; event EventHandler> DeepCopying; event EventHandler> DeepCopied; } //----------------------------------------------------------------------------- // NodeTree [Serializable] public class NodeTree : INode, ITree, ISerializable { private T _Data = default(T); private NodeTree _Parent = null; private NodeTree _Previous = null; private NodeTree _Next = null; private NodeTree _Child = null; protected NodeTree() { } ~NodeTree() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { if (_EventHandlerList != null) _EventHandlerList.Dispose(); } } //----------------------------------------------------------------------------- // Instantiation public static ITree NewTree() { return new RootObject(); } public static ITree NewTree(IEqualityComparer dataComparer) { return new RootObject(dataComparer); } protected static INode NewNode() { return new NodeTree(); } protected virtual NodeTree CreateTree() { return new RootObject(); } protected virtual NodeTree CreateNode() { return new NodeTree(); } //----------------------------------------------------------------------------- // ToString /// Obtains the representation of this instance. /// The representation of this instance. /// ///

/// This method returns a that represents this instance. ///

///
public override string ToString() { T data = Data; if (data == null) return String.Empty; return data.ToString(); } /// /// Uwe Keim start. /// public virtual string ToStringRecursive( ToStringRecursiveAction> action) { var s = string.Empty; foreach (NodeTree node in All.Nodes) { s += action(node); } return s; } public virtual string ToStringRecursive() { return ToStringRecursive( node => new string('\t', node.Depth) + node + Environment.NewLine); } /* public virtual string ToStringRecursive() { string s = String.Empty; foreach (NodeTree node in All.Nodes) s += new String('\t', node.Depth) + node + Environment.NewLine; return s; }*/ /// /// Uwe Keim end. /// //----------------------------------------------------------------------------- // Counts public virtual int Depth { get { int i = -1; for (INode node = this; !node.IsRoot; node = node.Parent) i++; return i; } } public virtual int BranchIndex { get { int i = -1; for (INode node = this; node != null; node = node.Previous) i++; return i; } } public virtual int BranchCount { get { int i = 0; for (INode node = First; node != null; node = node.Next) i++; return i; } } //----------------------------------------------------------------------------- // DeepCopyData [ReflectionPermission(SecurityAction.Demand, Unrestricted = true)] protected virtual T DeepCopyData(T data) { //if ( ! Root.IsTree ) throw new InvalidOperationException( "This is not a tree" ); if (data == null) { Debug.Assert(true); return default(T); } // IDeepCopy IDeepCopy deepCopy = data as IDeepCopy; if (deepCopy != null) return (T)deepCopy.CreateDeepCopy(); // ICloneable ICloneable cloneable = data as ICloneable; if (cloneable != null) return (T)cloneable.Clone(); // Copy constructor ConstructorInfo ctor = data.GetType().GetConstructor( BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(T) }, null); if (ctor != null) return (T)ctor.Invoke(new object[] { data }); //return ( T ) Activator.CreateInstance( typeof( T ), new object[] { data } ); // give up return data; } //----------------------------------------------------------------------------- // RootObject [Serializable] protected class RootObject : NodeTree { private int _Version = 0; protected override int Version { get { return _Version; } set { _Version = value; } } private IEqualityComparer _DataComparer; public override IEqualityComparer DataComparer { get { if (_DataComparer == null) _DataComparer = EqualityComparer.Default; return _DataComparer; } set { _DataComparer = value; } } public RootObject() { } public RootObject(IEqualityComparer dataComparer) { _DataComparer = dataComparer; } /// Obtains the representation of this instance. /// The representation of this instance. /// ///

/// This method returns a that represents this instance. ///

///
public override string ToString() { return "ROOT: " + DataType.Name; } // Save /// Populates a SerializationInfo with the data needed to serialize the target T. /// The SerializationInfo to populate with data. /// The destination for this serialization. /// ///

This method is called during serialization.

///

Do not call this method directly.

///
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("RootObjectVersion", 1); //info.AddValue( "DataType", _DataType ); } // Load /// Initializes a new instance of the class during deserialization. /// The SerializationInfo populated with data. /// The source for this serialization. /// ///

This method is called during deserialization.

///

Do not call this method directly.

///
protected RootObject(SerializationInfo info, StreamingContext context) : base(info, context) { int iVersion = info.GetInt32("RootObjectVersion"); if (iVersion != 1) throw new SerializationException("Unknown version"); //_DataType = info.GetValue( "DataType", typeof( Type ) ) as Type; } } //----------------------------------------------------------------------------- // GetRootObject protected virtual RootObject GetRootObject { get { return (RootObject)Root; } } //----------------------------------------------------------------------------- // DataComparer public virtual IEqualityComparer DataComparer { get { if (!Root.IsTree) throw new InvalidOperationException("This is not a Tree"); return GetRootObject.DataComparer; } set { if (!Root.IsTree) throw new InvalidOperationException("This is not a Tree"); GetRootObject.DataComparer = value; } } //----------------------------------------------------------------------------- // Version protected virtual int Version { get { INode root = Root; if (!root.IsTree) throw new InvalidOperationException("This is not a Tree"); return GetNodeTree(root).Version; } set { INode root = Root; if (!root.IsTree) throw new InvalidOperationException("This is not a Tree"); GetNodeTree(root).Version = value; } } protected bool HasChanged(int version) { return (Version != version); } protected void IncrementVersion() { INode root = Root; if (!root.IsTree) throw new InvalidOperationException("This is not a Tree"); GetNodeTree(root).Version++; } //----------------------------------------------------------------------------- // ISerializable // Save /// Populates a SerializationInfo with the data needed to serialize the target T. /// The SerializationInfo to populate with data. /// The destination for this serialization. /// ///

This method is called during serialization.

///

Do not call this method directly.

///
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("NodeTreeVersion", 1); info.AddValue("Data", _Data); info.AddValue("Parent", _Parent); info.AddValue("Previous", _Previous); info.AddValue("Next", _Next); info.AddValue("Child", _Child); } // Load /// Initializes a new instance of the class during deserialization. /// The SerializationInfo populated with data. /// The source for this serialization. /// ///

This method is called during deserialization.

///

Do not call this method directly.

///
protected NodeTree(SerializationInfo info, StreamingContext context) { int iVersion = info.GetInt32("NodeTreeVersion"); if (iVersion != 1) throw new SerializationException("Unknown version"); _Data = (T)info.GetValue("Data", typeof(T)); _Parent = (NodeTree)info.GetValue("Parent", typeof(NodeTree)); _Previous = (NodeTree)info.GetValue("Previous", typeof(NodeTree)); _Next = (NodeTree)info.GetValue("Next", typeof(NodeTree)); _Child = (NodeTree)info.GetValue("Child", typeof(NodeTree)); } //----------------------------------------------------------------------------- // XmlSerialization public virtual void XmlSerialize(Stream stream) { XmlSerializer xmlSerializer; try { xmlSerializer = new XmlSerializer(typeof(TreeXmlSerializationAdapter)); } catch (Exception x) { Debug.Assert(x == null); // false throw; } try { xmlSerializer.Serialize(stream, new TreeXmlSerializationAdapter(XmlAdapterTag, this)); } catch (Exception x) { Debug.Assert(x == null); // false throw; } } public static ITree XmlDeserialize(Stream stream) { XmlSerializer xmlSerializer; try { xmlSerializer = new XmlSerializer(typeof(TreeXmlSerializationAdapter)); } catch (Exception x) { Debug.Assert(x == null); // false throw; } object o; try { o = xmlSerializer.Deserialize(stream); } catch (Exception x) { Debug.Assert(x == null); // false throw; } TreeXmlSerializationAdapter adapter = (TreeXmlSerializationAdapter)o; ITree tree = adapter.Tree; return tree; } //----------------------------------------------------------------------------- protected static readonly object XmlAdapterTag = new object(); [XmlType("Tree")] public class TreeXmlSerializationAdapter { private int _Version = 0; [XmlAttribute] public int Version { get { return 1; } set { _Version = value; } } private ITree _Tree; [XmlIgnore] public ITree Tree { get { return _Tree; } } private TreeXmlSerializationAdapter() { } public TreeXmlSerializationAdapter(object tag, ITree tree) { if (!ReferenceEquals(XmlAdapterTag, tag)) throw new InvalidOperationException("Don't use this class"); _Tree = tree; } public NodeXmlSerializationAdapter Root { get { return new NodeXmlSerializationAdapter(XmlAdapterTag, _Tree.Root); } set { _Tree = NodeTree.NewTree(); ReformTree(_Tree.Root, value); } } private void ReformTree(INode parent, NodeXmlSerializationAdapter node) { foreach (NodeXmlSerializationAdapter child in node.Children) { INode n = parent.AddChild(child.Data); ReformTree(n, child); } } } [XmlType("Node")] public class NodeXmlSerializationAdapter { private int _Version = 0; [XmlAttribute] public int Version { get { return 1; } set { _Version = value; } } private INode _Node; private IXmlCollection _Children = new ChildCollection(); [XmlIgnore] public INode Node { get { return _Node; } } // Load private NodeXmlSerializationAdapter() { _Node = NodeTree.NewNode(); } // Save public NodeXmlSerializationAdapter(object tag, INode node) { if (!ReferenceEquals(XmlAdapterTag, tag)) throw new InvalidOperationException("Don't use this class"); _Node = node; foreach (INode child in node.DirectChildren.Nodes) _Children.Add(new NodeXmlSerializationAdapter(XmlAdapterTag, child)); } public T Data { get { return _Node.Data; } set { GetNodeTree(_Node)._Data = value; } } public IXmlCollection Children { get { return _Children; } set { Debug.Assert(value == null); } } public interface IXmlCollection : ICollection { NodeXmlSerializationAdapter this[int index] { get; } void Add(NodeXmlSerializationAdapter item); } private class ChildCollection : List, IXmlCollection { } } //----------------------------------------------------------------------------- // INode public T Data { get { return _Data; } set { if (IsRoot) throw new InvalidOperationException("This is a Root"); OnSetting(this, value); _Data = value; OnSetDone(this, value); } } public INode Parent { get { return _Parent; } } public INode Previous { get { return _Previous; } } public INode Next { get { return _Next; } } public INode Child { get { return _Child; } } //----------------------------------------------------------------------------- public ITree Tree { get { return (ITree)Root; } } public INode Root { get { INode node = this; while (node.Parent != null) node = node.Parent; return node; } } public INode Top { get { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); //if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" ); if (this.IsRoot) return null; INode node = this; while (node.Parent.Parent != null) node = node.Parent; return node; } } public INode First { get { INode node = this; while (node.Previous != null) node = node.Previous; return node; } } public INode Last { get { INode node = this; while (node.Next != null) node = node.Next; return node; } } public INode LastChild { get { if (Child == null) return null; return Child.Last; } } //----------------------------------------------------------------------------- public bool HasPrevious { get { return Previous != null; } } public bool HasNext { get { return Next != null; } } public bool HasChild { get { return Child != null; } } public bool IsFirst { get { return Previous == null; } } public bool IsLast { get { return Next == null; } } public bool IsTree { get { if (!IsRoot) return false; return this is RootObject; } } public bool IsRoot { get { bool b = (Parent == null); if (b) { Debug.Assert(Previous == null); Debug.Assert(Next == null); } return b; } } public bool HasParent { get { //if ( IsRoot ) throw new InvalidOperationException( "This is a Root" ); if (IsRoot) return false; return Parent.Parent != null; } } public bool IsTop { get { //if ( IsRoot ) throw new InvalidOperationException( "This is a Root" ); if (IsRoot) return false; return Parent.Parent == null; } } //----------------------------------------------------------------------------- public virtual INode this[T item] { get { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); IEqualityComparer comparer = DataComparer; foreach (INode n in All.Nodes) if (comparer.Equals(n.Data, item)) return n; return null; } } public virtual bool Contains(INode item) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); return All.Nodes.Contains(item); } public virtual bool Contains(T item) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); return All.Values.Contains(item); } public virtual INode Find(T item) { return All.Find(item); } public virtual INode Find(Predicate predicate) { return All.Find(predicate); } //----------------------------------------------------------------------------- public INode InsertPrevious(T o) { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); NodeTree newNode = CreateNode(); newNode._Data = o; this.InsertPreviousCore(newNode); return newNode; } public INode InsertNext(T o) { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); NodeTree newNode = CreateNode(); newNode._Data = o; this.InsertNextCore(newNode); return newNode; } public INode InsertChild(T o) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); NodeTree newNode = CreateNode(); newNode._Data = o; this.InsertChildCore(newNode); return newNode; } public INode Add(T o) { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); return this.Last.InsertNext(o); } public INode AddChild(T o) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (Child == null) return InsertChild(o); else return Child.Add(o); } //----------------------------------------------------------------------------- public void InsertPrevious(ITree tree) { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); NodeTree newTree = GetNodeTree(tree); if (!newTree.IsRoot) throw new ArgumentException("Tree is not a Root"); if (!newTree.IsTree) throw new ArgumentException("Tree is not a tree"); for (INode n = newTree.Child; n != null; n = n.Next) { NodeTree node = GetNodeTree(n); NodeTree copy = node.CopyCore(); InsertPreviousCore(copy); } } public void InsertNext(ITree tree) { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); NodeTree newTree = GetNodeTree(tree); if (!newTree.IsRoot) throw new ArgumentException("Tree is not a Root"); if (!newTree.IsTree) throw new ArgumentException("Tree is not a tree"); for (INode n = newTree.LastChild; n != null; n = n.Previous) { NodeTree node = GetNodeTree(n); NodeTree copy = node.CopyCore(); InsertNextCore(copy); } } public void InsertChild(ITree tree) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); NodeTree newTree = GetNodeTree(tree); if (!newTree.IsRoot) throw new ArgumentException("Tree is not a Root"); if (!newTree.IsTree) throw new ArgumentException("Tree is not a tree"); for (INode n = newTree.LastChild; n != null; n = n.Previous) { NodeTree node = GetNodeTree(n); NodeTree copy = node.CopyCore(); InsertChildCore(copy); } } public void Add(ITree tree) { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); this.Last.InsertNext(tree); } public void AddChild(ITree tree) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (this.Child == null) this.InsertChild(tree); else this.Child.Add(tree); } //----------------------------------------------------------------------------- protected virtual void InsertPreviousCore(INode newINode) { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!newINode.IsRoot) throw new ArgumentException("Node is not a Root"); if (newINode.IsTree) throw new ArgumentException("Node is a tree"); IncrementVersion(); OnInserting(this, NodeTreeInsertOperation.Previous, newINode); NodeTree newNode = GetNodeTree(newINode); newNode._Parent = this._Parent; newNode._Previous = this._Previous; newNode._Next = this; this._Previous = newNode; if (newNode.Previous != null) { NodeTree Previous = GetNodeTree(newNode.Previous); Previous._Next = newNode; } else // this is a first node { NodeTree Parent = GetNodeTree(newNode.Parent); Parent._Child = newNode; } OnInserted(this, NodeTreeInsertOperation.Previous, newINode); } protected virtual void InsertNextCore(INode newINode) { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!newINode.IsRoot) throw new ArgumentException("Node is not a Root"); if (newINode.IsTree) throw new ArgumentException("Node is a tree"); IncrementVersion(); OnInserting(this, NodeTreeInsertOperation.Next, newINode); NodeTree newNode = GetNodeTree(newINode); newNode._Parent = this._Parent; newNode._Previous = this; newNode._Next = this._Next; this._Next = newNode; if (newNode.Next != null) { NodeTree Next = GetNodeTree(newNode.Next); Next._Previous = newNode; } OnInserted(this, NodeTreeInsertOperation.Next, newINode); } protected virtual void InsertChildCore(INode newINode) { if (!newINode.IsRoot) throw new ArgumentException("Node is not a Root"); if (newINode.IsTree) throw new ArgumentException("Node is a tree"); IncrementVersion(); OnInserting(this, NodeTreeInsertOperation.Child, newINode); NodeTree newNode = GetNodeTree(newINode); newNode._Parent = this; newNode._Next = this._Child; this._Child = newNode; if (newNode.Next != null) { NodeTree Next = GetNodeTree(newNode.Next); Next._Previous = newNode; } OnInserted(this, NodeTreeInsertOperation.Child, newINode); } protected virtual void AddCore(INode newINode) { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); NodeTree lastNode = GetNodeTree(Last); lastNode.InsertNextCore(newINode); } protected virtual void AddChildCore(INode newINode) { if (this.Child == null) this.InsertChildCore(newINode); else { NodeTree childNode = GetNodeTree(Child); childNode.AddCore(newINode); } } //----------------------------------------------------------------------------- public ITree Cut(T o) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); INode n = this[o]; if (n == null) return null; return n.Cut(); } public ITree Copy(T o) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); INode n = this[o]; if (n == null) return null; return n.Copy(); } public ITree DeepCopy(T o) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); INode n = this[o]; if (n == null) return null; return n.DeepCopy(); } public bool Remove(T o) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); INode n = this[o]; if (n == null) return false; n.Remove(); return true; } //----------------------------------------------------------------------------- private NodeTree BoxInTree(NodeTree node) { if (!node.IsRoot) throw new ArgumentException("Node is not a Root"); if (node.IsTree) throw new ArgumentException("Node is a tree"); NodeTree tree = CreateTree(); tree.AddChildCore(node); return tree; } public ITree Cut() { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); NodeTree node = CutCore(); return BoxInTree(node); } public ITree Copy() { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (IsTree) { NodeTree NewTree = CopyCore(); return NewTree; } else { NodeTree NewNode = CopyCore(); return BoxInTree(NewNode); } } public ITree DeepCopy() { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (IsTree) { NodeTree NewTree = DeepCopyCore(); return NewTree; } else { NodeTree NewNode = DeepCopyCore(); return BoxInTree(NewNode); } } public void Remove() { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); RemoveCore(); } //----------------------------------------------------------------------------- protected virtual NodeTree CutCore() { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); IncrementVersion(); OnCutting(this); INode OldRoot = Root; if (this._Next != null) this._Next._Previous = this._Previous; if (this.Previous != null) this._Previous._Next = this._Next; else // this is a first node { Debug.Assert(Parent.Child == this); this._Parent._Child = this._Next; Debug.Assert(this.Next == null || this.Next.Previous == null); } this._Parent = null; this._Previous = null; this._Next = null; OnCutDone(OldRoot, this); return this; } protected virtual NodeTree CopyCore() { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (IsRoot && !IsTree) throw new InvalidOperationException("This is a Root"); if (IsTree) { NodeTree NewTree = CreateTree(); OnCopying(this, NewTree); CopyChildNodes(this, NewTree, false); OnCopied(this, NewTree); return NewTree; } else { NodeTree NewNode = CreateNode(); NewNode._Data = Data; OnCopying(this, NewNode); CopyChildNodes(this, NewNode, false); OnCopied(this, NewNode); return NewNode; } } protected virtual NodeTree DeepCopyCore() { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (IsRoot && !IsTree) throw new InvalidOperationException("This is a Root"); if (IsTree) { NodeTree NewTree = CreateTree(); OnCopying(this, NewTree); CopyChildNodes(this, NewTree, true); OnCopied(this, NewTree); return NewTree; } else { NodeTree NewNode = CreateNode(); NewNode._Data = DeepCopyData(Data); OnDeepCopying(this, NewNode); CopyChildNodes(this, NewNode, true); OnDeepCopied(this, NewNode); return NewNode; } } private void CopyChildNodes(INode oldNode, NodeTree newNode, bool bDeepCopy) { NodeTree previousNewChildNode = null; for (INode oldChildNode = oldNode.Child; oldChildNode != null; oldChildNode = oldChildNode.Next) { NodeTree newChildNode = CreateNode(); if (!bDeepCopy) newChildNode._Data = oldChildNode.Data; else newChildNode._Data = DeepCopyData(oldChildNode.Data); // if ( ! bDeepCopy ) // OnCopying( oldChildNode, newChildNode ); // else // OnDeepCopying( oldChildNode, newChildNode ); if (oldChildNode.Previous == null) newNode._Child = newChildNode; newChildNode._Parent = newNode; newChildNode._Previous = previousNewChildNode; if (previousNewChildNode != null) previousNewChildNode._Next = newChildNode; // if ( ! bDeepCopy ) // OnCopied( oldChildNode, newChildNode ); // else // OnDeepCopied( oldChildNode, newChildNode ); CopyChildNodes(oldChildNode, newChildNode, bDeepCopy); previousNewChildNode = newChildNode; } } protected virtual void RemoveCore() { if (this.IsRoot) throw new InvalidOperationException("This is a Root"); CutCore(); } //----------------------------------------------------------------------------- public bool CanMoveToParent { get { if (this.IsRoot) return false; if (this.IsTop) return false; return true; } } public bool CanMoveToPrevious { get { if (this.IsRoot) return false; if (this.IsFirst) return false; return true; } } public bool CanMoveToNext { get { if (this.IsRoot) return false; if (this.IsLast) return false; return true; } } public bool CanMoveToChild { get { if (this.IsRoot) return false; if (this.IsFirst) return false; return true; } } public bool CanMoveToFirst { get { if (this.IsRoot) return false; if (this.IsFirst) return false; return true; } } public bool CanMoveToLast { get { if (this.IsRoot) return false; if (this.IsLast) return false; return true; } } //----------------------------------------------------------------------------- public void MoveToParent() { if (!CanMoveToParent) throw new InvalidOperationException("Cannot move to Parent"); NodeTree parentNode = GetNodeTree(this.Parent); NodeTree thisNode = this.CutCore(); parentNode.InsertNextCore(thisNode); } public void MoveToPrevious() { if (!CanMoveToPrevious) throw new InvalidOperationException("Cannot move to Previous"); NodeTree previousNode = GetNodeTree(this.Previous); NodeTree thisNode = this.CutCore(); previousNode.InsertPreviousCore(thisNode); } public void MoveToNext() { if (!CanMoveToNext) throw new InvalidOperationException("Cannot move to Next"); NodeTree nextNode = GetNodeTree(this.Next); NodeTree thisNode = this.CutCore(); nextNode.InsertNextCore(thisNode); } public void MoveToChild() { if (!CanMoveToChild) throw new InvalidOperationException("Cannot move to Child"); NodeTree previousNode = GetNodeTree(this.Previous); NodeTree thisNode = this.CutCore(); previousNode.AddChildCore(thisNode); } public void MoveToFirst() { if (!CanMoveToFirst) throw new InvalidOperationException("Cannot move to first"); NodeTree firstNode = GetNodeTree(this.First); NodeTree thisNode = this.CutCore(); firstNode.InsertPreviousCore(thisNode); } public void MoveToLast() { if (!CanMoveToLast) throw new InvalidOperationException("Cannot move to last"); NodeTree lastNode = GetNodeTree(this.Last); NodeTree thisNode = this.CutCore(); lastNode.InsertNextCore(thisNode); } //----------------------------------------------------------------------------- // Enumerators public virtual IEnumerableCollection> Nodes { get { return All.Nodes; } } public virtual IEnumerableCollection Values { get { return All.Values; } } //----------------------------------------------------------------------------- // BaseEnumerableCollectionPair protected abstract class BaseEnumerableCollectionPair : IEnumerableCollectionPair { private NodeTree _Root = null; protected NodeTree Root { get { return _Root; } set { _Root = value; } } protected BaseEnumerableCollectionPair(NodeTree root) { _Root = root; } // Nodes public abstract IEnumerableCollection> Nodes { get; } protected abstract class BaseNodesEnumerableCollection : IEnumerableCollection>, IEnumerator> { private int _Version = 0; private object _SyncRoot = new object(); private NodeTree _Root = null; protected NodeTree Root { get { return _Root; } set { _Root = value; } } private INode _CurrentNode = null; protected INode CurrentNode { get { return _CurrentNode; } set { _CurrentNode = value; } } private bool _BeforeFirst = true; protected bool BeforeFirst { get { return _BeforeFirst; } set { _BeforeFirst = value; } } private bool _AfterLast = false; protected bool AfterLast { get { return _AfterLast; } set { _AfterLast = value; } } protected BaseNodesEnumerableCollection(NodeTree root) { _Root = root; _CurrentNode = root; _Version = _Root.Version; } ~BaseNodesEnumerableCollection() { Dispose(false); } protected abstract BaseNodesEnumerableCollection CreateCopy(); protected virtual bool HasChanged { get { return _Root.HasChanged(_Version); } } // IDisposable public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { } // IEnumerable IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } // IEnumerable> public virtual IEnumerator> GetEnumerator() { Reset(); return this; } // ICollection public virtual int Count { get { BaseNodesEnumerableCollection e = CreateCopy(); int i = 0; foreach (INode o in e) i++; return i; } } public virtual bool IsSynchronized { get { return false; } } public virtual object SyncRoot { get { return _SyncRoot; } } void ICollection.CopyTo(Array array, int index) { if (array == null) throw new ArgumentNullException("array"); if (array.Rank > 1) throw new ArgumentException("array is multidimensional", "array"); if (index < 0) throw new ArgumentOutOfRangeException("index"); int count = Count; if (count > 0) if (index >= array.Length) throw new ArgumentException("index is out of bounds", "index"); if (index + count > array.Length) throw new ArgumentException("Not enough space in array", "array"); BaseNodesEnumerableCollection e = CreateCopy(); foreach (INode n in e) array.SetValue(n, index++); } public virtual void CopyTo(T[] array, int index) { ((ICollection)this).CopyTo(array, index); } // ICollectionEnumerable> public virtual bool Contains(INode item) { BaseNodesEnumerableCollection e = CreateCopy(); IEqualityComparer> comparer = EqualityComparer>.Default; foreach (INode n in e) if (comparer.Equals(n, item)) return true; return false; } // IEnumerator object IEnumerator.Current { get { return Current; } } // IEnumerator> public virtual void Reset() { if (HasChanged) throw new InvalidOperationException("Tree has been modified."); _CurrentNode = _Root; _BeforeFirst = true; _AfterLast = false; } public virtual bool MoveNext() { if (HasChanged) throw new InvalidOperationException("Tree has been modified."); _BeforeFirst = false; return true; } public virtual INode Current { get { if (_BeforeFirst) throw new InvalidOperationException("Enumeration has not started."); if (_AfterLast) throw new InvalidOperationException("Enumeration has finished."); return _CurrentNode; } } } // Find public virtual INode Find(T data) { IEqualityComparer comparer = _Root.DataComparer; INode retval = null; foreach (INode node in this.Nodes) if (comparer.Equals(node.Data, data)) if (retval != null) { Debug.Assert(false, "Multiple matches"); return null; } else retval = node; return retval; } public virtual INode Find(Predicate predicate) { INode retval = null; foreach (INode node in this.Nodes) if (predicate(node.Data)) if (retval != null) { Debug.Assert(false, "Multiple matches"); return null; } else retval = node; return retval; } // Values public virtual IEnumerableCollection Values { get { return new ValuesEnumerableCollection(_Root.DataComparer, this.Nodes); } } private class ValuesEnumerableCollection : IEnumerableCollection, IEnumerator { IEqualityComparer _DataComparer; private IEnumerableCollection> _Nodes; private IEnumerator> _Enumerator; public ValuesEnumerableCollection(IEqualityComparer dataComparer, IEnumerableCollection> nodes) { _DataComparer = dataComparer; _Nodes = nodes; _Enumerator = _Nodes.GetEnumerator(); } protected ValuesEnumerableCollection(ValuesEnumerableCollection o) { _Nodes = o._Nodes; _Enumerator = _Nodes.GetEnumerator(); } protected virtual ValuesEnumerableCollection CreateCopy() { return new ValuesEnumerableCollection(this); } // IDisposable ~ValuesEnumerableCollection() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { } // IEnumerable IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } // IEnumerable public virtual IEnumerator GetEnumerator() { Reset(); return this; } // ICollection public virtual int Count { get { return _Nodes.Count; } } public virtual bool IsSynchronized { get { return false; } } public virtual object SyncRoot { get { return _Nodes.SyncRoot; } } public virtual void CopyTo(Array array, int index) { if (array == null) throw new ArgumentNullException("array"); if (array.Rank > 1) throw new ArgumentException("array is multidimensional", "array"); if (index < 0) throw new ArgumentOutOfRangeException("index"); int count = Count; if (count > 0) if (index >= array.Length) throw new ArgumentException("index is out of bounds", "index"); if (index + count > array.Length) throw new ArgumentException("Not enough space in array", "array"); ValuesEnumerableCollection e = CreateCopy(); foreach (T n in e) array.SetValue(n, index++); } // IEnumerableCollection public virtual bool Contains(T item) { ValuesEnumerableCollection e = CreateCopy(); foreach (T n in e) if (_DataComparer.Equals(n, item)) return true; return false; } // IEnumerator object IEnumerator.Current { get { return Current; } } // IEnumerator Members public virtual void Reset() { _Enumerator.Reset(); } public virtual bool MoveNext() { return _Enumerator.MoveNext(); } public virtual T Current { get { if (_Enumerator == null) { Debug.Assert(false); return default(T); } if (_Enumerator.Current == null) { Debug.Assert(false); return default(T); } return _Enumerator.Current.Data; } } } } //----------------------------------------------------------------------------- // AllEnumerator public IEnumerableCollectionPair All { get { return new AllEnumerator(this); } } protected class AllEnumerator : BaseEnumerableCollectionPair { public AllEnumerator(NodeTree root) : base(root) { } public override IEnumerableCollection> Nodes { get { return new NodesEnumerableCollection(Root); } } protected class NodesEnumerableCollection : BaseNodesEnumerableCollection { private bool _First = true; public NodesEnumerableCollection(NodeTree root) : base(root) { } protected NodesEnumerableCollection(NodesEnumerableCollection o) : base(o.Root) { } protected override BaseNodesEnumerableCollection CreateCopy() { return new NodesEnumerableCollection(this); } public override void Reset() { base.Reset(); _First = true; } public override bool MoveNext() { if (!base.MoveNext()) goto hell; if (CurrentNode == null) throw new InvalidOperationException("Current is null"); if (CurrentNode.IsRoot) { CurrentNode = CurrentNode.Child; if (CurrentNode == null) goto hell; } if (_First) { _First = false; return true; } if (CurrentNode.Child != null) { CurrentNode = CurrentNode.Child; return true; } for (; CurrentNode.Parent != null; CurrentNode = CurrentNode.Parent) { if (CurrentNode == Root) goto hell; if (CurrentNode.Next != null) { CurrentNode = CurrentNode.Next; return true; } } hell: AfterLast = true; return false; } } } //----------------------------------------------------------------------------- // AllChildrenEnumerator public IEnumerableCollectionPair AllChildren { get { return new AllChildrenEnumerator(this); } } private class AllChildrenEnumerator : BaseEnumerableCollectionPair { public AllChildrenEnumerator(NodeTree root) : base(root) { } public override IEnumerableCollection> Nodes { get { return new NodesEnumerableCollection(Root); } } protected class NodesEnumerableCollection : BaseNodesEnumerableCollection { public NodesEnumerableCollection(NodeTree root) : base(root) { } protected NodesEnumerableCollection(NodesEnumerableCollection o) : base(o.Root) { } protected override BaseNodesEnumerableCollection CreateCopy() { return new NodesEnumerableCollection(this); } public override bool MoveNext() { if (!base.MoveNext()) goto hell; if (CurrentNode == null) throw new InvalidOperationException("Current is null"); if (CurrentNode.Child != null) { CurrentNode = CurrentNode.Child; return true; } for (; CurrentNode.Parent != null; CurrentNode = CurrentNode.Parent) { if (CurrentNode == Root) goto hell; if (CurrentNode.Next != null) { CurrentNode = CurrentNode.Next; return true; } } hell: AfterLast = true; return false; } } } //----------------------------------------------------------------------------- // DirectChildrenEnumerator public IEnumerableCollectionPair DirectChildren { get { return new DirectChildrenEnumerator(this); } } private class DirectChildrenEnumerator : BaseEnumerableCollectionPair { public DirectChildrenEnumerator(NodeTree root) : base(root) { } public override IEnumerableCollection> Nodes { get { return new NodesEnumerableCollection(Root); } } protected class NodesEnumerableCollection : BaseNodesEnumerableCollection { public NodesEnumerableCollection(NodeTree root) : base(root) { } protected NodesEnumerableCollection(NodesEnumerableCollection o) : base(o.Root) { } protected override BaseNodesEnumerableCollection CreateCopy() { return new NodesEnumerableCollection(this); } public override int Count { get { return Root.DirectChildCount; } } public override bool MoveNext() { if (!base.MoveNext()) goto hell; if (CurrentNode == null) throw new InvalidOperationException("Current is null"); if (CurrentNode == Root) CurrentNode = Root.Child; else CurrentNode = CurrentNode.Next; if (CurrentNode != null) return true; hell: AfterLast = true; return false; } } } //----------------------------------------------------------------------------- // DirectChildrenInReverseEnumerator public IEnumerableCollectionPair DirectChildrenInReverse { get { return new DirectChildrenInReverseEnumerator(this); } } private class DirectChildrenInReverseEnumerator : BaseEnumerableCollectionPair { public DirectChildrenInReverseEnumerator(NodeTree root) : base(root) { } public override IEnumerableCollection> Nodes { get { return new NodesEnumerableCollection(Root); } } protected class NodesEnumerableCollection : BaseNodesEnumerableCollection { public NodesEnumerableCollection(NodeTree root) : base(root) { } protected NodesEnumerableCollection(NodesEnumerableCollection o) : base(o.Root) { } protected override BaseNodesEnumerableCollection CreateCopy() { return new NodesEnumerableCollection(this); } public override int Count { get { return Root.DirectChildCount; } } public override bool MoveNext() { if (!base.MoveNext()) goto hell; if (CurrentNode == null) throw new InvalidOperationException("Current is null"); if (CurrentNode == Root) CurrentNode = Root.LastChild; else CurrentNode = CurrentNode.Previous; if (CurrentNode != null) return true; hell: AfterLast = true; return false; } } } //----------------------------------------------------------------------------- // DirectChildCount public int DirectChildCount { get { int i = 0; for (INode n = this.Child; n != null; n = n.Next) i++; return i; } } //----------------------------------------------------------------------------- // ITree public virtual Type DataType { get { return typeof(T); } } public void Clear() { if (!this.IsRoot) throw new InvalidOperationException("This is not a Root"); if (!this.IsTree) throw new InvalidOperationException("This is not a tree"); OnClearing(this); _Child = null; OnCleared(this); } //----------------------------------------------------------------------------- // GetNodeTree protected static NodeTree GetNodeTree(ITree tree) { if (tree == null) throw new ArgumentNullException("Tree is null"); return (NodeTree)tree; // can throw an InvalidCastException. } protected static NodeTree GetNodeTree(INode node) { if (node == null) throw new ArgumentNullException("Node is null"); return (NodeTree)node; // can throw an InvalidCastException. } //----------------------------------------------------------------------------- // ICollection // public virtual bool IsSynchronized { get { return false; } } // Not thread safe // public virtual T SyncRoot { get { return this; } } // Not sure about this! public virtual int Count { get { int i = IsRoot ? 0 : 1; for (INode n = this.Child; n != null; n = n.Next) i += n.Count; return i; } } public virtual bool IsReadOnly { get { return false; } } //----------------------------------------------------------------------------- // Sorting public virtual void SortAllChildren() { foreach (INode node in All.Nodes) node.SortDirectChildren(); } public virtual void SortAllChildren(Comparison comparison) { foreach (INode node in All.Nodes) node.SortDirectChildren(comparison); } public virtual void SortAllChildren(IComparer comparer) { foreach (INode node in All.Nodes) node.SortDirectChildren(comparer); } public virtual void SortDirectChildren() { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (DirectChildCount < 2) return; List> children = new List>(DirectChildren.Nodes); children.Sort(); SortDirectChildrenCore(children); } public virtual void SortDirectChildren(Comparison comparison) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (DirectChildCount < 2) return; List> children = new List>(DirectChildren.Nodes); children.Sort((x, y) => comparison(x.Data, y.Data)); SortDirectChildrenCore(children); } public virtual void SortDirectChildren(IComparer comparer) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (DirectChildCount < 2) return; List> children = new List>(DirectChildren.Nodes); NodeComparer nodeComparer = new NodeComparer(comparer); children.Sort(nodeComparer); SortDirectChildrenCore(children); } class NodeComparer : IComparer> { IComparer _DataComparer = null; public NodeComparer(IComparer dataComparer) { _DataComparer = dataComparer; } public int Compare(INode x, INode y) { return _DataComparer.Compare(x.Data, y.Data); } } void SortDirectChildrenCore(List> children) { _Child = null; NodeTree previous = null; foreach (INode iChild in children) { NodeTree child = GetNodeTree(iChild); child._Parent = this; child._Previous = null; child._Next = null; if (_Child == null) { _Child = child; } else { previous._Next = child; child._Previous = previous; } previous = child; } } //----------------------------------------------------------------------------- // Events private EventHandlerList _EventHandlerList; protected EventHandlerList EventHandlerList { get { return _EventHandlerList; } //set { _EventHandlerList = value; } } protected EventHandlerList GetCreateEventHandlerList() { if (_EventHandlerList == null) _EventHandlerList = new EventHandlerList(); return _EventHandlerList; } private static readonly object _ValidateEventKey = new object(); private static readonly object _ClearingEventKey = new object(); private static readonly object _ClearedEventKey = new object(); private static readonly object _SettingEventKey = new object(); private static readonly object _SetDoneEventKey = new object(); private static readonly object _InsertingEventKey = new object(); private static readonly object _InsertedEventKey = new object(); private static readonly object _CuttingEventKey = new object(); private static readonly object _CutDoneEventKey = new object(); private static readonly object _CopyingEventKey = new object(); private static readonly object _CopiedEventKey = new object(); private static readonly object _DeepCopyingEventKey = new object(); private static readonly object _DeepCopiedEventKey = new object(); protected static object ValidateEventKey { get { return _ValidateEventKey; } } protected static object ClearingEventKey { get { return _ClearingEventKey; } } protected static object ClearedEventKey { get { return _ClearedEventKey; } } protected static object SettingEventKey { get { return _SettingEventKey; } } protected static object SetDoneEventKey { get { return _SetDoneEventKey; } } protected static object InsertingEventKey { get { return _InsertingEventKey; } } protected static object InsertedEventKey { get { return _InsertedEventKey; } } protected static object CuttingEventKey { get { return _CuttingEventKey; } } protected static object CutDoneEventKey { get { return _CutDoneEventKey; } } protected static object CopyingEventKey { get { return _CopyingEventKey; } } protected static object CopiedEventKey { get { return _CopiedEventKey; } } protected static object DeepCopyingEventKey { get { return _DeepCopyingEventKey; } } protected static object DeepCopiedEventKey { get { return _DeepCopiedEventKey; } } public event EventHandler> Validate { add { GetCreateEventHandlerList().AddHandler(ValidateEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(ValidateEventKey, value); } } public event EventHandler Clearing { add { GetCreateEventHandlerList().AddHandler(ClearingEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(ClearingEventKey, value); } } public event EventHandler Cleared { add { GetCreateEventHandlerList().AddHandler(ClearedEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(ClearedEventKey, value); } } public event EventHandler> Setting { add { GetCreateEventHandlerList().AddHandler(SettingEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(SettingEventKey, value); } } public event EventHandler> SetDone { add { GetCreateEventHandlerList().AddHandler(SetDoneEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(SetDoneEventKey, value); } } public event EventHandler> Inserting { add { GetCreateEventHandlerList().AddHandler(InsertingEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(InsertingEventKey, value); } } public event EventHandler> Inserted { add { GetCreateEventHandlerList().AddHandler(InsertedEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(InsertedEventKey, value); } } public event EventHandler Cutting { add { GetCreateEventHandlerList().AddHandler(CuttingEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(CuttingEventKey, value); } } public event EventHandler CutDone { add { GetCreateEventHandlerList().AddHandler(CutDoneEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(CutDoneEventKey, value); } } public event EventHandler> Copying { add { GetCreateEventHandlerList().AddHandler(CopyingEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(CopyingEventKey, value); } } public event EventHandler> Copied { add { GetCreateEventHandlerList().AddHandler(CopiedEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(CopiedEventKey, value); } } public event EventHandler> DeepCopying { add { GetCreateEventHandlerList().AddHandler(DeepCopyingEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(DeepCopyingEventKey, value); } } public event EventHandler> DeepCopied { add { GetCreateEventHandlerList().AddHandler(DeepCopiedEventKey, value); } remove { GetCreateEventHandlerList().RemoveHandler(DeepCopiedEventKey, value); } } //----------------------------------------------------------------------------- // Validate protected virtual void OnValidate(INode node, T data) { if (!Root.IsTree) throw new InvalidOperationException("This is not a tree"); if (data is INode) throw new ArgumentException("Object is a node"); if ((!typeof(T).IsClass) || ((object)data) != null) if (!DataType.IsInstanceOfType(data)) throw new ArgumentException("Object is not a " + DataType.Name); if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[ValidateEventKey]; if (e != null) e(node, new NodeTreeDataEventArgs(data)); } if (!IsRoot) GetNodeTree(Root).OnValidate(node, data); } //----------------------------------------------------------------------------- // Clear protected virtual void OnClearing(ITree tree) { if (_EventHandlerList != null) { EventHandler e = (EventHandler)_EventHandlerList[ClearingEventKey]; if (e != null) e(tree, EventArgs.Empty); } } protected virtual void OnCleared(ITree tree) { if (_EventHandlerList != null) { EventHandler e = (EventHandler)_EventHandlerList[ClearedEventKey]; if (e != null) e(tree, EventArgs.Empty); } } //----------------------------------------------------------------------------- // Set protected virtual void OnSetting(INode node, T data) { OnSettingCore(node, data, true); } protected virtual void OnSettingCore(INode node, T data, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[SettingEventKey]; if (e != null) e(node, new NodeTreeDataEventArgs(data)); } if (!IsRoot) GetNodeTree(Root).OnSettingCore(node, data, false); if (raiseValidate) OnValidate(node, data); } protected virtual void OnSetDone(INode node, T data) { OnSetDoneCore(node, data, true); } protected virtual void OnSetDoneCore(INode node, T data, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[SetDoneEventKey]; if (e != null) e(node, new NodeTreeDataEventArgs(data)); } if (!IsRoot) GetNodeTree(Root).OnSetDoneCore(node, data, false); // if ( raiseValidate ) OnValidate( Node, Data ); } //----------------------------------------------------------------------------- // Insert protected virtual void OnInserting(INode oldNode, NodeTreeInsertOperation operation, INode newNode) { OnInsertingCore(oldNode, operation, newNode, true); } protected virtual void OnInsertingCore(INode oldNode, NodeTreeInsertOperation operation, INode newNode, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[InsertingEventKey]; if (e != null) e(oldNode, new NodeTreeInsertEventArgs(operation, newNode)); } if (!IsRoot) GetNodeTree(Root).OnInsertingCore(oldNode, operation, newNode, false); if (raiseValidate) OnValidate(oldNode, newNode.Data); if (raiseValidate) OnInsertingTree(newNode); } protected virtual void OnInsertingTree(INode newNode) { for (INode child = newNode.Child; child != null; child = child.Next) { OnInsertingTree(newNode, child); OnInsertingTree(child); } } protected virtual void OnInsertingTree(INode newNode, INode child) { OnInsertingTreeCore(newNode, child, true); } protected virtual void OnInsertingTreeCore(INode newNode, INode child, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[InsertingEventKey]; if (e != null) e(newNode, new NodeTreeInsertEventArgs(NodeTreeInsertOperation.Tree, child)); } if (!IsRoot) GetNodeTree(Root).OnInsertingTreeCore(newNode, child, false); if (raiseValidate) OnValidate(newNode, child.Data); } protected virtual void OnInserted(INode oldNode, NodeTreeInsertOperation operation, INode newNode) { OnInsertedCore(oldNode, operation, newNode, true); } protected virtual void OnInsertedCore(INode oldNode, NodeTreeInsertOperation operation, INode newNode, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[InsertedEventKey]; if (e != null) e(oldNode, new NodeTreeInsertEventArgs(operation, newNode)); } if (!IsRoot) GetNodeTree(Root).OnInsertedCore(oldNode, operation, newNode, false); // if ( raiseValidate ) OnValidate( OldNode, NewNode.Data ); if (raiseValidate) OnInsertedTree(newNode); } protected virtual void OnInsertedTree(INode newNode) { for (INode child = newNode.Child; child != null; child = child.Next) { OnInsertedTree(newNode, child); OnInsertedTree(child); } } protected virtual void OnInsertedTree(INode newNode, INode child) { OnInsertedTreeCore(newNode, child, true); } protected virtual void OnInsertedTreeCore(INode newNode, INode child, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[InsertedEventKey]; if (e != null) e(newNode, new NodeTreeInsertEventArgs(NodeTreeInsertOperation.Tree, child)); } if (!IsRoot) GetNodeTree(Root).OnInsertedTreeCore(newNode, child, false); // if ( raiseValidate ) OnValidate( newNode, child.Data ); } //----------------------------------------------------------------------------- // Cut protected virtual void OnCutting(INode oldNode) { if (_EventHandlerList != null) { EventHandler e = (EventHandler)_EventHandlerList[CuttingEventKey]; if (e != null) e(oldNode, EventArgs.Empty); } if (!IsRoot) GetNodeTree(Root).OnCutting(oldNode); } protected virtual void OnCutDone(INode oldRoot, INode oldNode) { if (_EventHandlerList != null) { EventHandler e = (EventHandler)_EventHandlerList[CutDoneEventKey]; if (e != null) e(oldNode, EventArgs.Empty); } if (!IsTree) GetNodeTree(oldRoot).OnCutDone(oldRoot, oldNode); } //----------------------------------------------------------------------------- // Copy protected virtual void OnCopying(INode oldNode, INode newNode) { OnCopyingCore(oldNode, newNode, true); } protected virtual void OnCopyingCore(INode oldNode, INode newNode, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[CopyingEventKey]; if (e != null) e(oldNode, new NodeTreeNodeEventArgs(newNode)); } if (!IsRoot) GetNodeTree(Root).OnCopyingCore(oldNode, newNode, false); // if ( raiseValidate ) OnValidate( oldNode, newNode.Data ); } protected virtual void OnCopied(INode oldNode, INode newNode) { OnCopiedCore(oldNode, newNode, true); } protected virtual void OnCopiedCore(INode oldNode, INode newNode, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[CopiedEventKey]; if (e != null) e(oldNode, new NodeTreeNodeEventArgs(newNode)); } if (!IsRoot) GetNodeTree(Root).OnCopiedCore(oldNode, newNode, false); // if ( raiseValidate ) OnValidate( oldNode, newNode.Data ); } //----------------------------------------------------------------------------- // DeepCopy protected virtual void OnDeepCopying(INode oldNode, INode newNode) { OnDeepCopyingCore(oldNode, newNode, true); } protected virtual void OnDeepCopyingCore(INode oldNode, INode newNode, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[DeepCopyingEventKey]; if (e != null) e(oldNode, new NodeTreeNodeEventArgs(newNode)); } if (!IsRoot) GetNodeTree(Root).OnDeepCopyingCore(oldNode, newNode, false); // if ( raiseValidate ) OnValidate( oldNode, newNode.Data ); } protected virtual void OnDeepCopied(INode oldNode, INode newNode) { OnDeepCopiedCore(oldNode, newNode, true); } protected virtual void OnDeepCopiedCore(INode oldNode, INode newNode, bool raiseValidate) { if (_EventHandlerList != null) { EventHandler> e = (EventHandler>)_EventHandlerList[DeepCopiedEventKey]; if (e != null) e(oldNode, new NodeTreeNodeEventArgs(newNode)); } if (!IsRoot) GetNodeTree(Root).OnDeepCopiedCore(oldNode, newNode, false); // if ( raiseValidate ) OnValidate( oldNode, newNode.Data ); } //----------------------------------------------------------------------------- } // class NodeTree //----------------------------------------------------------------------------- }