#region License Information /* HeuristicLab * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using HeuristicLab.PluginInfrastructure; using HeuristicLab.Visualization; namespace HeuristicLab.Networks.Views.NetworkVisualization { [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public sealed class PrimitiveAttribute : Attribute { public Type VisualizableType { get; private set; } public bool IsDefaultPrimitive { get; set; } private static readonly Dictionary defaultPrimitives = new Dictionary(); static PrimitiveAttribute() { var primitiveTypes = ApplicationManager.Manager.GetTypes(typeof(IPrimitive), true, true) .Where(x => !x.IsAbstract && !x.IsInterface && HasPrimitiveAttribute(x)); foreach (var primitiveType in primitiveTypes) { foreach (var visualizableType in GetDefaultVisualizableTypes(primitiveType)) { if (defaultPrimitives.ContainsKey(visualizableType)) throw new ArgumentException("DefaultPrimitive for type " + visualizableType + " is " + defaultPrimitives[visualizableType] + ". Can't register additional DefaultPrimitive " + primitiveType + "."); defaultPrimitives[visualizableType] = primitiveType; } } } public PrimitiveAttribute(Type visualizableType) { VisualizableType = visualizableType; } public PrimitiveAttribute(Type visualizableType, bool isDefaultPrimitive) : this(visualizableType) { IsDefaultPrimitive = isDefaultPrimitive; } public static bool HasPrimitiveAttribute(MemberInfo primitiveType) { var attributes = primitiveType.GetCustomAttributes(typeof(PrimitiveAttribute), false); return attributes.Any(); } public static bool CanVisualizeType(MemberInfo primitiveType, Type visualizable) { var attributes = (PrimitiveAttribute[])primitiveType.GetCustomAttributes(typeof(PrimitiveAttribute), false); return attributes.Any(x => visualizable.IsAssignableFrom(x.VisualizableType)); } public static IEnumerable GetDefaultVisualizableTypes(Type primitiveType) { var attributes = (PrimitiveAttribute[])primitiveType.GetCustomAttributes(typeof(PrimitiveAttribute), false); return attributes.Where(x => x.IsDefaultPrimitive).Select(x => x.VisualizableType); } public static IEnumerable GetVisualizableTypes(Type primitiveType) { var attributes = (PrimitiveAttribute[])primitiveType.GetCustomAttributes(typeof(PrimitiveAttribute), false); return attributes.Select(x => x.VisualizableType); } public static IPrimitive CreateDefaultPrimitive(Type visualizableType, params object[] args) { var t = GetDefaultPrimitiveType(visualizableType); if (t == null) return null; return (IPrimitive)Activator.CreateInstance(t, args); } // TODO: add support for generic types public static Type GetDefaultPrimitiveType(Type visualizableType) { var type = visualizableType; while (type != null) { Type primitiveType; if (defaultPrimitives.TryGetValue(type, out primitiveType)) return primitiveType; var nonInheritedInterfaces = type.GetInterfaces().Where(i => !i.IsAssignableFrom(type.BaseType)); var interfaces = new HashSet(nonInheritedInterfaces); while (interfaces.Any()) { interfaces.RemoveWhere(i => interfaces.Any(x => x.GetInterfaces().Contains(i))); var defaultViewList = defaultPrimitives.Keys.Where(interfaces.Contains).Select(x => defaultPrimitives[x]).ToList(); foreach (Type viewType in defaultViewList) if (defaultViewList.Any(t => t.IsSubclassOf(viewType))) defaultViewList.Remove(viewType); if (defaultViewList.Count == 1) return defaultViewList[0]; if (defaultViewList.Count > 1) throw new InvalidOperationException("Could not determine which is the default primitive for type " + visualizableType + " because more than one implemented interfaces have a default primitive."); interfaces = new HashSet(interfaces.SelectMany(i => i.GetInterfaces())); } type = type.BaseType; } return null; } } }