using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace DotNetOpenId {
///
/// A dictionary of handle/Association pairs.
///
///
/// Each method is locked, even if it is only one line, so that they are thread safe
/// against each other, particularly the ones that enumerate over the list, since they
/// can break if the collection is changed by another thread during enumeration.
///
[DebuggerDisplay("Count = {assocs.Count}")]
internal class Associations {
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
Dictionary assocs;
///
/// Instantiates a mapping between association handles and objects.
///
public Associations() {
this.assocs = new Dictionary();
}
///
/// Stores an in the collection.
///
public void Set(Association association) {
if (association == null) throw new ArgumentNullException("association");
lock (this) {
this.assocs[association.Handle] = association;
}
}
///
/// Returns the with the given handle. Null if not found.
///
public Association Get(string handle) {
lock (this) {
Association assoc;
assocs.TryGetValue(handle, out assoc);
return assoc;
}
}
///
/// Removes the with the given handle.
///
/// Whether an with the given handle was in the collection for removal.
public bool Remove(string handle) {
lock (this) {
return assocs.Remove(handle);
}
}
///
/// Gets the issued most recently. Null if no valid associations exist.
///
public Association Best {
get {
lock (this) {
Association best = null;
foreach (Association assoc in assocs.Values) {
if (best == null || best.Issued < assoc.Issued)
best = assoc;
}
return best;
}
}
}
///
/// Removes all expired associations from the collection.
///
public void ClearExpired() {
lock (this) {
var expireds = new List(assocs.Count);
foreach (Association assoc in assocs.Values)
if (assoc.IsExpired)
expireds.Add(assoc);
foreach (Association assoc in expireds)
assocs.Remove(assoc.Handle);
}
}
}
}