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; } } }