private static void LinkNodes(SqlMemo memo, Dictionary <SqlMemoNode, List <SqlMemoNodeIdentifier> > parentMappings) { foreach (SqlMemoNode node in parentMappings.Keys) { foreach (SqlMemoNodeIdentifier parent in parentMappings[node]) { SqlMemoNode matchingNode = memo.Groups.SelectMany(g => g.Operations).FirstOrDefault(n => n.Identifier == parent); if (matchingNode != null) { node.Parents.Add(matchingNode); } } } }
public static ReadOnlyCollection <SqlMemo> Parse(string memoText) { if (string.IsNullOrEmpty(memoText)) { return(new ReadOnlyCollection <SqlMemo>(new List <SqlMemo>())); } List <SqlMemo> memos = new List <SqlMemo>(); SqlMemo memo = null; StringBuilder sb = new StringBuilder(); using (StringReader reader = new StringReader(memoText)) { string line; int lineNumber = 0; SqlMemoGroup group = null; Dictionary <SqlMemoNode, List <SqlMemoNodeIdentifier> > parentMappings = null; while ((line = reader.ReadLine()) != null) { lineNumber++; if (line.StartsWith(_memoEndMarker)) { } else if (line.StartsWith(_initialMemoHeader) || line.StartsWith(_finalMemoHeader)) { if (memo != null) { LinkNodes(memo, parentMappings); memo.InnerText = sb.ToString(); memos.Add(memo); memo = null; sb = new StringBuilder(); } memo = new SqlMemo(); parentMappings = new Dictionary <SqlMemoNode, List <SqlMemoNodeIdentifier> >(); if (line.StartsWith(_initialMemoHeader)) { memo.Description = "Initial Memo"; } else if (line.StartsWith(_finalMemoHeader)) { memo.Description = "Final Memo"; } } else if (string.IsNullOrEmpty(line.Trim())) { // Skip } else if (line.StartsWith(" ")) { if (group != null) { sb.AppendLine(line); SqlMemoNode node = new SqlMemoNode(); int groupNumber; int operationNumber; ReadGroupNumber(ref line, group.GroupNumber, out groupNumber, out operationNumber); node.Identifier.GroupNumber = groupNumber; node.Identifier.OperationNumber = operationNumber; node.OperationName = ReadOperatorName(ref line); parentMappings.Add(node, new List <SqlMemoNodeIdentifier>()); while (ReadGroupNumber(ref line, null, out groupNumber, out operationNumber)) { SqlMemoNodeIdentifier parentIdentifier = new SqlMemoNodeIdentifier(); parentIdentifier.GroupNumber = groupNumber; parentIdentifier.OperationNumber = operationNumber; parentMappings[node].Add(parentIdentifier); } node.Arguments = line.Trim(); group.Operations.Add(node); } } else { if (memo != null) { string originalLine = line; bool isRoot = false; string rootMarker = "Root "; if (line.StartsWith(rootMarker)) { isRoot = true; line = line.Substring(rootMarker.Length); } line = line.Trim(); string groupMarkerPattern = @"^Group (?<groupNumber>\d+):(?<arguments>.*)$"; Match match = Regex.Match(line, groupMarkerPattern); if (match.Success) { string groupNumberString = match.Groups["groupNumber"].Value; string arguments = match.Groups["arguments"].Value; int groupNumber; int.TryParse(groupNumberString, out groupNumber); group = new SqlMemoGroup(); group.GroupNumber = groupNumber; group.IsRoot = isRoot; group.Arguments = arguments; memo.Groups.Add(group); sb.AppendLine(originalLine); } } } } if (memo != null) { LinkNodes(memo, parentMappings); memo.InnerText = sb.ToString(); memos.Add(memo); } } return(new ReadOnlyCollection <SqlMemo>(memos)); }