public TemplateScope( int nestLevel, NamedValueSet tokens, TemplateIterator iterator, int iterationStartLine, int iterationNumber) { NestLevel = nestLevel; Tokens = new NamedValueSet(tokens); Iterator = iterator; IterationStartLine = iterationStartLine; IterationNumber = iterationNumber; }
public string CommentSuffix = null; // use "-->" for XML/XSD public string[] ProcessTemplate(string[] template, TemplateIterator outerIterator) { var output = new List <string>(); var savedScopes = new Stack <TemplateScope>(); TemplateIterator currentIterator = outerIterator; int iterationStartLine = 0; int iterationNumber = 0; var currentTokens = new NamedValueSet(currentIterator.Iterations[iterationNumber].Tokens); int currentLine = 0; int nestLevel = 0; while (currentLine < template.Length) { string trimmedLine = template[currentLine].Trim(); // check for template directive bool specialLine = false; if (((CommentPrefix == null) || trimmedLine.StartsWith(CommentPrefix)) && ((CommentSuffix == null) || trimmedLine.EndsWith(CommentSuffix))) { // comment line - might have a template directive in it if (CommentPrefix != null) { trimmedLine = trimmedLine.Substring(CommentPrefix.Length); } if (CommentSuffix != null) { trimmedLine = trimmedLine.Substring(0, trimmedLine.Length - CommentSuffix.Length); } trimmedLine = trimmedLine.Trim(); if (trimmedLine.StartsWith("##")) { // directive found specialLine = true; string[] directiveParts = trimmedLine.Substring(2).Split(':'); string directive = directiveParts[0].ToLower().Trim(); switch (directive) { case "foreach": // start of for loop block // - save scope and loop { string iteratorName = directiveParts[1].Trim(); savedScopes.Push(new TemplateScope(nestLevel, currentTokens, currentIterator, iterationStartLine, iterationNumber)); iterationStartLine = currentLine; if (!currentIterator.Iterations[iterationNumber].SubIterators.ContainsKey(iteratorName)) { throw new ApplicationException( $"Unknown iterator name '{iteratorName}' in template (line {currentLine})."); } currentIterator = currentIterator.Iterations[iterationNumber].SubIterators[iteratorName]; // 1st iteration at new level nestLevel++; iterationNumber = 0; currentTokens.Add(currentIterator.Iterations[iterationNumber].Tokens); } break; case "end": // end of block - exit or loop if ((currentIterator != null) && ((iterationNumber + 1) < currentIterator.Iterations.Length)) { // restart loop currentLine = iterationStartLine; iterationNumber++; currentTokens.Add(currentIterator.Iterations[iterationNumber].Tokens); } else { // pop scope TemplateScope oldScope = savedScopes.Pop(); nestLevel = oldScope.NestLevel; currentTokens = oldScope.Tokens; currentIterator = oldScope.Iterator; iterationStartLine = oldScope.IterationStartLine; iterationNumber = oldScope.IterationNumber; } break; default: throw new ApplicationException( $"Unknown directive '{directive}' in template (line {currentLine})."); } } } if (!specialLine) { // ordinary input line currentTokens.Set("SourceLine", currentLine); currentTokens.Set("OutputLine", output.Count); currentTokens.Set("NestLevel", nestLevel); output.Add(currentTokens.ReplaceTokens(template[currentLine])); } currentLine++; } if (savedScopes.Count > 0) { throw new ApplicationException("Not enough matching ##end directives in template!"); } return(output.ToArray()); }
static void Main(string[] args) { Console.WriteLine("FpMLCodeListTool: Starting..."); var outerIterator = new TemplateIterator(1); outerIterator.Iterations[0].Tokens.Set("NameSpace", "FpML.V5r10.Codes"); outerIterator.Iterations[0].Tokens.Set("ToolTitle", "TemplateProcessor"); outerIterator.Iterations[0].Tokens.Set("ToolVersion", "1.1.0.0"); Console.WriteLine("FpMLCodeListTool: Parsing code lists..."); string[] xmlFiles = Directory.GetFiles(@"..\..\..\..\FpML.V5r10\fpml.org\download\codelist", "*.xml", SearchOption.AllDirectories); var classIterator = new TemplateIterator(xmlFiles.Length); outerIterator.Iterations[0].SubIterators["ClassDef"] = classIterator; int fileNum = 0; foreach (string xmlFile in xmlFiles) { try { //Console.WriteLine("FpMLCodeListTool: Parsing '{0}' ...", xmlFile); var data = XmlSerializerHelper.DeserializeFromFile <CodeListDocument>(xmlFile); string classDefName = GetClassDefName(data.Identification.ShortName); // determine primary key string primaryKey = null; foreach (Key key in data.ColumnSet.Key) { if (key.Id == "PrimaryKey") { if (primaryKey != null) { throw new ApplicationException("PrimaryKey defined more than once!"); } primaryKey = key.ColumnRef[0].Ref; } } if (primaryKey == null) { throw new ApplicationException("PrimaryKey is not defined!"); } classIterator.Iterations[fileNum].Tokens.Set("ClassDef", classDefName); classIterator.Iterations[fileNum].Tokens.Set("PrimaryKey", primaryKey); classIterator.Iterations[fileNum].Tokens.Set("ClassDefDataFile", Path.GetFileNameWithoutExtension(xmlFile)); // subiterator - column (field) definitions var fieldIterator = new TemplateIterator(data.ColumnSet.Column.Length); classIterator.Iterations[fileNum].SubIterators["FieldDef"] = fieldIterator; int colNum = 0; foreach (Column col in data.ColumnSet.Column) { fieldIterator.Iterations[colNum].Tokens.Set("ColumnNum", colNum); fieldIterator.Iterations[colNum].Tokens.Set("ColumnName", col.ShortName); fieldIterator.Iterations[colNum].Tokens.Set("XSDataType", col.Data.Type); // next column colNum++; } // subiterator - row (primary key/enum) definitions var valueIterator = new TemplateIterator(data.SimpleCodeList.Row.Length); classIterator.Iterations[fileNum].SubIterators["ValueDef"] = valueIterator; int rowNum = 0; foreach (Row row in data.SimpleCodeList.Row) { valueIterator.Iterations[rowNum].Tokens.Set("RowNum", rowNum + 1); // note: 0 = Undefined string value = row.Value[0].SimpleValue.Value; valueIterator.Iterations[rowNum].Tokens.Set("RowName", value); string enumName = EnumHelper.ToEnumId(value); valueIterator.Iterations[rowNum].Tokens.Set("RowEnum", enumName); //valueIterator.Iterations[rowNum].Tokens.Set("XSDataType", row.Data.Type); // next row rowNum++; } } catch (Exception excp) { Console.Error.WriteLine("FpMLCodeListTool: Parse '{0}' failed: {1}", xmlFile, excp); } // next file fileNum++; } // write XML schema definitions Console.WriteLine("FpMLCodeListTool: Writing schema definition..."); { const string templateFileName = "TemplateCodeList.txt"; outerIterator.Iterations[0].Tokens.Set("TemplateFile", templateFileName); string text = ResourceHelper.GetResourceWithPartialName(Assembly.GetExecutingAssembly(), templateFileName); string[] input = text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var tp = new TemplateProcessor { CommentPrefix = "<!--", CommentSuffix = "-->" }; string[] output = tp.ProcessTemplate(input, outerIterator); using (StreamWriter f = File.CreateText("FpMLCodes.xsd")) { foreach (string line in output) { f.WriteLine(line); } f.Flush(); } } // write class extensions Console.WriteLine("FpMLCodeListTool: Writing class extensions..."); { const string templateFileName = "TemplateExtensions.txt"; outerIterator.Iterations[0].Tokens.Set("TemplateFile", templateFileName); string text = ResourceHelper.GetResourceWithPartialName(Assembly.GetExecutingAssembly(), templateFileName); string[] input = text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var tp = new TemplateProcessor { CommentPrefix = "//", CommentSuffix = null }; string[] output = tp.ProcessTemplate(input, outerIterator); using (StreamWriter f = File.CreateText("FpMLCodesExt.cs")) { foreach (string line in output) { f.WriteLine(line); } f.Flush(); } } Console.WriteLine("FpMLCodeListTool: Complete."); }