#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; using OSGeo.MapGuide.MaestroAPI; using OSGeo.MapGuide.Maestro.ResourceEditors; using System.Windows.Forms; namespace OSGeo.MapGuide.Maestro.ResourceBrowser { /// /// This class stores a local copy of all loaded resources in a tree like structure /// public class RepositoryCache { private ServerConnectionI m_connection; public ServerConnectionI Connection { get { return m_connection; } set { m_connection = value; Reset(); } } /// /// The library root /// private ResourceFolder m_root = null; private Dictionary m_folders; private ResourceEditorMap m_editors; /// /// The editor map has images and various helper functions /// public ResourceEditorMap EditorMap { get { return m_editors; } } /// /// This marker is used on treenodes to indicate that the parent node has not loaded /// public static readonly object NOT_LOADED_MARKER = new object(); /// /// An event that is triggered when the cache is reset /// public event EventHandler CacheResetEvent; public RepositoryCache(ServerConnectionI connection, ResourceEditorMap editors) { m_connection = connection; m_editors = editors; } /// /// Reset the current cache contents, reloading anything from the server again /// public void Reset() { ResourceListResourceFolder tmp = new ResourceListResourceFolder(); tmp.ResourceId = "Library://"; m_root = new ResourceFolder(this, tmp); m_folders = new Dictionary(); RegisterFolder(m_root); if (CacheResetEvent != null) CacheResetEvent(this, new EventArgs()); } /// /// Builds a treeview with nodes /// /// The tree to update with new nodes public void BuildTree(TreeView tree) { tree.Nodes.Clear(); TreeNode rootnode = new TreeNode(m_connection.DisplayName, m_editors.ServerIcon, m_editors.ServerIcon); tree.Nodes.Add(rootnode); TreeNode dummy = new TreeNode("dummy"); dummy.Tag = NOT_LOADED_MARKER; rootnode.Nodes.Add(dummy); if (m_root == null) Reset(); rootnode.Expand(); if (rootnode.Nodes.Count == 1 && rootnode.Nodes[0] == dummy) BuildNode(rootnode, false); } /// /// Registers the folder as loaded for quick lookup /// /// The loaded folder private void RegisterFolder(ResourceFolder folder) { m_folders[folder.ResourceId] = folder; } /// /// Unregisters the folder as loaded /// /// The unloaded folder private void UnregisterFolder(ResourceFolder folder) { m_folders.Remove(folder.ResourceId); } /// /// Builds the childnodes of a node /// /// The node to update /// True to re-read from the server, false to allow usage of the cache, if avalible public void BuildNode(TreeNode node, bool forceRebuild) { ResourceFolder folder = FindFolder(node); if (forceRebuild || !folder.IsLoaded) folder.ReloadContents(); folder.RebuildNode(node); } /// /// Gets a list of documents present at the current node /// /// The treenode to return the documents for /// A list of documents at the present node public List GetDocuments(TreeNode node) { return FindFolder(node).Documents; } /// /// Gets a list of documents present at the current node /// /// The resourceId to return the documents for /// A list of documents at the present node public List GetDocuments(string resId) { return FindFolder(resId).Documents; } private ResourceFolder FindFolder(TreeNode node) { string resId = null; ; if (node.Parent == null) resId = "Library://"; else if (node.Tag is ResourceListResourceFolder) resId = (node.Tag as ResourceListResourceFolder).ResourceId; return FindFolder(resId); } private ResourceFolder FindFolder(string resId) { if (!string.IsNullOrEmpty(resId)) { if (m_folders.ContainsKey(resId)) return m_folders[resId]; else throw new Exception(Strings.RepositoryCache.UnknownNodeInternalError); } else throw new Exception(Strings.RepositoryCache.InvalidNodeInternalError); } /// /// Helper function to determine if the folder exists, trying to determine by cache use, then fallback to query the server. /// /// The resource to determine existance for /// A value indicating if the folder exists public bool FolderExists(string resId) { if (m_folders.ContainsKey(resId)) return true; else if (m_folders.ContainsKey(new ResourceIdentifier(resId).ParentFolder)) { ResourceFolder f = m_folders[new ResourceIdentifier(resId).ParentFolder]; if (f.IsLoaded) return false; else { f.ReloadContents(); return m_folders.ContainsKey(resId); } } return m_connection.HasFolder(resId); } /// /// Helper function to determine if the resource document exists, trying to determine by cache use, then fallback to query the server. /// /// The resource to determine existance for /// A value indicating if the resource document exists public bool ResourceExists(string resId) { string parentFolder = new ResourceIdentifier(resId).ParentFolder; if (m_folders.ContainsKey(parentFolder)) { ResourceFolder f = m_folders[parentFolder]; foreach (ResourceListResourceDocument doc in f.Documents) if (doc.ResourceId == resId) return true; return false; } else return m_connection.ResourceExists(resId); } private class ResourceFolder { RepositoryCache m_parent; private ResourceListResourceFolder m_item; private List m_documents = null; private List m_folders = null; public List Documents { get { if (m_documents == null) ReloadContents(); return m_documents; } } public ResourceFolder(RepositoryCache parent, ResourceListResourceFolder item) { m_parent = parent; m_item = item; } public void ReloadContents() { if (m_folders != null) foreach (ResourceFolder f in m_folders) f.Unload(); m_documents = new List(); m_folders = new List(); foreach (object o in m_parent.Connection.GetRepositoryResources(m_item.ResourceId, null, 1, false).Items) if (o is ResourceListResourceFolder) m_folders.Add(new ResourceFolder(m_parent, o as ResourceListResourceFolder)); else if (o is ResourceListResourceDocument) m_documents.Add(o as ResourceListResourceDocument); foreach (ResourceFolder f in m_folders) m_parent.RegisterFolder(f); } public void Unload() { if (m_folders != null) foreach (ResourceFolder f in m_folders) f.Unload(); m_parent.UnregisterFolder(this); } public void RebuildNode(TreeNode node) { if (m_folders == null) ReloadContents(); node.Nodes.Clear(); foreach (ResourceFolder folder in m_folders) { TreeNode n = new TreeNode(); n.Text = m_parent.EditorMap.GetResourceNameFromResourceID(folder.ResourceId); n.Tag = folder.m_item; n.ImageIndex = n.SelectedImageIndex = m_parent.EditorMap.FolderIcon; n.ToolTipText = string.Format(Strings.RepositoryCache.ResourceTooltip, new MaestroAPI.ResourceIdentifier(folder.ResourceId.Substring(0, folder.ResourceId.Length - 1) + ".Folder").Name, Strings.RepositoryCache.FolderName, folder.m_item.CreatedDate.ToString(System.Globalization.CultureInfo.CurrentUICulture), folder.m_item.ModifiedDate.ToString(System.Globalization.CultureInfo.CurrentUICulture)); TreeNode marker = new TreeNode("dummy"); marker.Tag = NOT_LOADED_MARKER; n.Nodes.Add(marker); node.Nodes.Add(n); } if (node.TreeView is ResourceTree && (node.TreeView as ResourceTree).HideDocuments) return; foreach (ResourceListResourceDocument document in m_documents) { TreeNode n = new TreeNode(); n.Text = m_parent.EditorMap.GetResourceNameFromResourceID(document.ResourceId); n.Tag = document; n.ImageIndex = n.SelectedImageIndex = m_parent.EditorMap.GetImageIndexFromResourceID(document.ResourceId); n.ToolTipText = string.Format(Strings.RepositoryCache.ResourceTooltip, new MaestroAPI.ResourceIdentifier(document.ResourceId).Name, new MaestroAPI.ResourceIdentifier(document.ResourceId).Extension, document.CreatedDate.ToString(System.Globalization.CultureInfo.CurrentUICulture), document.ModifiedDate.ToString(System.Globalization.CultureInfo.CurrentUICulture)); if (new MaestroAPI.ResourceIdentifier(document.ResourceId).Extension == "LayerDefinition" || new MaestroAPI.ResourceIdentifier(document.ResourceId).Extension == "FeatureSource") { bool published = false; string serviceType = new MaestroAPI.ResourceIdentifier(document.ResourceId).Extension == "LayerDefinition" ? "WMS" : "WFS"; if (document.ResourceDocumentHeader != null && document.ResourceDocumentHeader.Metadata != null && document.ResourceDocumentHeader.Metadata.Simple != null && document.ResourceDocumentHeader.Metadata.Simple.Property["_IsPublished"] == "1") published = true; n.ToolTipText += "\r\n" + string.Format(Strings.RepositoryCache.PublishedTooltip, serviceType, published); } node.Nodes.Add(n); } } public string Tooltip { get { return ""; } } public string Name { get { return ""; } } public string ResourceId { get { return m_item.ResourceId; } } public bool IsLoaded { get { return m_folders != null; } } } } }