Files
sqltoolsservice/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/NodePathGenerator.cs

265 lines
8.7 KiB
C#

//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
{
public class NodePathGenerator
{
private static ServerExplorerTree TreeRoot { get; set; }
private static Dictionary<string, HashSet<Node>> NodeTypeDictionary { get; set; }
internal static void Initialize()
{
if (TreeRoot != null)
{
return;
}
var assembly = typeof(ObjectExplorerService).Assembly;
var resource = assembly.GetManifestResourceStream("Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel.TreeNodeDefinition.xml");
var serializer = new XmlSerializer(typeof(ServerExplorerTree));
NodeTypeDictionary = new Dictionary<string, HashSet<Node>>();
using (var reader = new StreamReader(resource))
{
TreeRoot = (ServerExplorerTree)serializer.Deserialize(reader);
}
foreach (var node in TreeRoot.Nodes)
{
var containedType = node.ContainedType();
if (containedType != null && node.Label() != string.Empty)
{
if (!NodeTypeDictionary.ContainsKey(containedType))
{
NodeTypeDictionary.Add(containedType, new HashSet<Node>());
}
NodeTypeDictionary.GetValueOrDefault(containedType).Add(node);
}
}
var serverNode = TreeRoot.Nodes.FirstOrDefault(node => node.Name == "Server");
var serverSet = new HashSet<Node>();
serverSet.Add(serverNode);
NodeTypeDictionary.Add("Server", serverSet);
}
internal static HashSet<string> FindNodePaths(ObjectExplorerSession objectExplorerSession, string typeName, string schema, string name, string databaseName, List<string> parentNames = null)
{
if (TreeRoot == null)
{
Initialize();
}
var returnSet = new HashSet<string>();
var matchingNodes = NodeTypeDictionary.GetValueOrDefault(typeName);
if (matchingNodes == null)
{
return returnSet;
}
var path = name;
if (schema != null)
{
path = schema + "." + path;
}
path ??= "";
foreach (var matchingNode in matchingNodes)
{
var paths = GenerateNodePath(objectExplorerSession, matchingNode, databaseName, parentNames, path);
foreach (var newPath in paths)
{
returnSet.Add(newPath);
}
}
return returnSet;
}
private static HashSet<string> GenerateNodePath(ObjectExplorerSession objectExplorerSession, Node currentNode, string databaseName, List<string> parentNames, string path)
{
if (parentNames != null)
{
parentNames = parentNames.ToList();
}
if (currentNode.Name == "Server" || (currentNode.Name == "Database" && objectExplorerSession.Root.NodeType == "Database"))
{
var serverRoot = objectExplorerSession.Root;
if (objectExplorerSession.Root.NodeType == "Database")
{
serverRoot = objectExplorerSession.Root.Parent;
path = objectExplorerSession.Root.NodeValue + (path.Length > 0 ? ("/" + path) : "");
}
path = serverRoot.NodeValue + (path.Length > 0 ? ("/" + path) : "");
var returnSet = new HashSet<string>();
returnSet.Add(path);
return returnSet;
}
var currentLabel = currentNode.Label();
if (currentLabel != string.Empty)
{
path = currentLabel + "/" + path;
var returnSet = new HashSet<string>();
foreach (var parent in currentNode.ParentNodes())
{
var paths = GenerateNodePath(objectExplorerSession, parent, databaseName, parentNames, path);
foreach (var newPath in paths)
{
returnSet.Add(newPath);
}
}
return returnSet;
}
else
{
var returnSet = new HashSet<string>();
if (currentNode.ContainedType() == "Database")
{
path = databaseName + "/" + path;
}
else if (parentNames != null && parentNames.Count > 0)
{
var parentName = parentNames.Last();
parentNames.RemoveAt(parentNames.Count - 1);
path = parentName + "/" + path;
}
else
{
return returnSet;
}
foreach (var parentNode in currentNode.ParentNodes())
{
var newPaths = GenerateNodePath(objectExplorerSession, parentNode, databaseName, parentNames, path);
foreach (var newPath in newPaths)
{
returnSet.Add(newPath);
}
}
return returnSet;
}
}
[XmlRoot("ServerExplorerTree")]
public class ServerExplorerTree
{
[XmlElement("Node", typeof(Node))]
public List<Node> Nodes { get; set; }
public Node GetNode(string name)
{
foreach (var node in this.Nodes)
{
if (node.Name == name)
{
return node;
}
}
return null;
}
}
public class Node
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string LocLabel { get; set; }
[XmlAttribute]
public string TreeNode { get; set; }
[XmlAttribute]
public string NodeType { get; set; }
[XmlElement("Child", typeof(Child))]
public List<Child> Children { get; set; }
public HashSet<Node> ChildFolders()
{
var childSet = new HashSet<Node>();
foreach (var child in this.Children)
{
var node = TreeRoot.GetNode(child.Name);
if (node != null)
{
childSet.Add(node);
}
}
return childSet;
}
public string ContainedType()
{
if (this.TreeNode != null)
{
return this.TreeNode.Replace("TreeNode", "");
}
else if (this.NodeType != null)
{
return this.NodeType;
}
return null;
}
public Node ContainedObject()
{
var containedType = this.ContainedType();
if (containedType == null)
{
return null;
}
var containedNode = TreeRoot.GetNode(containedType);
if (containedNode == this)
{
return null;
}
return containedNode;
}
public string Label()
{
if (this.LocLabel.StartsWith("SR."))
{
return SR.Keys.GetString(this.LocLabel.Remove(0, 3));
}
return string.Empty;
}
public HashSet<Node> ParentNodes()
{
var parentNodes = new HashSet<Node>();
foreach (var node in TreeRoot.Nodes)
{
if (this != node && (node.ContainedType() == this.Name || node.Children.Any(child => child.Name == this.Name)))
{
parentNodes.Add(node);
}
}
return parentNodes;
}
}
public class Child
{
[XmlAttribute]
public string Name { get; set; }
}
}
}