using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CategoryTheory
{
/// <summary>
/// Extensions methods
/// </summary>
public static class StaticExtension
{
/// <summary>
/// Exception message
/// </summary>
public static readonly string TargetSourceArrow = "Target of first arrow does not coincide with source of next arrow";
/// <summary>
/// Gets interface of object
/// </summary>
/// <param name="obj">object</param>
/// <param name="interfaceName">Interface name</param>
/// <returns>The interface</returns>
static object GetInterface(this IAssociatedObject obj, string interfaceName)
{
Type t = obj.GetType();
Type ti = t.GetInterface(interfaceName);
if (ti != null)
{
return obj;
}
if (obj is IChildrenObject)
{
IChildrenObject co = obj as IChildrenObject;
IAssociatedObject[] ch = co.Children;
if (ch != null)
{
foreach (IAssociatedObject ob in ch)
{
if (ob != null)
{
object o = GetInterface(ob, interfaceName);
if (o != null)
{
return o;
}
}
}
}
}
return null;
}
/// <summary>
/// Gets object of predefined type
/// </summary>
/// <typeparam name="T">The type</typeparam>
/// <param name="obj">The prototype</param>
/// <returns>The object of predefined type</returns>
public static T GetObject<T>(this IAssociatedObject obj) where T : class
{
// If o is subtype of t
if (obj is T)
{
// Returns o as T
return obj as T;
}
// Search in childen
// If o is IChildrenObject
if (obj is IChildrenObject)
{
IChildrenObject co = obj as IChildrenObject;
// Gets children
IAssociatedObject[] ch = co.Children;
if (ch != null)
{
// Recursive search among children
foreach (IAssociatedObject ob in ch)
{
T a = GetObject<T>(ob);
// If chid object is found
if (a != null)
{
// Returns the object
return a;
}
}
}
}
return null;
}
/// <summary>
/// Try to get object of predefined type
/// </summary>
/// <typeparam name="T">The type</typeparam>
/// <param name="obj">The prototype</param>
/// <param name="message">The exception message</param>
/// <returns>The object of predefined type</returns>
public static T GetObject<T>(this IAssociatedObject obj, string message) where T : class
{
T a = GetObject<T>(obj);
if (a != null)
{
return a;
}
throw new Exception(message);
}
/// <summary>
/// Try to get source of the arrow
/// </summary>
/// <typeparam name="T">Source type</typeparam>
/// <param name="obj">The prototype</param>
/// <returns>The source</returns>
public static T GetSource<T>(this IAssociatedObject obj) where T : class
{
return GetObject<T>(obj, CategoryException.IllegalSource);
}
/// <summary>
/// Try to get target of arrow
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj">Target type</param>
/// <returns>The target</returns>
public static T GetTarget<T>(this IAssociatedObject obj) where T : class
{
return GetObject<T>(obj, CategoryException.IllegalTarget);
}
/// <summary>
/// Gets simple object
/// </summary>
/// <typeparam name="T">Type of object</typeparam>
/// <param name="o">Initial object</param>
/// <returns>The object</returns>
public static T GetSimpleObject<T>(this object o) where T : class
{
if (o is T)
{
return o as T;
}
return null;
}
/// <summary>
/// Gets simple object
/// </summary>
/// <typeparam name="T">Type of object</typeparam>
/// <param name="o">Initial object</param>
/// <param name="message">Exception message</param>
/// <returns>The object</returns>
public static T GetSimpleObject<T>(this object o, string message) where T : class
{
T t = GetSimpleObject<T>(o);
if (t != null)
{
return t;
}
throw new Exception(message);
}
/// <summary>
/// Sets associated object to object and all its children;
/// </summary>
/// <param name="ao">The associated object</param>
/// <param name="obj">The object to set</param>
static public void SetAssociatedObject(this IAssociatedObject ao, object obj)
{
ao.Object = obj;
if (ao is IChildrenObject)
{
IChildrenObject co = ao as IChildrenObject;
IAssociatedObject[] ch = co.Children;
if (ch != null)
{
foreach (IAssociatedObject o in ch)
{
if (o != null)
{
SetAssociatedObject(o, obj);
}
}
}
}
}
/// <summary>
/// Checks connection between first and next arrow
/// </summary>
/// <param name="first">The first arrow</param>
/// <param name="next">The next arrow</param>
static public void CheckArrowConnection(this ICategoryArrow first, ICategoryArrow next)
{
if (first.Source != next.Target)
{
throw new CategoryException(TargetSourceArrow);
}
}
}
}