mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-20 09:35:38 -05:00
393 lines
12 KiB
Plaintext
393 lines
12 KiB
Plaintext
<#@ template debug="false" hostspecific="true" language="C#" #>
|
|
<#@ output extension=".cs" #>
|
|
<#@ assembly name="System.Xml.dll" #>
|
|
<#@ import namespace="System" #>
|
|
<#@ import namespace="System.Globalization" #>
|
|
<#@ import namespace="System.Text" #>
|
|
<#@ import namespace="System.Xml" #>
|
|
<#@ import namespace="System.Collections.Generic" #>
|
|
<#@ import namespace="System.IO" #>
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Composition;
|
|
using Microsoft.SqlTools.ServiceLayer;
|
|
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
|
|
|
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
|
{
|
|
|
|
<#
|
|
var directory = Path.GetDirectoryName(Host.TemplateFile);
|
|
string xmlFile = Path.Combine(directory, "TreeNodeDefinition.xml");
|
|
|
|
/////////
|
|
// TODO - is Generate all the ReverseDependencies needed?
|
|
/////////
|
|
// var allReverseDependencies = GetReverseDependencies(xmlFile);
|
|
// WriteLine(" internal static class TreeNodeRules");
|
|
// WriteLine(" {");
|
|
// WriteLine(" internal static Dictionary<Type, IList<Type>> TypeReverseDependencyMap = new Dictionary<Type, IList<Type>>()");
|
|
// WriteLine(" {");
|
|
// foreach (var reverseDependencyKey in allReverseDependencies.Keys)
|
|
// {
|
|
// bool isFirstDependentType = true;
|
|
// StringBuilder dependentListBuilder = new StringBuilder("{");
|
|
// foreach (var dependentType in allReverseDependencies[reverseDependencyKey])
|
|
// {
|
|
// if (isFirstDependentType)
|
|
// {
|
|
// isFirstDependentType = false;
|
|
// }
|
|
// else
|
|
// {
|
|
// dependentListBuilder.Append(",");
|
|
// }
|
|
//
|
|
// dependentListBuilder.Append(string.Format(CultureInfo.InvariantCulture, " typeof({0})", dependentType));
|
|
// }
|
|
// dependentListBuilder.Append(" }");
|
|
//
|
|
// WriteLine(string.Format(CultureInfo.InvariantCulture, " {{ typeof({0}), new List<Type> {1} }}", reverseDependencyKey, dependentListBuilder.ToString()));
|
|
// }
|
|
// WriteLine(" };");
|
|
// WriteLine(" }");
|
|
// WriteLine("");
|
|
|
|
/////////
|
|
// First generate all the TreeNodes
|
|
/////////
|
|
var allTreeNodes = GetUniqueTreeNodes(xmlFile);
|
|
foreach (var TreeNode in allTreeNodes)
|
|
{
|
|
var name = TreeNode.GetAttribute("Name");
|
|
WriteLine(string.Format(" internal sealed partial class {0} : SmoTreeNode", name));
|
|
WriteLine(" {");
|
|
WriteLine(string.Format(" public {0}() : base()", name));
|
|
WriteLine(" {");
|
|
WriteLine(" NodeValue = string.Empty;");
|
|
WriteLine(string.Format(" this.NodeType = \"{0}\";", name.Replace("TreeNode", string.Empty)));
|
|
WriteLine(string.Format(" this.NodeTypeId = NodeTypes.{0};", name.Replace("TreeNode", string.Empty)));
|
|
WriteLine(" OnInitialize();");
|
|
WriteLine(" }");
|
|
WriteLine(" }");
|
|
WriteLine("");
|
|
}
|
|
|
|
/////////
|
|
// Now generate all the ChildFactories
|
|
/////////
|
|
var allNodes = GetNodes(xmlFile);
|
|
foreach (var type in allNodes)
|
|
{
|
|
XmlElement nodeElement = GetNodeElement(xmlFile, type);
|
|
var imageAttr = nodeElement.GetAttribute("Image");
|
|
var isAlwaysLeaf = nodeElement.GetAttributeNode("IsAlwaysLeaf");
|
|
var baseClass = nodeElement.GetAttribute("BaseClass");
|
|
var strategy = nodeElement.GetAttribute("Strategy");
|
|
var ChildQuerierTypes = nodeElement.GetAttribute("ChildQuerierTypes");
|
|
var TreeNode = nodeElement.GetAttribute("TreeNode");
|
|
var isAsync = nodeElement.GetAttributeNode("IsAsyncLoad");
|
|
var disableSort = nodeElement.GetAttributeNode("DisableSort");
|
|
|
|
string childFactoryBaseClass = "SmoChildFactoryBase";
|
|
|
|
// TODO Will we need alternative child factories? If so, add code here to support this
|
|
|
|
if (isAlwaysLeaf == null)
|
|
{
|
|
WriteLine(" [Export(typeof(ChildFactory))]");
|
|
WriteLine(" [Shared]");
|
|
|
|
WriteLine(string.Format(" internal partial class {0}ChildFactory : {1}", type, childFactoryBaseClass));
|
|
|
|
WriteLine(" {");
|
|
WriteLine(string.Format(" public override IEnumerable<string> ApplicableParents() {{ return new[] {{ \"{0}\" }}; }}", type));
|
|
|
|
List<XmlElement> children = GetChildren(xmlFile, type);
|
|
if (children.Count > 0)
|
|
{
|
|
WriteLine("");
|
|
WriteLine(" protected override void OnExpandPopulateFolders(IList<TreeNode> currentChildren, TreeNode parent)");
|
|
WriteLine(" {");
|
|
foreach (var child in children)
|
|
{
|
|
XmlElement childAsXmlElement = GetNodeElement(xmlFile, child.GetAttribute("Name"));
|
|
if (childAsXmlElement == null)
|
|
{
|
|
// TODO SHould we error with clear message that this needs to be fixed?
|
|
continue;
|
|
}
|
|
string childImage = childAsXmlElement.GetAttribute("Image");
|
|
var msShippedOwned = childAsXmlElement.GetAttributeNode("IsMsShippedOwned");
|
|
var validFor = childAsXmlElement.GetAttribute("ValidFor");
|
|
|
|
if (TreeNodeExists(xmlFile, child.GetAttribute("Name") + "TreeNode"))
|
|
{
|
|
WriteLine(string.Format(" currentChildren.Add(new {0}TreeNode {{ SortPriority = SmoTreeNode.NextSortPriority }} );", child.GetAttribute("Name")));
|
|
}
|
|
else
|
|
{
|
|
WriteLine(" currentChildren.Add(new FolderNode {");
|
|
WriteLine(string.Format(" NodeValue = {0},", childAsXmlElement.GetAttribute("LocLabel")));
|
|
WriteLine(string.Format(" NodeType = \"{0}\",", "Folder"));
|
|
WriteLine(string.Format(" NodeTypeId = NodeTypes.{0},", child.GetAttribute("Name")));
|
|
|
|
if (msShippedOwned != null)
|
|
{
|
|
WriteLine(" IsMsShippedOwned = true,");
|
|
}
|
|
if (!string.IsNullOrWhiteSpace(validFor))
|
|
{
|
|
WriteLine(string.Format(" ValidFor = {0},", GetValidForFlags(validFor)));
|
|
}
|
|
WriteLine(" SortPriority = SmoTreeNode.NextSortPriority,");
|
|
WriteLine(" });");
|
|
}
|
|
}
|
|
WriteLine(" }");
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(strategy))
|
|
{
|
|
string[] allTypes = ChildQuerierTypes.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
|
WriteLine("");
|
|
WriteLine(" internal override Type[] ChildQuerierTypes");
|
|
WriteLine(" {");
|
|
WriteLine(" get");
|
|
WriteLine(" {");
|
|
if (!string.IsNullOrWhiteSpace(ChildQuerierTypes))
|
|
{
|
|
Write(" return new [] {");
|
|
foreach (var typeToRe in allTypes)
|
|
{
|
|
Write(string.Format(" typeof({0}Querier),", typeToRe));
|
|
}
|
|
WriteLine(" };");
|
|
}
|
|
else
|
|
{
|
|
Write(" return new Type[0];");
|
|
}
|
|
WriteLine(" }");
|
|
WriteLine(" }");
|
|
|
|
WriteLine("");
|
|
|
|
WriteLine(" public override TreeNode CreateChild(TreeNode parent, object context)");
|
|
WriteLine(" {");
|
|
if (string.IsNullOrWhiteSpace(TreeNode))
|
|
{
|
|
WriteLine(" var child = new SmoTreeNode();");
|
|
WriteLine(" child.IsAlwaysLeaf = true;");
|
|
if (type.EndsWith("s"))
|
|
{
|
|
var typeName = type.Substring(0, type.Length - 1);
|
|
WriteLine(string.Format(" child.NodeType = \"{0}\";", typeName));
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
var modelNodeChildren = GetNodeElement(xmlFile, TreeNode.Replace("TreeNode",string.Empty));
|
|
WriteLine(string.Format(" var child = new {0}();", TreeNode));
|
|
if (modelNodeChildren.ChildNodes.Count == 0)
|
|
{
|
|
WriteLine(" child.IsAlwaysLeaf = true;");
|
|
}
|
|
}
|
|
if (disableSort != null)
|
|
{
|
|
WriteLine(" child.SortPriority = SmoTreeNode.NextSortPriority;");
|
|
}
|
|
WriteLine(" InitializeChild(child, context);");
|
|
WriteLine(" return child;");
|
|
WriteLine(" }");
|
|
}
|
|
else if (baseClass == "ModelBased")
|
|
{
|
|
WriteLine("");
|
|
WriteLine(" internal override Type[] ChildQuerierTypes { get {return null;} }");
|
|
WriteLine("");
|
|
// TODO Is reverse engineering strategy every needed?
|
|
// WriteLine(" protected override ReverseEngineeringStrategy Strategy { get {return ReverseEngineeringStrategy.None;} }");
|
|
WriteLine("");
|
|
WriteLine(" public override TreeNode CreateChild(TreeNode parent, object context)");
|
|
WriteLine(" {");
|
|
WriteLine(" return null;");
|
|
WriteLine(" }");
|
|
}
|
|
|
|
WriteLine(" }");
|
|
WriteLine("");
|
|
}
|
|
}
|
|
#>
|
|
}
|
|
|
|
<#+
|
|
public static string GetValidForFlags(string validForStr)
|
|
{
|
|
List<string> flags = new List<string>();
|
|
if (validForStr.Contains("Sql2005"))
|
|
{
|
|
flags.Add("ValidForFlag.Sql2005");
|
|
}
|
|
|
|
if (validForStr.Contains("Sql2008"))
|
|
{
|
|
flags.Add("ValidForFlag.Sql2008");
|
|
}
|
|
|
|
if (validForStr.Contains("Sql2012"))
|
|
{
|
|
flags.Add("ValidForFlag.Sql2012");
|
|
}
|
|
|
|
if (validForStr.Contains("Sql2014"))
|
|
{
|
|
flags.Add("ValidForFlag.Sql2014");
|
|
}
|
|
|
|
if (validForStr.Contains("Sql2016"))
|
|
{
|
|
flags.Add("ValidForFlag.Sql2016");
|
|
}
|
|
|
|
if (validForStr.Contains("AzureV11"))
|
|
{
|
|
flags.Add("ValidForFlag.Azure");
|
|
}
|
|
|
|
if (validForStr.Contains("AzureV12"))
|
|
{
|
|
flags.Add("ValidForFlag.AzureV12");
|
|
}
|
|
|
|
if (validForStr.Contains("NotDebugInstance"))
|
|
{
|
|
flags.Add("ValidForFlag.NotDebugInstance");
|
|
}
|
|
|
|
if (validForStr.Contains("NotContainedUser"))
|
|
{
|
|
flags.Add("ValidForFlag.NotContainedUser");
|
|
}
|
|
|
|
if (validForStr.Contains("CanConnectToMaster"))
|
|
{
|
|
flags.Add("ValidForFlag.CanConnectToMaster");
|
|
}
|
|
|
|
if (validForStr.Contains("CanViewSecurity"))
|
|
{
|
|
flags.Add("ValidForFlag.CanViewSecurity");
|
|
}
|
|
|
|
return string.Join("|", flags);
|
|
}
|
|
public static string[] GetNodes(string xmlFile)
|
|
{
|
|
List<string> typesList = new List<string>();
|
|
XmlDocument doc = new XmlDocument();
|
|
doc.Load(xmlFile);
|
|
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/Node");
|
|
if (treeTypes != null)
|
|
{
|
|
foreach (var type in treeTypes)
|
|
{
|
|
XmlElement element = type as XmlElement;
|
|
if (element != null)
|
|
{
|
|
typesList.Add(element.GetAttribute("Name"));
|
|
}
|
|
}
|
|
}
|
|
return typesList.ToArray();
|
|
}
|
|
|
|
public static Dictionary<string, List<string>> GetReverseDependencies(string xmlFile)
|
|
{
|
|
Dictionary<string, List<string>> dependencyMap = new Dictionary<string, List<string>>();
|
|
XmlDocument doc = new XmlDocument();
|
|
doc.Load(xmlFile);
|
|
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/ReverseDependencyList/ReverseDependency");
|
|
if (treeTypes != null)
|
|
{
|
|
foreach (var type in treeTypes)
|
|
{
|
|
XmlElement element = type as XmlElement;
|
|
if (element != null)
|
|
{
|
|
string typeName = element.GetAttribute("Type");
|
|
string dependency = element.GetAttribute("DependsOn");
|
|
List<string> dependenciesForType;
|
|
if (dependencyMap.TryGetValue(typeName, out dependenciesForType))
|
|
{
|
|
dependenciesForType.Add(dependency);
|
|
}
|
|
else
|
|
{
|
|
string[] allDepedencies = dependency.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
|
dependenciesForType = new List<string>();
|
|
dependenciesForType.AddRange(allDepedencies);
|
|
dependencyMap.Add(typeName, dependenciesForType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return dependencyMap;
|
|
}
|
|
|
|
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
|
|
{
|
|
XmlDocument doc = new XmlDocument();
|
|
doc.Load(xmlFile);
|
|
return (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/Node[@Name='{0}']", nodeName));
|
|
}
|
|
|
|
public static bool TreeNodeExists(string xmlFile, string TreeNode)
|
|
{
|
|
XmlDocument doc = new XmlDocument();
|
|
doc.Load(xmlFile);
|
|
var found = (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode[@Name='{0}']", TreeNode));
|
|
|
|
return (found != null);
|
|
}
|
|
|
|
public static List<XmlElement> GetUniqueTreeNodes(string xmlFile)
|
|
{
|
|
XmlDocument doc = new XmlDocument();
|
|
doc.Load(xmlFile);
|
|
|
|
List<XmlElement> retElements = new List<XmlElement>();
|
|
XmlNodeList nodeList = doc.SelectNodes("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode");
|
|
foreach (var item in nodeList)
|
|
{
|
|
XmlElement itemAsElement = item as XmlElement;
|
|
if (itemAsElement != null)
|
|
{
|
|
retElements.Add(itemAsElement);
|
|
}
|
|
}
|
|
return retElements;
|
|
}
|
|
|
|
public static List<XmlElement> GetChildren(string xmlFile, string parentName)
|
|
{
|
|
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
|
|
XmlDocument doc = new XmlDocument();
|
|
doc.Load(xmlFile);
|
|
|
|
List<XmlElement> retElements = new List<XmlElement>();
|
|
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/Node[@Name='{0}']/Child", parentName));
|
|
foreach (var item in nodeList)
|
|
{
|
|
XmlElement itemAsElement = item as XmlElement;
|
|
if (itemAsElement != null)
|
|
{
|
|
retElements.Add(itemAsElement);
|
|
}
|
|
}
|
|
return retElements;
|
|
}
|
|
#> |