diff options
author | Lluis Sanchez <lluis@novell.com> | 2010-03-17 15:30:51 +0300 |
---|---|---|
committer | Lluis Sanchez <lluis@novell.com> | 2010-03-17 15:30:51 +0300 |
commit | 3352c438c92957c57ce5818d2b410b9d761076f5 (patch) | |
tree | 0fdce565f42e17cbc1675f014da34527b99e0fa5 /main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyContainer.cs | |
parent | de8a39a96737efd04aabafb4cc27c546061c90f5 (diff) | |
parent | 585086f0ea0a49166046bb8f48d2def87907d0e0 (diff) |
Merged MD.Projects into MD.Core, and MD.Projects.Gui, MD.Core.Gui and MD.Components into MD.Ide.
svn path=/trunk/monodevelop/; revision=153728
Diffstat (limited to 'main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyContainer.cs')
-rw-r--r-- | main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyContainer.cs | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyContainer.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyContainer.cs new file mode 100644 index 0000000000..c5c778e8c1 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyContainer.cs @@ -0,0 +1,287 @@ +// +// PolicyContainer.cs +// +// Author: +// Lluis Sanchez Gual <lluis@novell.com> +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; + +namespace MonoDevelop.Projects.Policies +{ + /// <summary> + /// A set of policies. Policies are identified by type. + /// </summary> + public abstract class PolicyContainer + { + internal PolicyDictionary policies; + + /// <summary> + /// Returns true if there isn't any policy defined. + /// </summary> + public bool IsEmpty { + get { return policies == null || policies.Count == 0; } + } + + /// <summary> + /// The Get methods return policies taking into account inheritance. If a policy + /// can't be found it may return null, but never an 'undefined' policy. + /// </summary> + /// <returns> + /// The policy of the given type, or null if not found. + /// </returns> + public T Get<T> () where T : class, IEquatable<T>, new () + { + if (policies != null) { + object policy; + if (policies.TryGetValue (typeof(T), null, out policy)) { + if (!PolicyService.IsUndefinedPolicy (policy)) + return (T)policy; + else if (InheritDefaultPolicies) + return PolicyService.GetDefaultPolicy<T> (); + else + return null; + } + } + if (!InheritDefaultPolicies) + return null; + else if (IsRoot) + return PolicyService.GetDefaultPolicy<T> (); + else + return ParentPolicies.Get<T> (); + } + + public T Get<T> (string scope) where T : class, IEquatable<T>, new () + { + return Get<T> (new string[] { scope }); + } + + public T Get<T> (IEnumerable<string> scopes) where T : class, IEquatable<T>, new () + { + // The search is done vertically, looking first at the parents + foreach (string scope in scopes) { + PolicyContainer currentBag = this; + while (currentBag != null) { + if (currentBag.DirectHas<T> (scope)) { + T pol = currentBag.DirectGet<T> (scope); + if (!PolicyService.IsUndefinedPolicy (pol)) + return pol; + // If the bag has the policy (Has<> returns true) but the policy is undefined, + // then we have to keep looking using the base scopes. + // We start looking from the original bag, using the new scope. + break; + } else + currentBag = currentBag.ParentPolicies; + } + } + if (InheritDefaultPolicies) + return PolicyService.GetDefaultPolicy<T>(scopes); + else + return null; + } + + public void Set<T> (T value) where T : class, IEquatable<T>, new () + { + Set (value, null); + } + + public void Set<T> (T value, string scope) where T : class, IEquatable<T>, new () + { + CheckReadOnly (); + PolicyKey key = new PolicyKey (typeof(T), scope); + System.Diagnostics.Debug.Assert (key.Scope == scope); + + if (policies == null) { + policies = new PolicyDictionary (); + } else if (value != null) { + object oldVal = null; + policies.TryGetValue (key, out oldVal); + if (oldVal != null && ((IEquatable<T>)oldVal).Equals (value)) + return; + } + + policies[key] = value; + OnPolicyChanged (key.PolicyType, key.Scope); + } + + internal void InternalSet (Type t, string scope, object ob) + { + PolicyKey key = new PolicyKey (t, scope); + if (policies == null) + policies = new PolicyDictionary (); + policies[key] = ob; + OnPolicyChanged (key.PolicyType, key.Scope); + } + + public bool Remove<T> () where T : class, IEquatable<T>, new () + { + CheckReadOnly (); + return Remove<T> (null); + } + + public bool Remove<T> (string scope) where T : class, IEquatable<T>, new () + { + CheckReadOnly (); + return InternalRemove (typeof(T), scope); + } + + internal bool InternalRemove (Type type, string scope) + { + if (policies != null) { + if (policies.Remove (new PolicyKey (type, scope))) { + OnPolicyChanged (type, scope); + if (policies.Count == 0) + policies = null; + return true; + } + } + return false; + } + + public IEnumerable<string> GetScopes<T> () + { + foreach (PolicyKey pk in policies.Keys) { + if (pk.PolicyType == typeof(T)) + yield return pk.Scope; + } + } + + public IEnumerable<ScopedPolicy<T>> GetScoped<T> () where T : class, IEquatable<T>, new () + { + if (policies == null) + yield break; + + foreach (KeyValuePair<PolicyKey,object> pinfo in policies) { + if (pinfo.Key.PolicyType == typeof(T)) + yield return new ScopedPolicy<T> ((T)pinfo.Value, pinfo.Key.Scope); + } + T pol = Get<T> (); + if (pol != null && !PolicyService.IsUndefinedPolicy (pol)) + yield return new ScopedPolicy<T> (pol, null); + } + + internal IEnumerable<ScopedPolicy> GetScoped (Type t) + { + foreach (KeyValuePair<PolicyKey,object> pinfo in policies) { + if (pinfo.Key.PolicyType == t) + yield return new ScopedPolicy (t, pinfo.Value, pinfo.Key.Scope); + } + object pol = Get (t); + if (pol != null) + yield return new ScopedPolicy (t, pol, null); + } + + internal object Get (Type type) + { + return Get (type, (string) null); + } + + internal object Get (Type type, string scope) + { + if (policies == null) + return null; + object o; + if (policies.TryGetValue (type, scope, out o)) { + if (PolicyService.IsUndefinedPolicy (o)) + return null; + } + return o; + } + + public abstract bool IsRoot { get; } + + public event EventHandler<PolicyChangedEventArgs> PolicyChanged; + + #region Methods to be used for fine grained management of policies + + // The DirectGet set of methods returns policies directly stored in the container, + // ignoring inherited policies. Those methods can return undefined policies, + // so return values have to be checked with PolicyService.IsUndefinedPolicy + + internal PolicyDictionary Policies { get { return policies; } } + + public T DirectGet<T> () where T : class, IEquatable<T>, new () + { + return DirectGet<T> (null); + } + + public T DirectGet<T> (string scope) where T : class, IEquatable<T>, new () + { + if (policies != null) { + object policy; + if (policies.TryGetValue (typeof(T), scope, out policy)) + return (T) policy; + } + return null; + } + + public bool DirectHas<T> () + { + return DirectHas<T> ((string)null); + } + + public bool DirectHas<T> (string scope) + { + return policies != null && policies.ContainsKey (new PolicyKey (typeof(T), scope)); + } + + public bool DirectHas<T> (IEnumerable<string> scopes) + { + foreach (string scope in scopes) { + if (DirectHas<T> (scope)) + return true; + } + return false; + } + + /// <summary> + /// The set of policies from which inherit policies when not found in this container + /// </summary> + public abstract PolicyContainer ParentPolicies { get; } + + #endregion + + /// <summary> + /// When set to true, the container will return a default policy when requesting a + /// policy object that is not defined in the container. + /// </summary> + protected abstract bool InheritDefaultPolicies { get; } + + protected virtual void OnPolicyChanged (Type policyType, string scope) + { + if (PolicyChanged != null) + PolicyChanged (this, new PolicyChangedEventArgs (policyType, scope)); + } + + public virtual bool ReadOnly { + get; + internal set; + } + + void CheckReadOnly () + { + if (ReadOnly) + throw new InvalidOperationException ("This PolicyContainer can't be modified"); + } + } +} |