using System;
using System.Collections.Generic;
using Chernobyl.Collections.Generic.Event;
using Chernobyl.Collections.Generic.Hierarchy;
using Chernobyl.Event;
using Chernobyl.Utility;
namespace Chernobyl.Collections.Generic.Graph
{
///
/// A type used to maintain bi-directional connections between nodes in a
/// graph.
///
/// The vertice reference types that
/// make up the types contained in the network.
public class Connections : Collection
where TNode : class
{
///
/// Initializes a new instance of the
/// class.
///
/// The instance whose connections are being
/// held by this.
/// The method used to get the connection
/// from a
/// type. This method will be used to add/remove the
/// to/from the connected .
/// Thrown if any of the parameters
/// provided are null.
public Connections(TNode connected, Func> getConnections)
{
connected.ThrowIfNull("parent");
getConnections.ThrowIfNull("getChildren");
_connected = connected;
_getConnections = getConnections;
_implementation = new DecoratingEventList();
_implementation.ItemsAdded += OnItemsAdded;
_implementation.ItemsRemoved += OnItemsRemoved;
}
///
/// The implementation of this .
///
protected override ICollection Implementation
{
get { return _implementation; }
}
///
/// Invoked when an item is added to this .
/// This method ensures that the new
/// intances are also connected to the .
///
/// The sender of the event.
/// The instance
/// containing the event data.
void OnItemsAdded(object sender, ItemsEventArgs e)
{
// If the parent node isn't already in this node, add it.
foreach (TNode node in e.Items)
{
ICollection nodeConnections = _getConnections(node);
if (nodeConnections.Contains(_connected) == false)
nodeConnections.Add(_connected);
}
}
///
/// Invoked when an item is remove from this .
/// This method ensures that the old
/// intances are also disconnected from the .
///
/// The sender of the event.
/// The instance
/// containing the event data.
void OnItemsRemoved(object sender, ItemsEventArgs e)
{
// Remove the parent connection from the
foreach (TNode node in e.Items)
_getConnections(node).Remove(_connected);
}
///
/// The instance whose connections are being held by this.
///
readonly TNode _connected;
///
/// The method used to get the connection
/// from a type. This method will be used
/// to add/remove the to/from the connected
/// .
///
readonly Func> _getConnections;
///
/// The backing field to .
///
readonly IEventCollection _implementation;
}
///
/// A type used to maintain bi-directional connections between
/// instances in a graph. This type
/// performs the same job as but is easier
/// to create for types.
///
public class NodeConnections : Connections
{
///
/// Initializes a new instance of the class.
///
/// The instance whose connections are being
/// held by this.
public NodeConnections(INode connected)
: base(connected, connection => connection.Connections)
{ }
}
}