#region Disclaimer / License // Copyright (C) 2009, Kenneth Skovhede // http://www.hexad.dk, opensource@hexad.dk // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #endregion using System; using System.Collections.Generic; using System.Text; namespace OSGeo.MapGuide.MaestroAPI { /// <summary> /// This class contains all the required code for maintaining resource identifiers. /// It has implicit conversions to and from a string, which makes it much easier to use. /// It has both static methods that operate on strings, as well as a class that can be manipulated. /// </summary> public class ResourceIdentifier { /// <summary> /// The actual ResourceID /// </summary> private string m_id; /// <summary> /// Constructs a new ResourceIdentifier with the given full path /// </summary> /// <param name="resourceId">The path of the resource to refence</param> public ResourceIdentifier(string resourceId) { m_id = resourceId; } /// <summary> /// Constructs a new ResourceIdentifier, based on an existing one. /// </summary> /// <param name="id">The resource identifier to copy</param> public ResourceIdentifier(ResourceIdentifier id) { m_id = id.m_id; } /// <summary> /// Constructs a new library based resource identifier /// </summary> /// <param name="name">The name of the resource, may include path information with the \"/\" character</param> /// <param name="type">The type of resource the identifier names</param> public ResourceIdentifier(string name, ResourceTypes type) { if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name"); if (name.IndexOf(".") > 0 || name.IndexOf("//") > 0 || name.IndexOf(":") > 0) throw new ArgumentException("The resource name must not contain ':', \"//\" or '.'", "name"); if (!Enum.IsDefined(typeof(ResourceTypes), type)) throw new ArgumentException("The type given was not a valid ResourceType", "type"); m_id = "Library://" + name + EnumHelper.ResourceName(type, true); } /// <summary> /// Constructs a new session based resource identifier /// </summary> /// <param name="name">The name of the resource, may include path information with the \"/\" character</param> /// <param name="type">The type of resource the identifier names</param> /// <param name="sessionId">The session id to use</param> public ResourceIdentifier(string name, ResourceTypes type, string sessionId) : this(name, type) { this.ConvertToSession(sessionId); } /// <summary> /// Gets a value indicating if the resource is blank /// </summary> public bool IsEmpty { get { return string.IsNullOrEmpty(m_id); } } /// <summary> /// Gets or sets the name of the resource /// </summary> public string Name { get { return GetName(m_id); } set { m_id = SetName(m_id, value); } } /// <summary> /// Gets or sets the name and extension of the resource /// </summary> public string Fullname { get { return GetFullname(m_id); } set { m_id = SetName(m_id, value); } } /// <summary> /// Gets or sets the extension of the resourceId /// </summary> public string Extension { get { return GetExtension(m_id); } set { m_id = SetExtension(m_id, value); } } /// <summary> /// Gets the full path of the resource, that is the path without repository information /// </summary> public string Fullpath { get { return GetFullpath(m_id); } set { m_id = SetPath(m_id, value); } } /// <summary> /// Gets the path of the resource, that is the path without repository information and no extension /// </summary> public string Path { get { return GetPath(m_id); } set { m_id = SetPath(m_id, value); } } /// <summary> /// Gets or sets the path to the resource, including the repository /// </summary> public string RepositoryPath { get { return GetRepositoryPath(m_id); } set { m_id = SetRepositoryPath(m_id, value); } } /// <summary> /// Gets a value indicating if the resource is in the library repository /// </summary> public bool IsInLibrary { get { return GetRepository(m_id) == "Library://"; } } /// <summary> /// Gets a value indicating if the resource is in the session repository /// </summary> public bool IsInSessionRepository { get { return !this.IsInLibrary; } } /// <summary> /// Converts this instance to be in the library repository /// </summary> public void ConvertToLibrary() { m_id = ResourceIdentifier.ConvertToLibrary(m_id); } /// <summary> /// Converts this instance to be in the session repository /// </summary> /// <param name="sessionId">The sessionid</param> public void ConvertToSession(string sessionId) { m_id = ResourceIdentifier.ConvertToSession(m_id, sessionId); } /// <summary> /// Helper operator that makes using the resource identifiers easier /// </summary> /// <param name="id">The id to convert to a string</param> /// <returns>The converted string</returns> public static implicit operator string(ResourceIdentifier id) { return id == null ? null : id.m_id; } /// <summary> /// Helper operator that makes using the resource identifiers easier /// </summary> /// <param name="id">The id to convert into a resource indetifier class</param> /// <returns>The resource identifier</returns> public static implicit operator ResourceIdentifier(string id) { return new ResourceIdentifier(id); } /// <summary> /// Returns the full resource id as a string /// </summary> /// <returns>The full resource id as a string</returns> public override string ToString() { return m_id; } /// <summary> /// Gets the length of the resource identifier as a string /// </summary> public int Length { get { return m_id == null ? 0 : m_id.Length; } } /// <summary> /// Gets or sets the full resource identifier /// </summary> public string ResourceId { get { return m_id; } set { m_id = value; } } /// <summary> /// Gets a value indicating if the resource identifier points to a folder /// </summary> public bool IsFolder { get { return ResourceIdentifier.IsFolderResource(m_id); } } /// <summary> /// Gets a value indicating if the resource identifier is valid /// </summary> public bool IsValid { get { return ResourceIdentifier.Validate(m_id); } } /// <summary> /// Normalizes the identifier, that is prepends a slash if the identifier points to a folder /// </summary> public void Normalize() { m_id = ResourceIdentifier.Normalize(m_id); } /// <summary> /// Gets the containing folder path for the resource, including the repository /// </summary> public string ParentFolder { get { return ResourceIdentifier.GetParentFolder(m_id); } } #region Static handlers /// <summary> /// Gets the name of a resource, given its identifier /// </summary> /// <param name="identifier">The identifier to look for</param> /// <returns>The name of the resource</returns> public static string GetName(string identifier) { if (string.IsNullOrEmpty(identifier)) throw new ArgumentNullException("identifier"); string temp = GetPath(identifier); if (string.IsNullOrEmpty(temp)) throw new ArgumentException("The value must be a resource identifier", "identifier"); return temp.Substring(temp.LastIndexOf("/") + 1); } /// <summary> /// Sets the name of the resource, with or without the extension /// </summary> /// <param name="identifier">The identifier to give a new name</param> /// <param name="newname">The new name to assign</param> /// <returns>The renamed identifier</returns> public static string SetName(string identifier, string newname) { string temp = GetPath(identifier); if (identifier.EndsWith("/")) { if (!newname.EndsWith("/")) newname += "/"; } else newname += "." + GetExtension(identifier); if (newname.IndexOf("/") > 0) throw new ArgumentException("The new name must not contain the \"/\" character", "newname"); temp = temp.Substring(0, temp.Length - GetName(identifier).Length) + newname; return GetRepository(identifier) + temp; } /// <summary> /// Sets the path of the identifier, with or without the extension /// </summary> /// <param name="identifier">The identifier to update</param> /// <param name="newpath">The new path to user, with or without the extension</param> /// <returns>The new identifier</returns> public static string SetPath(string identifier, string newpath) { string temp = GetPath(identifier); if (!identifier.EndsWith("/")) newpath += "." + GetExtension(identifier); return GetRepository(identifier) + newpath + (identifier.EndsWith("/") ? "/" : ""); } /// <summary> /// Changes the extension of the given resource /// </summary> /// <param name="identifier">The identifier to change the extension for</param> /// <param name="newextension">The new extension to use</param> /// <returns>The renmaed identifier</returns> public static string SetExtension(string identifier, string newextension) { if (identifier.EndsWith("/")) throw new Exception("Cannot change extension for a folder"); if (!newextension.StartsWith(".")) newextension = "." + newextension; if (newextension.LastIndexOf(".") > 0) throw new ArgumentException("The supplied extension is invalid", "newextension"); return identifier.Substring(0, identifier.Length - GetExtension(identifier).Length - 1) + newextension; } /// <summary> /// Gets the repository part of a resource identifier, eg.: "Library://" or "Session:xxxx//" /// </summary> /// <param name="identifier"></param> /// <returns></returns> public static string GetRepository(string identifier) { if (string.IsNullOrEmpty(identifier)) throw new ArgumentNullException("identifier"); int ix = identifier.IndexOf("//"); if (ix <= 0) throw new ArgumentException("The value must be a resource identifier", "identifier"); string repo = identifier.Substring(0, ix); if (repo != "Library:" && !repo.StartsWith("Session:")) throw new ArgumentException("The value must be a resource identifier", "identifier"); return repo + "//"; } /// <summary> /// Returns the full path of the resource, that is the resourceId without the repository information /// </summary> /// <param name="identifier">The identifier to get the path from</param> /// <returns>The path of the identifier</returns> public static string GetFullpath(string identifier) { if (string.IsNullOrEmpty(identifier)) throw new ArgumentNullException("identifier"); return identifier.Substring(GetRepository(identifier).Length); } /// <summary> /// Returns the path of the resource, that is the resourceId without the repository information and extension /// </summary> /// <param name="identifier">The identifier to get the path from</param> /// <returns>The path of the identifier</returns> public static string GetPath(string identifier) { if (string.IsNullOrEmpty(identifier)) throw new ArgumentNullException("identifier"); return identifier.Substring(GetRepository(identifier).Length, identifier.Length - GetExtension(identifier).Length - GetRepository(identifier).Length - 1); } /// <summary> /// Returns the extension of a resource identifier /// </summary> /// <param name="identifier">The identifier to get the extension from</param> /// <returns>The extension of the identifier</returns> public static string GetExtension(string identifier) { if (string.IsNullOrEmpty(identifier)) throw new ArgumentNullException("identifier"); if (identifier.EndsWith("/")) return ""; int ix = identifier.LastIndexOf("."); if (ix <= 0) throw new ArgumentException("The value must be a resource identifier", "identifier"); return identifier.Substring(ix + 1); } /// <summary> /// Converts a resource id to be placed in the library /// </summary> /// <param name="identifier">The identifier to convert</param> /// <returns>The converted identifier</returns> public static string ConvertToLibrary(string identifier) { return "Library://" + identifier.Substring(GetRepository(identifier).Length); } /// <summary> /// Converts a resource id to be placed in the library /// </summary> /// <param name="identifier">The identifier to convert</param> /// <param name="sessionId">The session id of the repository it should be placed in</param> /// <returns>The converted identifier</returns> public static string ConvertToSession(string identifier, string sessionId) { return "Session:" + sessionId + "//" + identifier.Substring(GetRepository(identifier).Length); } /// <summary> /// Gets the name and extension of the identifier /// </summary> /// <param name="identifier">The identifier to extract the information from</param> /// <returns>The full name of the identifier</returns> public static string GetFullname(string identifier) { if (identifier.EndsWith("/")) return GetName(identifier); else return GetName(identifier) + "." + GetExtension(identifier); } /// <summary> /// Determines if a resource identifier is valid /// </summary> /// <param name="identifier">The identifier to validate</param> /// <returns>A value indicating if the identifier is valid</returns> public static bool Validate(string identifier) { try { GetRepository(identifier); if (identifier.IndexOf(".") < 0 && !identifier.EndsWith("/")) return false; } catch { return false; } return true; } /// <summary> /// Returns a value indicating if the resource points to a folder /// </summary> /// <param name="identifier">The identifier to evaluate</param> /// <returns>A value indicating if the resource points to a folder</returns> public static bool IsFolderResource(string identifier) { return identifier.EndsWith("/"); } /// <summary> /// Normalizes a identifier, that is prepends a slash if it is a folder resource /// </summary> /// <param name="identifier">The identifier to normalize</param> /// <returns>The normalized identifier</returns> public static string Normalize(string identifier) { if (identifier.LastIndexOf(".") <= identifier.LastIndexOf("/") && !identifier.EndsWith("/")) return identifier + "/"; else return identifier; } /// <summary> /// Determines if a resource identifier is valid and of the desired type /// </summary> /// <param name="identifier">The identifier to validate</param> /// <param name="type">The type the resource identifer must be</param> /// <returns>A value indicating if the identifier is valid</returns> public static bool Validate(string identifier, ResourceTypes type) { if (!Validate(identifier)) return false; if (type == ResourceTypes.Folder) return IsFolderResource(identifier); else return EnumHelper.ResourceName(type) == GetExtension(identifier); } /// <summary> /// Returns the path that contains the resource, including the repository /// </summary> /// <param name="identifier">The resource identifier to use</param> /// <returns>The folder for the identifier</returns> public static string GetRepositoryPath(string identifier) { if (!Validate(identifier)) throw new Exception("Invalid resource id: " + identifier); identifier = Normalize(identifier); return identifier.Substring(0, identifier.LastIndexOf("/", identifier.Length)) + "/"; } /// <summary> /// Sets the path including the repository to the given value /// </summary> /// <param name="identifier">The identifier to change the folder for</param> /// <param name="folder">The new folder</param> /// <returns>An identifier in the new folder</returns> public static string SetRepositoryPath(string identifier, string folder) { if (!folder.StartsWith("Library:") && !folder.StartsWith("Session:")) { string res = identifier.EndsWith("/") ? "" : GetFullname(identifier); string repo = GetRepository(identifier); if (!folder.EndsWith("/") && !string.IsNullOrEmpty(folder)) folder += "/"; return repo + folder + res; } else if (GetExtension(identifier) == "") { if (!folder.EndsWith("/")) folder += "/"; return folder; } else { if (!folder.EndsWith("/")) folder += "/"; return folder + GetFullname(identifier); } } public static string GetParentFolder(string identifier) { if (!Validate(identifier)) throw new Exception("Invalid resource id: " + identifier); identifier = Normalize(identifier); if (identifier == GetRepository(identifier)) return identifier; if (identifier.EndsWith("/")) identifier = identifier.Remove(identifier.Length - 1); identifier = identifier.Remove(identifier.LastIndexOf("/") + 1); return identifier; } #endregion } }