using System; using System.Collections.Concurrent; using System.Diagnostics; using Umbraco.Core.Services; namespace Umbraco.Core.Models { [DebuggerDisplay("Tree - {Title} ({ApplicationAlias})")] public class ApplicationTree { private static readonly ConcurrentDictionary ResolvedTypes = new ConcurrentDictionary(); /// /// Initializes a new instance of the class. /// public ApplicationTree() { } /// /// Initializes a new instance of the class. /// /// if set to true [initialize]. /// The sort order. /// The application alias. /// The tree alias. /// The tree title. /// The icon closed. /// The icon opened. /// The tree type. public ApplicationTree(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) { Initialize = initialize; SortOrder = sortOrder; ApplicationAlias = applicationAlias; Alias = alias; Title = title; IconClosed = iconClosed; IconOpened = iconOpened; Type = type; } /// /// Gets or sets a value indicating whether this should initialize. /// /// true if initialize; otherwise, false. public bool Initialize { get; set; } /// /// Gets or sets the sort order. /// /// The sort order. public int SortOrder { get; set; } /// /// Gets the application alias. /// /// The application alias. public string ApplicationAlias { get; } /// /// Gets the tree alias. /// /// The alias. public string Alias { get; } /// /// Gets or sets the tree title. /// /// The title. public string Title { get; set; } /// /// Gets or sets the icon closed. /// /// The icon closed. public string IconClosed { get; set; } /// /// Gets or sets the icon opened. /// /// The icon opened. public string IconOpened { get; set; } /// /// Gets or sets the tree type assembly name. /// /// The type. public string Type { get; set; } /// /// Returns the localized root node display name /// /// /// public string GetRootNodeDisplayName(ILocalizedTextService textService) { var label = $"[{Alias}]"; // try to look up a the localized tree header matching the tree alias var localizedLabel = textService.Localize("treeHeaders/" + Alias); // if the localizedLabel returns [alias] then return the title attribute from the trees.config file, if it's defined if (localizedLabel != null && localizedLabel.Equals(label, StringComparison.InvariantCultureIgnoreCase)) { if (string.IsNullOrEmpty(Title) == false) label = Title; } else { // the localizedLabel translated into something that's not just [alias], so use the translation label = localizedLabel; } return label; } private Type _runtimeType; /// /// Returns the CLR type based on it's assembly name stored in the config /// /// public Type GetRuntimeType() { return _runtimeType ?? (_runtimeType = System.Type.GetType(Type)); } /// /// Used to try to get and cache the tree type /// /// /// internal static Type TryGetType(string type) { try { return ResolvedTypes.GetOrAdd(type, s => { var result = System.Type.GetType(type); if (result != null) { return result; } //we need to implement a bit of a hack here due to some trees being renamed and backwards compat var parts = type.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 2) throw new InvalidOperationException("Could not resolve type"); if (parts[1].Trim() != "Umbraco.Web" || parts[0].StartsWith("Umbraco.Web.Trees") == false || parts[0].EndsWith("Controller")) throw new InvalidOperationException("Could not resolve type"); //if it's one of our controllers but it's not suffixed with "Controller" then add it and try again var tempType = parts[0] + "Controller, Umbraco.Web"; result = System.Type.GetType(tempType); if (result != null) return result; throw new InvalidOperationException("Could not resolve type"); }); } catch (InvalidOperationException) { //swallow, this is our own exception, couldn't find the type // fixme bad use of exceptions here! return null; } } } }