text: #region License
  
  // Copyright (c) 2013, ClearCanvas Inc.
  // All rights reserved.
  // http://www.clearcanvas.ca
  //
  // This file is part of the ClearCanvas RIS/PACS open source project.
  //
  // The ClearCanvas RIS/PACS open source project 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.
  //
  // The ClearCanvas RIS/PACS open source project 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
  // the ClearCanvas RIS/PACS open source project.  If not, see
  // <http://www.gnu.org/licenses/>.
  
  #endregion
  
  using System;
  using System.Collections.Generic;
  using System.Configuration;
  using System.Linq;
  using System.Runtime.Serialization;
  
  namespace ClearCanvas.Common.Configuration
  {
  	[Flags]
  	public enum SettingsGroupFilter
  	{
  		/// <summary>
  		/// All settings groups (no filter).
  		/// </summary>
  		All = 0,
  
  		/// <summary>
  		/// Settings groups that will be stored in the enterprise configuration store, if one exists.
  		/// </summary>
  		SupportEnterpriseStorage		= 0x01,
  
  		/// <summary>
  		/// Settings groups that use some form of local storage.
  		/// </summary>
  		LocalStorage					= 0x02,
  
  		/// <summary>
  		/// Settings groups that support editing of the shared profile.
  		/// </summary>
  		SupportsEditingOfSharedProfile	= 0x04,
  	}
  
  	/// <summary>
  	/// Describes a settings group.
  	/// </summary>
  	[DataContract]
  	public class SettingsGroupDescriptor : IEquatable<SettingsGroupDescriptor>
  	{
  		/// <summary>
  		/// Returns a list of <see cref="SettingsGroupDescriptor"/> objects describing each settings class
  		/// that exists in the installed plugin base.
  		/// </summary>
  		/// <remarks>
  		/// This method is thread-safe.
  		/// </remarks>
  		public static List<SettingsGroupDescriptor> ListInstalledSettingsGroups()
  		{
  			return ListInstalledSettingsGroups(SettingsGroupFilter.All);
  		}
  
  		/// <summary>
  		/// Returns a list of <see cref="SettingsGroupDescriptor"/> objects describing each settings class
  		/// that exists in the installed plugin base, applying the specified filter.
  		/// </summary>
  		/// <remarks>
  		/// This method is thread-safe.
  		/// </remarks>
  		public static List<SettingsGroupDescriptor> ListInstalledSettingsGroups(SettingsGroupFilter filter)
  		{
  			return ListInstalledSettingsGroups(type => ApplyFilter(filter, type));
  		}
  
  		private static List<SettingsGroupDescriptor> ListInstalledSettingsGroups(Predicate<Type> filter)
  		{
  			var assemblies = Platform.PluginManager.Plugins
  				.Select(p => p.Assembly.Resolve())
  				.Concat(new[] { typeof(SettingsGroupDescriptor).Assembly });
  
  			var q = from assembly in assemblies
  					from t in assembly.GetTypes()
  					where t.IsSubclassOf(typeof(ApplicationSettingsBase)) && !t.IsAbstract && filter(t)
  					select new SettingsGroupDescriptor(t);
  
  			return q.ToList();
  		}
  
  		//Internal for unit tests
  		internal static bool ApplyFilter(SettingsGroupFilter filter, Type type)
  		{
  			if (filter == 0)
  				return true;
  
  			var providerClass = SettingsClassMetaDataReader.GetSettingsProvider(type);
  			if ((filter & SettingsGroupFilter.SupportEnterpriseStorage) == SettingsGroupFilter.SupportEnterpriseStorage
  				&& providerClass == typeof(StandardSettingsProvider))
  				return true;
  
  			if ((filter & SettingsGroupFilter.LocalStorage) == SettingsGroupFilter.LocalStorage
  				&& ApplicationSettingsHelper.IsLocallyStored(type))
  				return true;
  
  			if ((filter & SettingsGroupFilter.SupportsEditingOfSharedProfile) == SettingsGroupFilter.SupportsEditingOfSharedProfile
  				&& typeof(ISharedApplicationSettingsProvider).IsAssignableFrom(providerClass))
  				return true;
  
  			return false;
  		}
  
  		/// <summary>
  		/// Constructor.
  		/// </summary>
  		public SettingsGroupDescriptor(string name, Version version, string description, string assemblyQualifiedTypeName,
  			bool hasUserScopedSettings)
  		{
  			Name = name;
  			Version = version;
  			Description = description;
  			AssemblyQualifiedTypeName = assemblyQualifiedTypeName;
  			HasUserScopedSettings = hasUserScopedSettings;
  		}
  
  		/// <summary>
  		/// Constructor.
  		/// </summary>
  		public SettingsGroupDescriptor(Type settingsClass)
  		{
  			Name = SettingsClassMetaDataReader.GetGroupName(settingsClass);
  			Version = SettingsClassMetaDataReader.GetVersion(settingsClass, true);
  			Description = SettingsClassMetaDataReader.GetGroupDescription(settingsClass);
  			HasUserScopedSettings = SettingsClassMetaDataReader.HasUserScopedSettings(settingsClass);
  			AssemblyQualifiedTypeName = GetSafeClassName(settingsClass);
  		}
  
  		/// <summary>
  		/// Gets the name of the settings group.
  		/// </summary>
  		[DataMember]
  		public string Name { get; private set; }
  
  		/// <summary>
  		/// Gets the version of the settings group.
  		/// </summary>
  		[DataMember]
  		public Version Version { get; private set; }
  
  		/// <summary>
  		/// Gets the description of the settings group.
  		/// </summary>
  		[DataMember]
  		public string Description { get; private set; }
  
  		/// <summary>
  		/// Gets a value indicating whether this settings class has user-scoped settings.
  		/// </summary>
  		[DataMember]
  		public bool HasUserScopedSettings { get; private set; }
  
  		/// <summary>
  		/// Gets the assembly-qualified type name of the class that implements the settings group.
  		/// </summary>
  		[DataMember]
  		public string AssemblyQualifiedTypeName { get; private set; }
  
  		/// <summary>
  		/// Settings groups are considered equal if they have the same name and version.
  		/// </summary>
  		public override bool Equals(object obj)
  		{
  			return this.Equals(obj as SettingsGroupDescriptor);
  		}
  
  		/// <summary>
  		/// Gets the hash code for this object.
  		/// </summary>
  		public override int GetHashCode()
  		{
  			return Name.GetHashCode() ^ Version.GetHashCode();
  		}
  
  		public override string ToString()
  		{
  			return Name;
  		}
  
  		#region IEquatable<SettingsGroupDescriptor> Members
  
  		/// <summary>
  		/// Settings groups are considered equal if they have the same name and version.
  		/// </summary>
  		public bool Equals(SettingsGroupDescriptor other)
  		{
  			return other != null && this.Name == other.Name && this.Version == other.Version;
  		}
  
  		#endregion
  
  		/// <summary>
  		/// Gets the assembly qualified name of the type, but without all the version and culture info.
  		/// </summary>
  		/// <param name="settingsClass"></param>
  		/// <returns></returns>
  		private static string GetSafeClassName(Type settingsClass)
  		{
  			return string.Format("{0}, {1}", settingsClass.FullName, settingsClass.Assembly.GetName().Name);
  		}
  
  	}
  }