// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using System.Reflection;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
namespace OpenTap
{
///
/// with this attribute belong to a group with a specified name.
/// They can be marked as profile groups, enabling selectable profiles for settings in that group.
///
[AttributeUsage(AttributeTargets.Class)]
public class SettingsGroupAttribute : Attribute
{
///
/// Name of the settings group.
///
public string GroupName { get; }
///
/// Specifies whether this settings group uses profiles.
///
public bool Profile { get; }
///
/// Constructor for
///
/// The name of the settings group.
/// If this settings group should use profiles.
public SettingsGroupAttribute(string GroupName, bool Profile = true)
{
this.GroupName = GroupName;
this.Profile = Profile;
}
}
///
/// Attribute that determines if the settings list should be fixed.
///
[AttributeUsage(AttributeTargets.Class)]
public class FixedSettingsListAttribute : Attribute
{
}
internal interface IComponentSettingsList : IList
{
/// Return the objects which have been removed but still alive (non-GC'd) resources.
/// This requires using a list of WeakReferences.
IResource[] GetRemovedAliveResources();
}
///
/// Contains some extra functionality for the ComponentSettingsList.
/// Created so that it is possible to know which (generic) ComponentSettingsList
/// contains a given type.
///
public static class ComponentSettingsList
{
static Dictionary typeHandlersCache;
static Dictionary typeHandlers
{
get
{
if (typeHandlersCache == null)
{
typeHandlersCache = new Dictionary();
foreach (Type settingsType in PluginManager.GetPlugins(typeof(ComponentSettings)))
{
Type baseType = settingsType;
while (baseType != typeof(object))
{
baseType = baseType.BaseType;
if (baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(ComponentSettingsList<,>))
{
Type[] types = settingsType.BaseType.GetGenericArguments();
if (types.Length == 2)
{
typeHandlersCache[types[1]] = types[0];
break;
}
}
}
}
}
return typeHandlersCache;
}
}
///
/// Gets the GetCurrent method for the container for type T.
/// Null if no such container.
///
///
///
static PropertyInfo getGetCurrentMethodForContainer(Type T)
{
return getGetCurrentMethodsForContainer(T).FirstOrDefault();
}
static IEnumerable getGetCurrentMethodsForContainer(Type T)
{
if (T == null)
throw new ArgumentNullException("T");
foreach (Type key in typeHandlers.Keys)
{
if (T.DescendsTo(key))
{
Type compSetType = typeHandlers[key];
if (GetCurrentProp(compSetType) is { } prop)
yield return prop;
}
}
}
private static PropertyInfo GetCurrentProp(Type compSetType)
{
return compSetType.GetProperty("Current", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
}
private static IList GetCurrent(Type compSetType)
{
if (GetCurrentProp(compSetType) is {} prop)
return (IList)prop.GetValue(null, null);
return null;
}
///
/// Finds a ComponentSettingsList containing instances of T.
///
///
/// A List of type T. Null if no ComponentSettingsList exists containing T.
public static IList GetContainer(Type T)
{
var m = getGetCurrentMethodForContainer(T);
if (m == null) return null;
return (IList)m.GetValue(null, null);
}
internal static IEnumerable GetResourceContainers()
{
foreach (Type key in typeHandlers.Keys)
{
if (!key.DescendsTo(typeof(IResource))) continue;
Type compSetType = typeHandlers[key];
if (GetCurrent(compSetType) is IList lst)
yield return lst;
}
}
///
/// For checking if there is a ComponentSettings for T without evaluating GetCurrent.
///
///
///
internal static bool HasContainer(Type T)
{
return getGetCurrentMethodForContainer(T) != null;
}
///
/// Gets the ComponentSettings list for T and filters the instances that are not T.
///
///
public static IList GetItems()
{
IList items = GetContainer(typeof(T));
if (items == null) return new List();
return items.OfType().ToList();
}
///
/// (non-generic) Gets the ComponentSettings list for T and filters the instances that are not T.
///
///
///
public static IList GetItems(Type T)
{
var container = GetContainer(T);
if (container == null) return new List