//-----------------------------------------------------------------------
//
// Copyright (c) Outercurve Foundation. All rights reserved.
//
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.Extensions {
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using DotNetOpenAuth.Messaging;
using Validation;
///
/// Manages a fast, two-way mapping between type URIs and their aliases.
///
internal class AliasManager {
///
/// The format of auto-generated aliases.
///
private const string AliasFormat = "alias{0}";
///
/// Tracks extension Type URIs and aliases assigned to them.
///
private Dictionary typeUriToAliasMap = new Dictionary();
///
/// Tracks extension aliases and Type URIs assigned to them.
///
private Dictionary aliasToTypeUriMap = new Dictionary();
///
/// Gets the aliases that have been set.
///
public IEnumerable Aliases {
get { return this.aliasToTypeUriMap.Keys; }
}
///
/// Gets an alias assigned for a given Type URI. A new alias is assigned if necessary.
///
/// The type URI.
/// The alias assigned to this type URI. Never null.
public string GetAlias(string typeUri) {
Requires.NotNullOrEmpty(typeUri, "typeUri");
string alias;
return this.typeUriToAliasMap.TryGetValue(typeUri, out alias) ? alias : this.AssignNewAlias(typeUri);
}
///
/// Sets an alias and the value that will be returned by .
///
/// The alias.
/// The type URI.
public void SetAlias(string alias, string typeUri) {
Requires.NotNullOrEmpty(alias, "alias");
Requires.NotNullOrEmpty(typeUri, "typeUri");
this.aliasToTypeUriMap.Add(alias, typeUri);
this.typeUriToAliasMap.Add(typeUri, alias);
}
///
/// Takes a sequence of type URIs and assigns aliases for all of them.
///
/// The type URIs to create aliases for.
/// An optional dictionary of URI/alias pairs that suggest preferred aliases to use if available for certain type URIs.
public void AssignAliases(IEnumerable typeUris, IDictionary preferredTypeUriToAliases) {
Requires.NotNull(typeUris, "typeUris");
// First go through the actually used type URIs and see which ones have matching preferred aliases.
if (preferredTypeUriToAliases != null) {
foreach (string typeUri in typeUris) {
if (this.typeUriToAliasMap.ContainsKey(typeUri)) {
// this Type URI is already mapped to an alias.
continue;
}
string preferredAlias;
if (preferredTypeUriToAliases.TryGetValue(typeUri, out preferredAlias) && !this.IsAliasUsed(preferredAlias)) {
this.SetAlias(preferredAlias, typeUri);
}
}
}
// Now go through the whole list again and assign whatever is left now that the preferred ones
// have gotten their picks where available.
foreach (string typeUri in typeUris) {
if (this.typeUriToAliasMap.ContainsKey(typeUri)) {
// this Type URI is already mapped to an alias.
continue;
}
this.AssignNewAlias(typeUri);
}
}
///
/// Sets up aliases for any Type URIs in a dictionary that do not yet have aliases defined,
/// and where the given preferred alias is still available.
///
/// A dictionary of type URI keys and alias values.
public void SetPreferredAliasesWhereNotSet(IDictionary preferredTypeUriToAliases) {
Requires.NotNull(preferredTypeUriToAliases, "preferredTypeUriToAliases");
foreach (var pair in preferredTypeUriToAliases) {
if (this.typeUriToAliasMap.ContainsKey(pair.Key)) {
// type URI is already mapped
continue;
}
if (this.aliasToTypeUriMap.ContainsKey(pair.Value)) {
// alias is already mapped
continue;
}
// The type URI and alias are as yet unset, so go ahead and assign them.
this.SetAlias(pair.Value, pair.Key);
}
}
///
/// Gets the Type Uri encoded by a given alias.
///
/// The alias.
/// The Type URI.
/// Thrown if the given alias does not have a matching TypeURI.
public string ResolveAlias(string alias) {
Requires.NotNullOrEmpty(alias, "alias");
string typeUri = this.TryResolveAlias(alias);
if (typeUri == null) {
throw new ArgumentOutOfRangeException("alias");
}
return typeUri;
}
///
/// Gets the Type Uri encoded by a given alias.
///
/// The alias.
/// The Type URI for the given alias, or null if none for that alias exist.
public string TryResolveAlias(string alias) {
Requires.NotNullOrEmpty(alias, "alias");
string typeUri = null;
this.aliasToTypeUriMap.TryGetValue(alias, out typeUri);
return typeUri;
}
///
/// Returns a value indicating whether an alias has already been assigned to a type URI.
///
/// The alias in question.
/// True if the alias has already been assigned. False otherwise.
public bool IsAliasUsed(string alias) {
Requires.NotNullOrEmpty(alias, "alias");
return this.aliasToTypeUriMap.ContainsKey(alias);
}
///
/// Determines whether a given TypeURI has an associated alias assigned to it.
///
/// The type URI.
///
/// true if the given type URI already has an alias assigned; false otherwise.
///
public bool IsAliasAssignedTo(string typeUri) {
Requires.NotNull(typeUri, "typeUri");
return this.typeUriToAliasMap.ContainsKey(typeUri);
}
///
/// Assigns a new alias to a given Type URI.
///
/// The type URI to assign a new alias to.
/// The newly generated alias.
private string AssignNewAlias(string typeUri) {
Requires.NotNullOrEmpty(typeUri, "typeUri");
ErrorUtilities.VerifyInternal(!this.typeUriToAliasMap.ContainsKey(typeUri), "Oops! This type URI already has an alias!");
string alias = string.Format(CultureInfo.InvariantCulture, AliasFormat, this.typeUriToAliasMap.Count + 1);
this.typeUriToAliasMap.Add(typeUri, alias);
this.aliasToTypeUriMap.Add(alias, typeUri);
return alias;
}
}
}