<#@ 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> TypeReverseDependencyMap = new Dictionary>()"); // 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 {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 ApplicableParents() {{ return new[] {{ \"{0}\" }}; }}", type)); List children = GetChildren(xmlFile, type); if (children.Count > 0) { WriteLine(""); WriteLine(" protected override void OnExpandPopulateFolders(IList 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 flags = new List(); 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 typesList = new List(); 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> GetReverseDependencies(string xmlFile) { Dictionary> dependencyMap = new Dictionary>(); 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 dependenciesForType; if (dependencyMap.TryGetValue(typeName, out dependenciesForType)) { dependenciesForType.Add(dependency); } else { string[] allDepedencies = dependency.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries); dependenciesForType = new List(); 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 GetUniqueTreeNodes(string xmlFile) { XmlDocument doc = new XmlDocument(); doc.Load(xmlFile); List retElements = new List(); 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 GetChildren(string xmlFile, string parentName) { XmlElement nodeElement = GetNodeElement(xmlFile, parentName); XmlDocument doc = new XmlDocument(); doc.Load(xmlFile); List retElements = new List(); 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; } #>