using System;
using System.ComponentModel;
using System.Linq;
namespace Umbraco.Core
{
///
/// Represents an entity identifier.
///
/// An Udi can be fully qualified or "closed" eg umb://document/{guid} or "open" eg umb://document.
[TypeConverter(typeof(UdiTypeConverter))]
public abstract class Udi : IComparable
{
public Uri UriValue { get; }
///
/// Initializes a new instance of the Udi class.
///
/// The entity type part of the identifier.
/// The string value of the identifier.
protected Udi(string entityType, string stringValue)
{
EntityType = entityType;
UriValue = new Uri(stringValue);
}
///
/// Initializes a new instance of the Udi class.
///
/// The uri value of the identifier.
protected Udi(Uri uriValue)
{
EntityType = uriValue.Host;
UriValue = uriValue;
}
///
/// Gets the entity type part of the identifier.
///
public string EntityType { get; private set; }
public int CompareTo(Udi other)
{
return string.Compare(UriValue.ToString(), other.UriValue.ToString(), StringComparison.InvariantCultureIgnoreCase);
}
public override string ToString()
{
// UriValue is created in the ctor and is never null
// use AbsoluteUri here and not ToString else it's not encoded!
return UriValue.AbsoluteUri;
}
///
/// Creates a root Udi for an entity type.
///
/// The entity type.
/// The root Udi for the entity type.
public static Udi Create(string entityType)
{
return UdiParser.GetRootUdi(entityType);
}
///
/// Creates a string Udi.
///
/// The entity type.
/// The identifier.
/// The string Udi for the entity type and identifier.
public static Udi Create(string entityType, string id)
{
if (UdiParser.UdiTypes.TryGetValue(entityType, out var udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
if (string.IsNullOrWhiteSpace(id))
throw new ArgumentException("Value cannot be null or whitespace.", "id");
if (udiType != UdiType.StringUdi)
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have string udis.", entityType));
return new StringUdi(entityType, id);
}
///
/// Creates a Guid Udi.
///
/// The entity type.
/// The identifier.
/// The Guid Udi for the entity type and identifier.
public static Udi Create(string entityType, Guid id)
{
if (UdiParser.UdiTypes.TryGetValue(entityType, out var udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
if (udiType != UdiType.GuidUdi)
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have guid udis.", entityType));
if (id == default(Guid))
throw new ArgumentException("Cannot be an empty guid.", "id");
return new GuidUdi(entityType, id);
}
public static Udi Create(Uri uri)
{
// if it's a know type go fast and use ctors
// else fallback to parsing the string (and guess the type)
if (UdiParser.UdiTypes.TryGetValue(uri.Host, out var udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", uri.Host), "uri");
if (udiType == UdiType.GuidUdi)
return new GuidUdi(uri);
if (udiType == UdiType.StringUdi)
return new StringUdi(uri);
throw new ArgumentException(string.Format("Uri \"{0}\" is not a valid udi.", uri));
}
public void EnsureType(params string[] validTypes)
{
if (validTypes.Contains(EntityType) == false)
throw new Exception(string.Format("Unexpected entity type \"{0}\".", EntityType));
}
///
/// Gets a value indicating whether this Udi is a root Udi.
///
/// A root Udi points to the "root of all things" for a given entity type, e.g. the content tree root.
public abstract bool IsRoot { get; }
///
/// Ensures that this Udi is not a root Udi.
///
/// This Udi.
/// When this Udi is a Root Udi.
public Udi EnsureNotRoot()
{
if (IsRoot) throw new Exception("Root Udi.");
return this;
}
public override bool Equals(object obj)
{
var other = obj as Udi;
return other != null && GetType() == other.GetType() && UriValue == other.UriValue;
}
public override int GetHashCode()
{
return UriValue.GetHashCode();
}
public static bool operator ==(Udi udi1, Udi udi2)
{
if (ReferenceEquals(udi1, udi2)) return true;
if ((object)udi1 == null || (object)udi2 == null) return false;
return udi1.Equals(udi2);
}
public static bool operator !=(Udi udi1, Udi udi2)
{
return (udi1 == udi2) == false;
}
}
}